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 ){
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] )
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 )
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] );
62 else // last pixel of the line has no pixel to lerp to
71 else if ( bytesperpixel == 3 ) {
72 for ( j = 0, f = 0; j < outwidth; j++, f += fstep )
76 in += ( xi - oldx ) * 3;
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] );
86 else // last pixel of the line has no pixel to lerp to
96 globalOutputStream() << "R_ResampleTextureLerpLine: unsupported bytesperpixel " << bytesperpixel << "\n";
105 void R_ResampleTexture( const void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight, int bytesperpixel ){
106 if ( rowsize < outwidth * bytesperpixel ) {
114 rowsize = outwidth * bytesperpixel;
115 row1 = (byte *)malloc( rowsize );
116 row2 = (byte *)malloc( rowsize );
119 if ( bytesperpixel == 4 ) {
120 int i, j, yi, oldy, f, fstep, lerp, endy = ( inheight - 1 ), inwidth4 = inwidth * 4, outwidth4 = outwidth * 4;
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] )
126 inrow = (byte *)indata;
128 R_ResampleTextureLerpLine( inrow, row1, inwidth, outwidth, bytesperpixel );
129 R_ResampleTextureLerpLine( inrow + inwidth4, row2, inwidth, outwidth, bytesperpixel );
131 for ( i = 0, f = 0; i < outheight; i++,f += fstep )
137 inrow = (byte *)indata + inwidth4 * yi;
138 if ( yi == oldy + 1 ) {
139 memcpy( row1, row2, outwidth4 );
142 R_ResampleTextureLerpLine( inrow, row1, inwidth, outwidth, bytesperpixel );
145 R_ResampleTextureLerpLine( inrow + inwidth4, row2, inwidth, outwidth, bytesperpixel );
200 inrow = (byte *)indata + inwidth4 * yi;
201 if ( yi == oldy + 1 ) {
202 memcpy( row1, row2, outwidth4 );
205 R_ResampleTextureLerpLine( inrow, row1, inwidth, outwidth, bytesperpixel );
210 memcpy( out, row1, outwidth4 );
214 else if ( bytesperpixel == 3 ) {
215 int i, j, yi, oldy, f, fstep, lerp, endy = ( inheight - 1 ), inwidth3 = inwidth * 3, outwidth3 = outwidth * 3;
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] )
221 inrow = (byte *)indata;
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 )
231 inrow = (byte *)indata + inwidth3 * yi;
232 if ( yi == oldy + 1 ) {
233 memcpy( row1, row2, outwidth3 );
236 R_ResampleTextureLerpLine( inrow, row1, inwidth, outwidth, bytesperpixel );
239 R_ResampleTextureLerpLine( inrow + inwidth3, row2, inwidth, outwidth, bytesperpixel );
287 inrow = (byte *)indata + inwidth3 * yi;
288 if ( yi == oldy + 1 ) {
289 memcpy( row1, row2, outwidth3 );
292 R_ResampleTextureLerpLine( inrow, row1, inwidth, outwidth, bytesperpixel );
297 memcpy( out, row1, outwidth3 );
303 globalOutputStream() << "R_ResampleTexture: unsupported bytesperpixel " << bytesperpixel << "\n";
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 ) {
314 height2 = height >> 1;
315 nextrow = width << 2;
316 for ( y = 0; y < height2; y++ )
318 for ( x = 0; x < width2; x++ )
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 );
327 in += nextrow; // skip a line
334 for ( y = 0; y < height; y++ )
336 for ( x = 0; x < width2; x++ )
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 );
350 if ( height > destheight ) {
352 height2 = height >> 1;
353 nextrow = width << 2;
354 for ( y = 0; y < height2; y++ )
356 for ( x = 0; x < width; x++ )
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 );
365 in += nextrow; // skip a line
370 globalOutputStream() << "GL_MipReduce: desired size already achieved\n";