2 Copyright (c) 2002 Forest "LordHavoc" Hale
6 Redistribution and use in source and binary forms, with or without modification,
7 are permitted provided that the following conditions are met:
9 Redistributions of source code must retain the above copyright notice, this list
10 of conditions and the following disclaimer.
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.
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
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.
35 #include "stream/textstream.h"
37 static byte *row1 = NULL, *row2 = NULL;
38 static int rowsize = 0;
40 void R_ResampleTextureLerpLine (const byte *in, byte *out, int inwidth, int outwidth, int bytesperpixel)
42 int j, xi, oldx = 0, f, fstep, endx, lerp;
43 #define LERPBYTE(i) out[i] = (byte) ((((row2[i] - row1[i]) * lerp) >> 16) + row1[i])
45 fstep = (int) (inwidth * 65536.0f / outwidth);
47 if (bytesperpixel == 4)
49 for (j = 0,f = 0;j < outwidth;j++, f += fstep)
54 in += (xi - oldx) * 4;
61 *out++ = (byte) ((((in[4] - in[0]) * lerp) >> 16) + in[0]);
62 *out++ = (byte) ((((in[5] - in[1]) * lerp) >> 16) + in[1]);
63 *out++ = (byte) ((((in[6] - in[2]) * lerp) >> 16) + in[2]);
64 *out++ = (byte) ((((in[7] - in[3]) * lerp) >> 16) + in[3]);
66 else // last pixel of the line has no pixel to lerp to
75 else if (bytesperpixel == 3)
77 for (j = 0, f = 0; j < outwidth; j++, f += fstep)
82 in += (xi - oldx) * 3;
89 *out++ = (byte) ((((in[3] - in[0]) * lerp) >> 16) + in[0]);
90 *out++ = (byte) ((((in[4] - in[1]) * lerp) >> 16) + in[1]);
91 *out++ = (byte) ((((in[5] - in[2]) * lerp) >> 16) + in[2]);
93 else // last pixel of the line has no pixel to lerp to
103 globalOutputStream() << "R_ResampleTextureLerpLine: unsupported bytesperpixel " << bytesperpixel << "\n";
112 void R_ResampleTexture (const void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight, int bytesperpixel)
114 if (rowsize < outwidth * bytesperpixel)
121 rowsize = outwidth * bytesperpixel;
122 row1 = (byte *)malloc(rowsize);
123 row2 = (byte *)malloc(rowsize);
126 if (bytesperpixel == 4)
128 int i, j, yi, oldy, f, fstep, lerp, endy = (inheight-1), inwidth4 = inwidth*4, outwidth4 = outwidth*4;
130 out = (byte *)outdata;
131 fstep = (int) (inheight * 65536.0f / outheight);
132 #define LERPBYTE(i) out[i] = (byte) ((((row2[i] - row1[i]) * lerp) >> 16) + row1[i])
134 inrow = (byte *)indata;
136 R_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth, bytesperpixel);
137 R_ResampleTextureLerpLine (inrow + inwidth4, row2, inwidth, outwidth, bytesperpixel);
139 for (i = 0, f = 0;i < outheight;i++,f += fstep)
147 inrow = (byte *)indata + inwidth4 * yi;
149 memcpy(row1, row2, outwidth4);
151 R_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth, bytesperpixel);
153 R_ResampleTextureLerpLine (inrow + inwidth4, row2, inwidth, outwidth, bytesperpixel);
211 inrow = (byte *)indata + inwidth4*yi;
213 memcpy(row1, row2, outwidth4);
215 R_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth, bytesperpixel);
219 memcpy(out, row1, outwidth4);
223 else if (bytesperpixel == 3)
225 int i, j, yi, oldy, f, fstep, lerp, endy = (inheight-1), inwidth3 = inwidth * 3, outwidth3 = outwidth * 3;
227 out = (byte *)outdata;
228 fstep = (int) (inheight*65536.0f/outheight);
229 #define LERPBYTE(i) out[i] = (byte) ((((row2[i] - row1[i]) * lerp) >> 16) + row1[i])
231 inrow = (byte *)indata;
233 R_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth, bytesperpixel);
234 R_ResampleTextureLerpLine (inrow + inwidth3, row2, inwidth, outwidth, bytesperpixel);
235 for (i = 0, f = 0;i < outheight;i++,f += fstep)
243 inrow = (byte *)indata + inwidth3*yi;
245 memcpy(row1, row2, outwidth3);
247 R_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth, bytesperpixel);
249 R_ResampleTextureLerpLine (inrow + inwidth3, row2, inwidth, outwidth, bytesperpixel);
300 inrow = (byte *)indata + inwidth3*yi;
302 memcpy(row1, row2, outwidth3);
304 R_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth, bytesperpixel);
308 memcpy(out, row1, outwidth3);
314 globalOutputStream() << "R_ResampleTexture: unsupported bytesperpixel " << bytesperpixel << "\n";
318 // in can be the same as out
319 void GL_MipReduce(byte *in, byte *out, int width, int height, int destwidth, int destheight)
321 int x, y, width2, height2, nextrow;
322 if (width > destwidth)
324 if (height > destheight)
328 height2 = height >> 1;
329 nextrow = width << 2;
330 for (y = 0;y < height2;y++)
332 for (x = 0;x < width2;x++)
334 out[0] = (byte) ((in[0] + in[4] + in[nextrow ] + in[nextrow+4]) >> 2);
335 out[1] = (byte) ((in[1] + in[5] + in[nextrow+1] + in[nextrow+5]) >> 2);
336 out[2] = (byte) ((in[2] + in[6] + in[nextrow+2] + in[nextrow+6]) >> 2);
337 out[3] = (byte) ((in[3] + in[7] + in[nextrow+3] + in[nextrow+7]) >> 2);
341 in += nextrow; // skip a line
348 for (y = 0;y < height;y++)
350 for (x = 0;x < width2;x++)
352 out[0] = (byte) ((in[0] + in[4]) >> 1);
353 out[1] = (byte) ((in[1] + in[5]) >> 1);
354 out[2] = (byte) ((in[2] + in[6]) >> 1);
355 out[3] = (byte) ((in[3] + in[7]) >> 1);
364 if (height > destheight)
367 height2 = height >> 1;
368 nextrow = width << 2;
369 for (y = 0;y < height2;y++)
371 for (x = 0;x < width;x++)
373 out[0] = (byte) ((in[0] + in[nextrow ]) >> 1);
374 out[1] = (byte) ((in[1] + in[nextrow+1]) >> 1);
375 out[2] = (byte) ((in[2] + in[nextrow+2]) >> 1);
376 out[3] = (byte) ((in[3] + in[nextrow+3]) >> 1);
380 in += nextrow; // skip a line
385 globalOutputStream() << "GL_MipReduce: desired size already achieved\n";