]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/texmanip.cpp
uncrustify! now the code is only ugly on the *inside*
[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 "stdafx.h"
33 #include "str.h"
34
35 static byte *row1 = NULL, *row2 = NULL;
36 static int rowsize = 0;
37
38 void R_ResampleTextureLerpLine( byte *in, byte *out, int inwidth, int outwidth, int bytesperpixel ){
39         int j, xi, oldx = 0, f, fstep, endx, lerp;
40 #define LERPBYTE( i ) out[i] = (byte) ( ( ( ( row2[i] - row1[i] ) * lerp ) >> 16 ) + row1[i] )
41
42         fstep = (int) ( inwidth * 65536.0f / outwidth );
43         endx = ( inwidth - 1 );
44         if ( bytesperpixel == 4 ) {
45                 for ( j = 0,f = 0; j < outwidth; j++, f += fstep )
46                 {
47                         xi = f >> 16;
48                         if ( xi != oldx ) {
49                                 in += ( xi - oldx ) * 4;
50                                 oldx = xi;
51                         }
52
53                         if ( xi < endx ) {
54                                 lerp = f & 0xFFFF;
55                                 *out++ = (byte) ( ( ( ( in[4] - in[0] ) * lerp ) >> 16 ) + in[0] );
56                                 *out++ = (byte) ( ( ( ( in[5] - in[1] ) * lerp ) >> 16 ) + in[1] );
57                                 *out++ = (byte) ( ( ( ( in[6] - in[2] ) * lerp ) >> 16 ) + in[2] );
58                                 *out++ = (byte) ( ( ( ( in[7] - in[3] ) * lerp ) >> 16 ) + in[3] );
59                         }
60                         else // last pixel of the line has no pixel to lerp to
61                         {
62                                 *out++ = in[0];
63                                 *out++ = in[1];
64                                 *out++ = in[2];
65                                 *out++ = in[3];
66                         }
67                 }
68         }
69         else if ( bytesperpixel == 3 ) {
70                 for ( j = 0, f = 0; j < outwidth; j++, f += fstep )
71                 {
72                         xi = f >> 16;
73                         if ( xi != oldx ) {
74                                 in += ( xi - oldx ) * 3;
75                                 oldx = xi;
76                         }
77
78                         if ( xi < endx ) {
79                                 lerp = f & 0xFFFF;
80                                 *out++ = (byte) ( ( ( ( in[3] - in[0] ) * lerp ) >> 16 ) + in[0] );
81                                 *out++ = (byte) ( ( ( ( in[4] - in[1] ) * lerp ) >> 16 ) + in[1] );
82                                 *out++ = (byte) ( ( ( ( in[5] - in[2] ) * lerp ) >> 16 ) + in[2] );
83                         }
84                         else // last pixel of the line has no pixel to lerp to
85                         {
86                                 *out++ = in[0];
87                                 *out++ = in[1];
88                                 *out++ = in[2];
89                         }
90                 }
91         }
92         else{
93                 Sys_Printf( "R_ResampleTextureLerpLine: unsupported bytesperpixel %i\n", bytesperpixel );
94         }
95 }
96
97 /*
98    ================
99    R_ResampleTexture
100    ================
101  */
102 void R_ResampleTexture( void *indata, int inwidth, int inheight, void *outdata,  int outwidth, int outheight, int bytesperpixel ){
103         if ( rowsize < outwidth * bytesperpixel ) {
104                 if ( row1 ) {
105                         free( row1 );
106                 }
107                 if ( row2 ) {
108                         free( row2 );
109                 }
110
111                 rowsize = outwidth * bytesperpixel;
112                 row1 = (byte *)malloc( rowsize );
113                 row2 = (byte *)malloc( rowsize );
114         }
115
116         if ( bytesperpixel == 4 ) {
117                 int i, j, yi, oldy, f, fstep, lerp, endy = ( inheight - 1 ), inwidth4 = inwidth * 4, outwidth4 = outwidth * 4;
118                 byte    *inrow, *out;
119                 out = (byte *)outdata;
120                 fstep = (int) ( inheight * 65536.0f / outheight );
121 #define LERPBYTE( i ) out[i] = (byte) ( ( ( ( row2[i] - row1[i] ) * lerp ) >> 16 ) + row1[i] )
122
123                 inrow = (byte *)indata;
124                 oldy = 0;
125                 R_ResampleTextureLerpLine( inrow, row1, inwidth, outwidth, bytesperpixel );
126                 R_ResampleTextureLerpLine( inrow + inwidth4, row2, inwidth, outwidth, bytesperpixel );
127
128                 for ( i = 0, f = 0; i < outheight; i++,f += fstep )
129                 {
130                         yi = f >> 16;
131                         if ( yi < endy ) {
132                                 lerp = f & 0xFFFF;
133                                 if ( yi != oldy ) {
134                                         inrow = (byte *)indata + inwidth4 * yi;
135                                         if ( yi == oldy + 1 ) {
136                                                 memcpy( row1, row2, outwidth4 );
137                                         }
138                                         else{
139                                                 R_ResampleTextureLerpLine( inrow, row1, inwidth, outwidth, bytesperpixel );
140                                         }
141
142                                         R_ResampleTextureLerpLine( inrow + inwidth4, row2, inwidth, outwidth, bytesperpixel );
143                                         oldy = yi;
144                                 }
145                                 j = outwidth - 4;
146                                 while ( j >= 0 )
147                                 {
148                                         LERPBYTE( 0 );
149                                         LERPBYTE( 1 );
150                                         LERPBYTE( 2 );
151                                         LERPBYTE( 3 );
152                                         LERPBYTE( 4 );
153                                         LERPBYTE( 5 );
154                                         LERPBYTE( 6 );
155                                         LERPBYTE( 7 );
156                                         LERPBYTE( 8 );
157                                         LERPBYTE( 9 );
158                                         LERPBYTE( 10 );
159                                         LERPBYTE( 11 );
160                                         LERPBYTE( 12 );
161                                         LERPBYTE( 13 );
162                                         LERPBYTE( 14 );
163                                         LERPBYTE( 15 );
164                                         out += 16;
165                                         row1 += 16;
166                                         row2 += 16;
167                                         j -= 4;
168                                 }
169                                 if ( j & 2 ) {
170                                         LERPBYTE( 0 );
171                                         LERPBYTE( 1 );
172                                         LERPBYTE( 2 );
173                                         LERPBYTE( 3 );
174                                         LERPBYTE( 4 );
175                                         LERPBYTE( 5 );
176                                         LERPBYTE( 6 );
177                                         LERPBYTE( 7 );
178                                         out += 8;
179                                         row1 += 8;
180                                         row2 += 8;
181                                 }
182                                 if ( j & 1 ) {
183                                         LERPBYTE( 0 );
184                                         LERPBYTE( 1 );
185                                         LERPBYTE( 2 );
186                                         LERPBYTE( 3 );
187                                         out += 4;
188                                         row1 += 4;
189                                         row2 += 4;
190                                 }
191                                 row1 -= outwidth4;
192                                 row2 -= outwidth4;
193                         }
194                         else
195                         {
196                                 if ( yi != oldy ) {
197                                         inrow = (byte *)indata + inwidth4 * yi;
198                                         if ( yi == oldy + 1 ) {
199                                                 memcpy( row1, row2, outwidth4 );
200                                         }
201                                         else{
202                                                 R_ResampleTextureLerpLine( inrow, row1, inwidth, outwidth, bytesperpixel );
203                                         }
204
205                                         oldy = yi;
206                                 }
207                                 memcpy( out, row1, outwidth4 );
208                         }
209                 }
210         }
211         else if ( bytesperpixel == 3 ) {
212                 int i, j, yi, oldy, f, fstep, lerp, endy = ( inheight - 1 ), inwidth3 = inwidth * 3, outwidth3 = outwidth * 3;
213                 byte    *inrow, *out;
214                 out = (byte *)outdata;
215                 fstep = (int) ( inheight * 65536.0f / outheight );
216 #define LERPBYTE( i ) out[i] = (byte) ( ( ( ( row2[i] - row1[i] ) * lerp ) >> 16 ) + row1[i] )
217
218                 inrow = (byte *)indata;
219                 oldy = 0;
220                 R_ResampleTextureLerpLine( inrow, row1, inwidth, outwidth, bytesperpixel );
221                 R_ResampleTextureLerpLine( inrow + inwidth3, row2, inwidth, outwidth, bytesperpixel );
222                 for ( i = 0, f = 0; i < outheight; i++,f += fstep )
223                 {
224                         yi = f >> 16;
225                         if ( yi < endy ) {
226                                 lerp = f & 0xFFFF;
227                                 if ( yi != oldy ) {
228                                         inrow = (byte *)indata + inwidth3 * yi;
229                                         if ( yi == oldy + 1 ) {
230                                                 memcpy( row1, row2, outwidth3 );
231                                         }
232                                         else{
233                                                 R_ResampleTextureLerpLine( inrow, row1, inwidth, outwidth, bytesperpixel );
234                                         }
235
236                                         R_ResampleTextureLerpLine( inrow + inwidth3, row2, inwidth, outwidth, bytesperpixel );
237                                         oldy = yi;
238                                 }
239                                 j = outwidth - 4;
240                                 while ( j >= 0 )
241                                 {
242                                         LERPBYTE( 0 );
243                                         LERPBYTE( 1 );
244                                         LERPBYTE( 2 );
245                                         LERPBYTE( 3 );
246                                         LERPBYTE( 4 );
247                                         LERPBYTE( 5 );
248                                         LERPBYTE( 6 );
249                                         LERPBYTE( 7 );
250                                         LERPBYTE( 8 );
251                                         LERPBYTE( 9 );
252                                         LERPBYTE( 10 );
253                                         LERPBYTE( 11 );
254                                         out += 12;
255                                         row1 += 12;
256                                         row2 += 12;
257                                         j -= 4;
258                                 }
259                                 if ( j & 2 ) {
260                                         LERPBYTE( 0 );
261                                         LERPBYTE( 1 );
262                                         LERPBYTE( 2 );
263                                         LERPBYTE( 3 );
264                                         LERPBYTE( 4 );
265                                         LERPBYTE( 5 );
266                                         out += 6;
267                                         row1 += 6;
268                                         row2 += 6;
269                                 }
270                                 if ( j & 1 ) {
271                                         LERPBYTE( 0 );
272                                         LERPBYTE( 1 );
273                                         LERPBYTE( 2 );
274                                         out += 3;
275                                         row1 += 3;
276                                         row2 += 3;
277                                 }
278                                 row1 -= outwidth3;
279                                 row2 -= outwidth3;
280                         }
281                         else
282                         {
283                                 if ( yi != oldy ) {
284                                         inrow = (byte *)indata + inwidth3 * yi;
285                                         if ( yi == oldy + 1 ) {
286                                                 memcpy( row1, row2, outwidth3 );
287                                         }
288                                         else{
289                                                 R_ResampleTextureLerpLine( inrow, row1, inwidth, outwidth, bytesperpixel );
290                                         }
291
292                                         oldy = yi;
293                                 }
294                                 memcpy( out, row1, outwidth3 );
295                         }
296                 }
297         }
298         else{
299                 Sys_Printf( "R_ResampleTexture: unsupported bytesperpixel %i\n", bytesperpixel );
300         }
301 }
302
303 // in can be the same as out
304 void GL_MipReduce( byte *in, byte *out, int width, int height, int destwidth, int destheight ){
305         int x, y, width2, height2, nextrow;
306         if ( width > destwidth ) {
307                 if ( height > destheight ) {
308                         // reduce both
309                         width2 = width >> 1;
310                         height2 = height >> 1;
311                         nextrow = width << 2;
312                         for ( y = 0; y < height2; y++ )
313                         {
314                                 for ( x = 0; x < width2; x++ )
315                                 {
316                                         out[0] = (byte) ( ( in[0] + in[4] + in[nextrow  ] + in[nextrow + 4] ) >> 2 );
317                                         out[1] = (byte) ( ( in[1] + in[5] + in[nextrow + 1] + in[nextrow + 5] ) >> 2 );
318                                         out[2] = (byte) ( ( in[2] + in[6] + in[nextrow + 2] + in[nextrow + 6] ) >> 2 );
319                                         out[3] = (byte) ( ( in[3] + in[7] + in[nextrow + 3] + in[nextrow + 7] ) >> 2 );
320                                         out += 4;
321                                         in += 8;
322                                 }
323                                 in += nextrow; // skip a line
324                         }
325                 }
326                 else
327                 {
328                         // reduce width
329                         width2 = width >> 1;
330                         for ( y = 0; y < height; y++ )
331                         {
332                                 for ( x = 0; x < width2; x++ )
333                                 {
334                                         out[0] = (byte) ( ( in[0] + in[4] ) >> 1 );
335                                         out[1] = (byte) ( ( in[1] + in[5] ) >> 1 );
336                                         out[2] = (byte) ( ( in[2] + in[6] ) >> 1 );
337                                         out[3] = (byte) ( ( in[3] + in[7] ) >> 1 );
338                                         out += 4;
339                                         in += 8;
340                                 }
341                         }
342                 }
343         }
344         else
345         {
346                 if ( height > destheight ) {
347                         // reduce height
348                         height2 = height >> 1;
349                         nextrow = width << 2;
350                         for ( y = 0; y < height2; y++ )
351                         {
352                                 for ( x = 0; x < width; x++ )
353                                 {
354                                         out[0] = (byte) ( ( in[0] + in[nextrow  ] ) >> 1 );
355                                         out[1] = (byte) ( ( in[1] + in[nextrow + 1] ) >> 1 );
356                                         out[2] = (byte) ( ( in[2] + in[nextrow + 2] ) >> 1 );
357                                         out[3] = (byte) ( ( in[3] + in[nextrow + 3] ) >> 1 );
358                                         out += 4;
359                                         in += 4;
360                                 }
361                                 in += nextrow; // skip a line
362                         }
363                 }
364                 else{
365                         Sys_Printf( "GL_MipReduce: desired size already achieved\n" );
366                 }
367         }
368 }