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) {
48 for (j = 0, f = 0; j < outwidth; j++, f += fstep) {
51 in += (xi - oldx) * 4;
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 } else // last pixel of the line has no pixel to lerp to
69 } else if (bytesperpixel == 3) {
70 for (j = 0, f = 0; j < outwidth; j++, f += fstep) {
73 in += (xi - oldx) * 3;
79 *out++ = (byte) ((((in[3] - in[0]) * lerp) >> 16) + in[0]);
80 *out++ = (byte) ((((in[4] - in[1]) * lerp) >> 16) + in[1]);
81 *out++ = (byte) ((((in[5] - in[2]) * lerp) >> 16) + in[2]);
82 } else // last pixel of the line has no pixel to lerp to
90 globalOutputStream() << "R_ResampleTextureLerpLine: unsupported bytesperpixel " << bytesperpixel << "\n";
99 void R_ResampleTexture(const void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight,
102 if (rowsize < outwidth * bytesperpixel) {
110 rowsize = outwidth * bytesperpixel;
111 row1 = (byte *) malloc(rowsize);
112 row2 = (byte *) malloc(rowsize);
115 if (bytesperpixel == 4) {
116 int i, j, yi, oldy, f, fstep, lerp, endy = (inheight - 1), inwidth4 = inwidth * 4, outwidth4 = outwidth * 4;
118 out = (byte *) outdata;
119 fstep = (int) (inheight * 65536.0f / outheight);
120 #define LERPBYTE(i) out[i] = (byte) ( ( ( ( row2[i] - row1[i] ) * lerp ) >> 16 ) + row1[i] )
122 inrow = (byte *) indata;
124 R_ResampleTextureLerpLine(inrow, row1, inwidth, outwidth, bytesperpixel);
125 R_ResampleTextureLerpLine(inrow + inwidth4, row2, inwidth, outwidth, bytesperpixel);
127 for (i = 0, f = 0; i < outheight; i++, f += fstep) {
132 inrow = (byte *) indata + inwidth4 * yi;
133 if (yi == oldy + 1) {
134 memcpy(row1, row2, outwidth4);
136 R_ResampleTextureLerpLine(inrow, row1, inwidth, outwidth, bytesperpixel);
139 R_ResampleTextureLerpLine(inrow + inwidth4, row2, inwidth, outwidth, bytesperpixel);
191 inrow = (byte *) indata + inwidth4 * yi;
192 if (yi == oldy + 1) {
193 memcpy(row1, row2, outwidth4);
195 R_ResampleTextureLerpLine(inrow, row1, inwidth, outwidth, bytesperpixel);
200 memcpy(out, row1, outwidth4);
203 } else if (bytesperpixel == 3) {
204 int i, j, yi, oldy, f, fstep, lerp, endy = (inheight - 1), inwidth3 = inwidth * 3, outwidth3 = outwidth * 3;
206 out = (byte *) outdata;
207 fstep = (int) (inheight * 65536.0f / outheight);
208 #define LERPBYTE(i) out[i] = (byte) ( ( ( ( row2[i] - row1[i] ) * lerp ) >> 16 ) + row1[i] )
210 inrow = (byte *) indata;
212 R_ResampleTextureLerpLine(inrow, row1, inwidth, outwidth, bytesperpixel);
213 R_ResampleTextureLerpLine(inrow + inwidth3, row2, inwidth, outwidth, bytesperpixel);
214 for (i = 0, f = 0; i < outheight; i++, f += fstep) {
219 inrow = (byte *) indata + inwidth3 * yi;
220 if (yi == oldy + 1) {
221 memcpy(row1, row2, outwidth3);
223 R_ResampleTextureLerpLine(inrow, row1, inwidth, outwidth, bytesperpixel);
226 R_ResampleTextureLerpLine(inrow + inwidth3, row2, inwidth, outwidth, bytesperpixel);
271 inrow = (byte *) indata + inwidth3 * yi;
272 if (yi == oldy + 1) {
273 memcpy(row1, row2, outwidth3);
275 R_ResampleTextureLerpLine(inrow, row1, inwidth, outwidth, bytesperpixel);
280 memcpy(out, row1, outwidth3);
284 globalOutputStream() << "R_ResampleTexture: unsupported bytesperpixel " << bytesperpixel << "\n";
288 // in can be the same as out
289 void GL_MipReduce(byte *in, byte *out, int width, int height, int destwidth, int destheight)
291 int x, y, width2, height2, nextrow;
292 if (width > destwidth) {
293 if (height > destheight) {
296 height2 = height >> 1;
297 nextrow = width << 2;
298 for (y = 0; y < height2; y++) {
299 for (x = 0; x < width2; x++) {
300 out[0] = (byte) ((in[0] + in[4] + in[nextrow] + in[nextrow + 4]) >> 2);
301 out[1] = (byte) ((in[1] + in[5] + in[nextrow + 1] + in[nextrow + 5]) >> 2);
302 out[2] = (byte) ((in[2] + in[6] + in[nextrow + 2] + in[nextrow + 6]) >> 2);
303 out[3] = (byte) ((in[3] + in[7] + in[nextrow + 3] + in[nextrow + 7]) >> 2);
307 in += nextrow; // skip a line
312 for (y = 0; y < height; y++) {
313 for (x = 0; x < width2; x++) {
314 out[0] = (byte) ((in[0] + in[4]) >> 1);
315 out[1] = (byte) ((in[1] + in[5]) >> 1);
316 out[2] = (byte) ((in[2] + in[6]) >> 1);
317 out[3] = (byte) ((in[3] + in[7]) >> 1);
324 if (height > destheight) {
326 height2 = height >> 1;
327 nextrow = width << 2;
328 for (y = 0; y < height2; y++) {
329 for (x = 0; x < width; x++) {
330 out[0] = (byte) ((in[0] + in[nextrow]) >> 1);
331 out[1] = (byte) ((in[1] + in[nextrow + 1]) >> 1);
332 out[2] = (byte) ((in[2] + in[nextrow + 2]) >> 1);
333 out[3] = (byte) ((in[3] + in[nextrow + 3]) >> 1);
337 in += nextrow; // skip a line
340 globalOutputStream() << "GL_MipReduce: desired size already achieved\n";