]> git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/texmanip.cpp
Merge branch 'illwieckz/files'
[xonotic/netradiant.git] / radiant / texmanip.cpp
1 /*
2    Copyright (c) 2002 Forest "LordHavoc" Hale
3
4    All rights reserved.
5
6    Redistribution and use in source and binary forms, with or without modification,
7    are permitted provided that the following conditions are met:
8
9    Redistributions of source code must retain the above copyright notice, this list
10    of conditions and the following disclaimer.
11
12    Redistributions in binary form must reproduce the above copyright notice, this
13    list of conditions and the following disclaimer in the documentation and/or
14    other materials provided with the distribution.
15
16    Neither the name of Forest Hale nor the names of other contributors may be used
17    to endorse or promote products derived from this software without specific prior
18    written permission.
19
20    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
21    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23    DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
24    DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
27    ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #include "texmanip.h"
33
34 #include <stdlib.h>
35 #include "stream/textstream.h"
36
37 static byte *row1 = NULL, *row2 = NULL;
38 static int rowsize = 0;
39
40 void R_ResampleTextureLerpLine( const byte *in, byte *out, int inwidth, int outwidth, int bytesperpixel ){
41         int j, xi, oldx = 0, f, fstep, endx, lerp;
42 #define LERPBYTE( i ) out[i] = (byte) ( ( ( ( row2[i] - row1[i] ) * lerp ) >> 16 ) + row1[i] )
43
44         fstep = (int) ( inwidth * 65536.0f / outwidth );
45         endx = ( inwidth - 1 );
46         if ( bytesperpixel == 4 ) {
47                 for ( j = 0,f = 0; j < outwidth; j++, f += fstep )
48                 {
49                         xi = f >> 16;
50                         if ( xi != oldx ) {
51                                 in += ( xi - oldx ) * 4;
52                                 oldx = xi;
53                         }
54
55                         if ( xi < endx ) {
56                                 lerp = f & 0xFFFF;
57                                 *out++ = (byte) ( ( ( ( in[4] - in[0] ) * lerp ) >> 16 ) + in[0] );
58                                 *out++ = (byte) ( ( ( ( in[5] - in[1] ) * lerp ) >> 16 ) + in[1] );
59                                 *out++ = (byte) ( ( ( ( in[6] - in[2] ) * lerp ) >> 16 ) + in[2] );
60                                 *out++ = (byte) ( ( ( ( in[7] - in[3] ) * lerp ) >> 16 ) + in[3] );
61                         }
62                         else // last pixel of the line has no pixel to lerp to
63                         {
64                                 *out++ = in[0];
65                                 *out++ = in[1];
66                                 *out++ = in[2];
67                                 *out++ = in[3];
68                         }
69                 }
70         }
71         else if ( bytesperpixel == 3 ) {
72                 for ( j = 0, f = 0; j < outwidth; j++, f += fstep )
73                 {
74                         xi = f >> 16;
75                         if ( xi != oldx ) {
76                                 in += ( xi - oldx ) * 3;
77                                 oldx = xi;
78                         }
79
80                         if ( xi < endx ) {
81                                 lerp = f & 0xFFFF;
82                                 *out++ = (byte) ( ( ( ( in[3] - in[0] ) * lerp ) >> 16 ) + in[0] );
83                                 *out++ = (byte) ( ( ( ( in[4] - in[1] ) * lerp ) >> 16 ) + in[1] );
84                                 *out++ = (byte) ( ( ( ( in[5] - in[2] ) * lerp ) >> 16 ) + in[2] );
85                         }
86                         else // last pixel of the line has no pixel to lerp to
87                         {
88                                 *out++ = in[0];
89                                 *out++ = in[1];
90                                 *out++ = in[2];
91                         }
92                 }
93         }
94         else
95         {
96                 globalOutputStream() << "R_ResampleTextureLerpLine: unsupported bytesperpixel " << bytesperpixel << "\n";
97         }
98 }
99
100 /*
101    ================
102    R_ResampleTexture
103    ================
104  */
105 void R_ResampleTexture( const void *indata, int inwidth, int inheight, void *outdata,  int outwidth, int outheight, int bytesperpixel ){
106         if ( rowsize < outwidth * bytesperpixel ) {
107                 if ( row1 ) {
108                         free( row1 );
109                 }
110                 if ( row2 ) {
111                         free( row2 );
112                 }
113
114                 rowsize = outwidth * bytesperpixel;
115                 row1 = (byte *)malloc( rowsize );
116                 row2 = (byte *)malloc( rowsize );
117         }
118
119         if ( bytesperpixel == 4 ) {
120                 int i, j, yi, oldy, f, fstep, lerp, endy = ( inheight - 1 ), inwidth4 = inwidth * 4, outwidth4 = outwidth * 4;
121                 byte *inrow, *out;
122                 out = (byte *)outdata;
123                 fstep = (int) ( inheight * 65536.0f / outheight );
124 #define LERPBYTE( i ) out[i] = (byte) ( ( ( ( row2[i] - row1[i] ) * lerp ) >> 16 ) + row1[i] )
125
126                 inrow = (byte *)indata;
127                 oldy = 0;
128                 R_ResampleTextureLerpLine( inrow, row1, inwidth, outwidth, bytesperpixel );
129                 R_ResampleTextureLerpLine( inrow + inwidth4, row2, inwidth, outwidth, bytesperpixel );
130
131                 for ( i = 0, f = 0; i < outheight; i++,f += fstep )
132                 {
133                         yi = f >> 16;
134                         if ( yi < endy ) {
135                                 lerp = f & 0xFFFF;
136                                 if ( yi != oldy ) {
137                                         inrow = (byte *)indata + inwidth4 * yi;
138                                         if ( yi == oldy + 1 ) {
139                                                 memcpy( row1, row2, outwidth4 );
140                                         }
141                                         else{
142                                                 R_ResampleTextureLerpLine( inrow, row1, inwidth, outwidth, bytesperpixel );
143                                         }
144
145                                         R_ResampleTextureLerpLine( inrow + inwidth4, row2, inwidth, outwidth, bytesperpixel );
146                                         oldy = yi;
147                                 }
148                                 j = outwidth - 4;
149                                 while ( j >= 0 )
150                                 {
151                                         LERPBYTE( 0 );
152                                         LERPBYTE( 1 );
153                                         LERPBYTE( 2 );
154                                         LERPBYTE( 3 );
155                                         LERPBYTE( 4 );
156                                         LERPBYTE( 5 );
157                                         LERPBYTE( 6 );
158                                         LERPBYTE( 7 );
159                                         LERPBYTE( 8 );
160                                         LERPBYTE( 9 );
161                                         LERPBYTE( 10 );
162                                         LERPBYTE( 11 );
163                                         LERPBYTE( 12 );
164                                         LERPBYTE( 13 );
165                                         LERPBYTE( 14 );
166                                         LERPBYTE( 15 );
167                                         out += 16;
168                                         row1 += 16;
169                                         row2 += 16;
170                                         j -= 4;
171                                 }
172                                 if ( j & 2 ) {
173                                         LERPBYTE( 0 );
174                                         LERPBYTE( 1 );
175                                         LERPBYTE( 2 );
176                                         LERPBYTE( 3 );
177                                         LERPBYTE( 4 );
178                                         LERPBYTE( 5 );
179                                         LERPBYTE( 6 );
180                                         LERPBYTE( 7 );
181                                         out += 8;
182                                         row1 += 8;
183                                         row2 += 8;
184                                 }
185                                 if ( j & 1 ) {
186                                         LERPBYTE( 0 );
187                                         LERPBYTE( 1 );
188                                         LERPBYTE( 2 );
189                                         LERPBYTE( 3 );
190                                         out += 4;
191                                         row1 += 4;
192                                         row2 += 4;
193                                 }
194                                 row1 -= outwidth4;
195                                 row2 -= outwidth4;
196                         }
197                         else
198                         {
199                                 if ( yi != oldy ) {
200                                         inrow = (byte *)indata + inwidth4 * yi;
201                                         if ( yi == oldy + 1 ) {
202                                                 memcpy( row1, row2, outwidth4 );
203                                         }
204                                         else{
205                                                 R_ResampleTextureLerpLine( inrow, row1, inwidth, outwidth, bytesperpixel );
206                                         }
207
208                                         oldy = yi;
209                                 }
210                                 memcpy( out, row1, outwidth4 );
211                         }
212                 }
213         }
214         else if ( bytesperpixel == 3 ) {
215                 int i, j, yi, oldy, f, fstep, lerp, endy = ( inheight - 1 ), inwidth3 = inwidth * 3, outwidth3 = outwidth * 3;
216                 byte *inrow, *out;
217                 out = (byte *)outdata;
218                 fstep = (int) ( inheight * 65536.0f / outheight );
219 #define LERPBYTE( i ) out[i] = (byte) ( ( ( ( row2[i] - row1[i] ) * lerp ) >> 16 ) + row1[i] )
220
221                 inrow = (byte *)indata;
222                 oldy = 0;
223                 R_ResampleTextureLerpLine( inrow, row1, inwidth, outwidth, bytesperpixel );
224                 R_ResampleTextureLerpLine( inrow + inwidth3, row2, inwidth, outwidth, bytesperpixel );
225                 for ( i = 0, f = 0; i < outheight; i++,f += fstep )
226                 {
227                         yi = f >> 16;
228                         if ( yi < endy ) {
229                                 lerp = f & 0xFFFF;
230                                 if ( yi != oldy ) {
231                                         inrow = (byte *)indata + inwidth3 * yi;
232                                         if ( yi == oldy + 1 ) {
233                                                 memcpy( row1, row2, outwidth3 );
234                                         }
235                                         else{
236                                                 R_ResampleTextureLerpLine( inrow, row1, inwidth, outwidth, bytesperpixel );
237                                         }
238
239                                         R_ResampleTextureLerpLine( inrow + inwidth3, row2, inwidth, outwidth, bytesperpixel );
240                                         oldy = yi;
241                                 }
242                                 j = outwidth - 4;
243                                 while ( j >= 0 )
244                                 {
245                                         LERPBYTE( 0 );
246                                         LERPBYTE( 1 );
247                                         LERPBYTE( 2 );
248                                         LERPBYTE( 3 );
249                                         LERPBYTE( 4 );
250                                         LERPBYTE( 5 );
251                                         LERPBYTE( 6 );
252                                         LERPBYTE( 7 );
253                                         LERPBYTE( 8 );
254                                         LERPBYTE( 9 );
255                                         LERPBYTE( 10 );
256                                         LERPBYTE( 11 );
257                                         out += 12;
258                                         row1 += 12;
259                                         row2 += 12;
260                                         j -= 4;
261                                 }
262                                 if ( j & 2 ) {
263                                         LERPBYTE( 0 );
264                                         LERPBYTE( 1 );
265                                         LERPBYTE( 2 );
266                                         LERPBYTE( 3 );
267                                         LERPBYTE( 4 );
268                                         LERPBYTE( 5 );
269                                         out += 6;
270                                         row1 += 6;
271                                         row2 += 6;
272                                 }
273                                 if ( j & 1 ) {
274                                         LERPBYTE( 0 );
275                                         LERPBYTE( 1 );
276                                         LERPBYTE( 2 );
277                                         out += 3;
278                                         row1 += 3;
279                                         row2 += 3;
280                                 }
281                                 row1 -= outwidth3;
282                                 row2 -= outwidth3;
283                         }
284                         else
285                         {
286                                 if ( yi != oldy ) {
287                                         inrow = (byte *)indata + inwidth3 * yi;
288                                         if ( yi == oldy + 1 ) {
289                                                 memcpy( row1, row2, outwidth3 );
290                                         }
291                                         else{
292                                                 R_ResampleTextureLerpLine( inrow, row1, inwidth, outwidth, bytesperpixel );
293                                         }
294
295                                         oldy = yi;
296                                 }
297                                 memcpy( out, row1, outwidth3 );
298                         }
299                 }
300         }
301         else
302         {
303                 globalOutputStream() << "R_ResampleTexture: unsupported bytesperpixel " << bytesperpixel << "\n";
304         }
305 }
306
307 // in can be the same as out
308 void GL_MipReduce( byte *in, byte *out, int width, int height, int destwidth, int destheight ){
309         int x, y, width2, height2, nextrow;
310         if ( width > destwidth ) {
311                 if ( height > destheight ) {
312                         // reduce both
313                         width2 = width >> 1;
314                         height2 = height >> 1;
315                         nextrow = width << 2;
316                         for ( y = 0; y < height2; y++ )
317                         {
318                                 for ( x = 0; x < width2; x++ )
319                                 {
320                                         out[0] = (byte) ( ( in[0] + in[4] + in[nextrow  ] + in[nextrow + 4] ) >> 2 );
321                                         out[1] = (byte) ( ( in[1] + in[5] + in[nextrow + 1] + in[nextrow + 5] ) >> 2 );
322                                         out[2] = (byte) ( ( in[2] + in[6] + in[nextrow + 2] + in[nextrow + 6] ) >> 2 );
323                                         out[3] = (byte) ( ( in[3] + in[7] + in[nextrow + 3] + in[nextrow + 7] ) >> 2 );
324                                         out += 4;
325                                         in += 8;
326                                 }
327                                 in += nextrow; // skip a line
328                         }
329                 }
330                 else
331                 {
332                         // reduce width
333                         width2 = width >> 1;
334                         for ( y = 0; y < height; y++ )
335                         {
336                                 for ( x = 0; x < width2; x++ )
337                                 {
338                                         out[0] = (byte) ( ( in[0] + in[4] ) >> 1 );
339                                         out[1] = (byte) ( ( in[1] + in[5] ) >> 1 );
340                                         out[2] = (byte) ( ( in[2] + in[6] ) >> 1 );
341                                         out[3] = (byte) ( ( in[3] + in[7] ) >> 1 );
342                                         out += 4;
343                                         in += 8;
344                                 }
345                         }
346                 }
347         }
348         else
349         {
350                 if ( height > destheight ) {
351                         // reduce height
352                         height2 = height >> 1;
353                         nextrow = width << 2;
354                         for ( y = 0; y < height2; y++ )
355                         {
356                                 for ( x = 0; x < width; x++ )
357                                 {
358                                         out[0] = (byte) ( ( in[0] + in[nextrow  ] ) >> 1 );
359                                         out[1] = (byte) ( ( in[1] + in[nextrow + 1] ) >> 1 );
360                                         out[2] = (byte) ( ( in[2] + in[nextrow + 2] ) >> 1 );
361                                         out[3] = (byte) ( ( in[3] + in[nextrow + 3] ) >> 1 );
362                                         out += 4;
363                                         in += 4;
364                                 }
365                                 in += nextrow; // skip a line
366                         }
367                 }
368                 else
369                 {
370                         globalOutputStream() << "GL_MipReduce: desired size already achieved\n";
371                 }
372         }
373 }