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