]> git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake3/q3data/images.c
Merge commit '19992696033a496e5c0925e950a29dc23de49b47' into master-merge
[xonotic/netradiant.git] / tools / quake3 / q3data / images.c
1 /*
2    Copyright (C) 1999-2007 id Software, Inc. and contributors.
3    For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5    This file is part of GtkRadiant.
6
7    GtkRadiant is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    GtkRadiant is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GtkRadiant; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 #include "q3data.h"
23
24 byte            *byteimage, *lbmpalette;
25 int byteimagewidth, byteimageheight;
26
27
28 char mip_prefix[1024];              // directory to dump the textures in
29
30 qboolean colormap_issued;
31 byte colormap_palette[768];
32
33 /*
34    ==============
35    Cmd_Grab
36
37    $grab filename x y width height
38    ==============
39  */
40 void Cmd_Grab( void ){
41         int xl,yl,w,h,y;
42         byte            *cropped;
43         char savename[1024];
44         char dest[1024];
45
46         GetToken( qfalse );
47
48         if ( token[0] == '/' || token[0] == '\\' ) {
49                 sprintf( savename, "%s%s.pcx", writedir, token + 1 );
50         }
51         else{
52                 sprintf( savename, "%spics/%s.pcx", writedir, token );
53         }
54
55         if ( g_release ) {
56                 if ( token[0] == '/' || token[0] == '\\' ) {
57                         sprintf( dest, "%s.pcx", token + 1 );
58                 }
59                 else{
60                         sprintf( dest, "pics/%s.pcx", token );
61                 }
62
63                 ReleaseFile( dest );
64                 return;
65         }
66
67         GetToken( qfalse );
68         xl = atoi( token );
69         GetToken( qfalse );
70         yl = atoi( token );
71         GetToken( qfalse );
72         w = atoi( token );
73         GetToken( qfalse );
74         h = atoi( token );
75
76         if ( xl < 0 || yl < 0 || w < 0 || h < 0 || xl + w > byteimagewidth || yl + h > byteimageheight ) {
77                 Error( "GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h );
78         }
79
80         // crop it to the proper size
81         cropped = malloc( w * h );
82         for ( y = 0 ; y < h ; y++ )
83         {
84                 memcpy( cropped + y * w, byteimage + ( y + yl ) * byteimagewidth + xl, w );
85         }
86
87         // save off the new image
88         printf( "saving %s\n", savename );
89         CreatePath( savename );
90         WritePCXfile( savename, cropped, w, h, lbmpalette );
91
92         free( cropped );
93 }
94
95 /*
96    ==============
97    Cmd_Raw
98
99    $grab filename x y width height
100    ==============
101  */
102 void Cmd_Raw( void ){
103         int xl,yl,w,h,y;
104         byte            *cropped;
105         char savename[1024];
106         char dest[1024];
107
108         GetToken( qfalse );
109
110         sprintf( savename, "%s%s.lmp", writedir, token );
111
112         if ( g_release ) {
113                 sprintf( dest, "%s.lmp", token );
114                 ReleaseFile( dest );
115                 return;
116         }
117
118         GetToken( qfalse );
119         xl = atoi( token );
120         GetToken( qfalse );
121         yl = atoi( token );
122         GetToken( qfalse );
123         w = atoi( token );
124         GetToken( qfalse );
125         h = atoi( token );
126
127         if ( xl < 0 || yl < 0 || w < 0 || h < 0 || xl + w > byteimagewidth || yl + h > byteimageheight ) {
128                 Error( "GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h );
129         }
130
131         // crop it to the proper size
132         cropped = malloc( w * h );
133         for ( y = 0 ; y < h ; y++ )
134         {
135                 memcpy( cropped + y * w, byteimage + ( y + yl ) * byteimagewidth + xl, w );
136         }
137
138         // save off the new image
139         printf( "saving %s\n", savename );
140         CreatePath( savename );
141
142         SaveFile( savename, cropped, w * h );
143
144         free( cropped );
145 }
146
147 /*
148    =============================================================================
149
150    COLORMAP GRABBING
151
152    =============================================================================
153  */
154
155 /*
156    ===============
157    BestColor
158    ===============
159  */
160 byte BestColor( int r, int g, int b, int start, int stop ){
161         int i;
162         int dr, dg, db;
163         int bestdistortion, distortion;
164         int bestcolor;
165         byte    *pal;
166
167 //
168 // let any color go to 0 as a last resort
169 //
170         bestdistortion = 256 * 256 * 4;
171         bestcolor = 0;
172
173         pal = colormap_palette + start * 3;
174         for ( i = start ; i <= stop ; i++ )
175         {
176                 dr = r - (int)pal[0];
177                 dg = g - (int)pal[1];
178                 db = b - (int)pal[2];
179                 pal += 3;
180                 distortion = dr * dr + dg * dg + db * db;
181                 if ( distortion < bestdistortion ) {
182                         if ( !distortion ) {
183                                 return i;       // perfect match
184
185                         }
186                         bestdistortion = distortion;
187                         bestcolor = i;
188                 }
189         }
190
191         return bestcolor;
192 }
193
194
195 /*
196    ==============
197    Cmd_Colormap
198
199    $colormap filename
200
201    the brightes colormap is first in the table (FIXME: reverse this now?)
202
203    64 rows of 256 : lightmaps
204    256 rows of 256 : translucency table
205    ==============
206  */
207 void Cmd_Colormap( void ){
208         int levels, brights;
209         int l, c;
210         float frac, red, green, blue;
211         float range;
212         byte    *cropped, *lump_p;
213         char savename[1024];
214         char dest[1024];
215
216         colormap_issued = qtrue;
217         if ( !g_release ) {
218                 memcpy( colormap_palette, lbmpalette, 768 );
219         }
220
221         if ( !TokenAvailable() ) { // just setting colormap_issued
222                 return;
223         }
224
225         GetToken( qfalse );
226         sprintf( savename, "%spics/%s.pcx", writedir, token );
227
228         if ( g_release ) {
229                 sprintf( dest, "pics/%s.pcx", token );
230                 ReleaseFile( dest );
231                 return;
232         }
233
234         range = 2;
235         levels = 64;
236         brights = 1;    // ignore 255 (transparent)
237
238         cropped = malloc( ( levels + 256 ) * 256 );
239         lump_p = cropped;
240
241 // shaded levels
242         for ( l = 0; l < levels; l++ )
243         {
244                 frac = range - range * (float)l / ( levels - 1 );
245                 for ( c = 0 ; c < 256 - brights ; c++ )
246                 {
247                         red = lbmpalette[c * 3];
248                         green = lbmpalette[c * 3 + 1];
249                         blue = lbmpalette[c * 3 + 2];
250
251                         red = (int)( red * frac + 0.5 );
252                         green = (int)( green * frac + 0.5 );
253                         blue = (int)( blue * frac + 0.5 );
254
255 //
256 // note: 254 instead of 255 because 255 is the transparent color, and we
257 // don't want anything remapping to that
258 // don't use color 0, because NT can't remap that (or 255)
259 //
260                         *lump_p++ = BestColor( red,green,blue, 1, 254 );
261                 }
262
263                 // fullbrights allways stay the same
264                 for ( ; c < 256 ; c++ )
265                         *lump_p++ = c;
266         }
267
268 // 66% transparancy table
269         for ( l = 0; l < 255; l++ )
270         {
271                 for ( c = 0 ; c < 255 ; c++ )
272                 {
273                         red = lbmpalette[c * 3] * 0.33 + lbmpalette[l * 3] * 0.66;
274                         green = lbmpalette[c * 3 + 1] * 0.33 + lbmpalette[l * 3 + 1] * 0.66;
275                         blue = lbmpalette[c * 3 + 2] * 0.33 + lbmpalette[l * 3 + 2] * 0.66;
276
277                         *lump_p++ = BestColor( red,green,blue, 1, 254 );
278                 }
279                 *lump_p++ = 255;
280         }
281         for ( c = 0 ; c < 256 ; c++ )
282                 *lump_p++ = 255;
283
284         // save off the new image
285         printf( "saving %s\n", savename );
286         CreatePath( savename );
287         WritePCXfile( savename, cropped, 256, levels + 256, lbmpalette );
288
289         free( cropped );
290 }
291
292 /*
293    =============================================================================
294
295    MIPTEX GRABBING
296
297    =============================================================================
298  */
299
300 byte pixdata[256];
301
302 int d_red, d_green, d_blue;
303
304 byte palmap[32][32][32];
305 qboolean palmap_built;
306
307 /*
308    =============
309    FindColor
310    =============
311  */
312 int FindColor( int r, int g, int b ){
313         int bestcolor;
314
315         if ( r > 255 ) {
316                 r = 255;
317         }
318         if ( r < 0 ) {
319                 r = 0;
320         }
321         if ( g > 255 ) {
322                 g = 255;
323         }
324         if ( g < 0 ) {
325                 g = 0;
326         }
327         if ( b > 255 ) {
328                 b = 255;
329         }
330         if ( b < 0 ) {
331                 b = 0;
332         }
333 #ifndef TABLECOLORS
334         bestcolor = BestColor( r, g, b, 0, 254 );
335 #else
336         bestcolor = palmap[r >> 3][g >> 3][b >> 3];
337 #endif
338
339         return bestcolor;
340 }
341
342
343 void BuildPalmap( void ){
344 #ifdef TABLECOLORS
345         int r, g, b;
346         int bestcolor;
347
348         if ( palmap_built ) {
349                 return;
350         }
351         palmap_built = qtrue;
352
353         for ( r = 4 ; r < 256 ; r += 8 )
354         {
355                 for ( g = 4 ; g < 256 ; g += 8 )
356                 {
357                         for ( b = 4 ; b < 256 ; b += 8 )
358                         {
359                                 bestcolor = BestColor( r, g, b, 1, 254 );
360                                 palmap[r >> 3][g >> 3][b >> 3] = bestcolor;
361                         }
362                 }
363         }
364 #endif
365
366         if ( !colormap_issued ) {
367                 Error( "You must issue a $colormap command first" );
368         }
369
370 }
371
372 /*
373    =============
374    AveragePixels
375    =============
376  */
377 byte AveragePixels( int count ){
378         int r,g,b;
379         int i;
380         int vis;
381         int pix;
382         int bestcolor;
383         byte    *pal;
384
385         vis = 0;
386         r = g = b = 0;
387         for ( i = 0 ; i < count ; i++ )
388         {
389                 pix = pixdata[i];
390
391                 r += lbmpalette[pix * 3];
392                 g += lbmpalette[pix * 3 + 1];
393                 b += lbmpalette[pix * 3 + 2];
394                 vis++;
395         }
396
397         r /= vis;
398         g /= vis;
399         b /= vis;
400
401         // error diffusion
402         r += d_red;
403         g += d_green;
404         b += d_blue;
405
406 //
407 // find the best color
408 //
409         bestcolor = FindColor( r, g, b );
410
411         // error diffusion
412         pal = colormap_palette + bestcolor * 3;
413         d_red = r - (int)pal[0];
414         d_green = g - (int)pal[1];
415         d_blue = b - (int)pal[2];
416
417         return bestcolor;
418 }
419
420
421
422 /*
423    =============================================================================
424
425    ENVIRONMENT MAP GRABBING
426
427    Creates six pcx files from tga files without any palette edge seams
428    also copies the tga files for GL rendering.
429    =============================================================================
430  */
431
432 // 3dstudio environment map suffixes
433 char    *suf[6] = {"rt", "ft", "lf", "bk", "up", "dn"};
434
435 /*
436    =================
437    Cmd_Environment
438    =================
439  */
440 void Cmd_Environment( void ){
441         char name[1024];
442         int i, x, y;
443         byte image[256 * 256];
444         byte    *tga;
445
446         GetToken( qfalse );
447
448         if ( g_release ) {
449                 for ( i = 0 ; i < 6 ; i++ )
450                 {
451                         sprintf( name, "env/%s%s.pcx", token, suf[i] );
452                         ReleaseFile( name );
453                         sprintf( name, "env/%s%s.tga", token, suf[i] );
454                         ReleaseFile( name );
455                 }
456                 return;
457         }
458         // get the palette
459         BuildPalmap();
460
461         sprintf( name, "%senv/", gamedir );
462         CreatePath( name );
463
464         // convert the images
465         for ( i = 0 ; i < 6 ; i++ )
466         {
467                 sprintf( name, "%senv/%s%s.tga", gamedir, token, suf[i] );
468                 printf( "loading %s...\n", name );
469                 LoadTGA( name, &tga, NULL, NULL );
470
471                 for ( y = 0 ; y < 256 ; y++ )
472                 {
473                         for ( x = 0 ; x < 256 ; x++ )
474                         {
475                                 image[y * 256 + x] = FindColor( tga[( y * 256 + x ) * 4 + 0],tga[( y * 256 + x ) * 4 + 1],tga[( y * 256 + x ) * 4 + 2] );
476                         }
477                 }
478                 free( tga );
479                 sprintf( name, "%senv/%s%s.pcx", writedir, token, suf[i] );
480                 if ( FileTime( name ) != -1 ) {
481                         printf( "%s already exists, not overwriting.\n", name );
482                 }
483                 else{
484                         WritePCXfile( name, image, 256, 256, colormap_palette );
485                 }
486         }
487 }