1 /*
2 Copyright (C) 1999-2006 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 // imagelib.c
23
24 #include "inout.h"
25 #include "cmdlib.h"
26 #include "etclib.h"
27 #include "imagelib.h"
28 #include "vfs.h"
29
fgetLittleShort(FILE * f)30 int fgetLittleShort( FILE *f ){
31 byte b1, b2;
32
33 b1 = fgetc( f );
34 b2 = fgetc( f );
35
36 return (short)( b1 + b2 * 256 );
37 }
38
fgetLittleLong(FILE * f)39 int fgetLittleLong( FILE *f ){
40 byte b1, b2, b3, b4;
41
42 b1 = fgetc( f );
43 b2 = fgetc( f );
44 b3 = fgetc( f );
45 b4 = fgetc( f );
46
47 return b1 + ( b2 << 8 ) + ( b3 << 16 ) + ( b4 << 24 );
48 }
49
bufLittleShort(byte * buf,int len,int * pos)50 int bufLittleShort( byte *buf, int len, int *pos ){
51 byte b1, b2;
52
53 if ( ( len - *pos ) < 2 ) {
54 Error( "Unexpected buffer end" );
55 }
56
57 b1 = buf[*pos]; *pos += 1;
58 b2 = buf[*pos]; *pos += 1;
59
60 return (short)( b1 + b2 * 256 );
61 }
62
bufLittleLong(byte * buf,int len,int * pos)63 int bufLittleLong( byte *buf, int len, int *pos ){
64 byte b1, b2, b3, b4;
65
66 if ( ( len - *pos ) < 4 ) {
67 Error( "Unexpected buffer end" );
68 }
69
70 b1 = buf[*pos]; *pos += 1;
71 b2 = buf[*pos]; *pos += 1;
72 b3 = buf[*pos]; *pos += 1;
73 b4 = buf[*pos]; *pos += 1;
74
75 return b1 + ( b2 << 8 ) + ( b3 << 16 ) + ( b4 << 24 );
76 }
77
78
79 /*
80 ============================================================================
81
82 LBM STUFF
83
84 ============================================================================
85 */
86
87
88 typedef unsigned char UBYTE;
89 //conflicts with windows typedef short WORD;
90 typedef unsigned short UWORD;
91 typedef long LONG;
92
93 typedef enum
94 {
95 ms_none,
96 ms_mask,
97 ms_transcolor,
98 ms_lasso
99 } mask_t;
100
101 typedef enum
102 {
103 cm_none,
104 cm_rle1
105 } compress_t;
106
107 typedef struct
108 {
109 UWORD w,h;
110 short x,y;
111 UBYTE nPlanes;
112 UBYTE masking;
113 UBYTE compression;
114 UBYTE pad1;
115 UWORD transparentColor;
116 UBYTE xAspect,yAspect;
117 short pageWidth,pageHeight;
118 } bmhd_t;
119
120 extern bmhd_t bmhd; // will be in native byte order
121
122
123
124 #define FORMID ( 'F' + ( 'O' << 8 ) + ( (int)'R' << 16 ) + ( (int)'M' << 24 ) )
125 #define ILBMID ( 'I' + ( 'L' << 8 ) + ( (int)'B' << 16 ) + ( (int)'M' << 24 ) )
126 #define PBMID ( 'P' + ( 'B' << 8 ) + ( (int)'M' << 16 ) + ( (int)' ' << 24 ) )
127 #define BMHDID ( 'B' + ( 'M' << 8 ) + ( (int)'H' << 16 ) + ( (int)'D' << 24 ) )
128 #define BODYID ( 'B' + ( 'O' << 8 ) + ( (int)'D' << 16 ) + ( (int)'Y' << 24 ) )
129 #define CMAPID ( 'C' + ( 'M' << 8 ) + ( (int)'A' << 16 ) + ( (int)'P' << 24 ) )
130
131
132 bmhd_t bmhd;
133
Align(int l)134 int Align( int l ){
135 if ( l & 1 ) {
136 return l + 1;
137 }
138 return l;
139 }
140
141
142
143 /*
144 ================
145 LBMRLEdecompress
146
147 Source must be evenly aligned!
148 ================
149 */
LBMRLEDecompress(byte * source,byte * unpacked,int bpwidth)150 byte *LBMRLEDecompress( byte *source,byte *unpacked, int bpwidth ){
151 int count;
152 byte b,rept;
153
154 count = 0;
155
156 do
157 {
158 rept = *source++;
159
160 if ( rept > 0x80 ) {
161 rept = ( rept ^ 0xff ) + 2;
162 b = *source++;
163 memset( unpacked,b,rept );
164 unpacked += rept;
165 }
166 else if ( rept < 0x80 ) {
167 rept++;
168 memcpy( unpacked,source,rept );
169 unpacked += rept;
170 source += rept;
171 }
172 else{
173 rept = 0; // rept of 0x80 is NOP
174
175 }
176 count += rept;
177
178 } while ( count < bpwidth );
179
180 if ( count > bpwidth ) {
181 Error( "Decompression exceeded width!\n" );
182 }
183
184
185 return source;
186 }
187
188
189 /*
190 =================
191 LoadLBM
192 =================
193 */
LoadLBM(const char * filename,byte ** picture,byte ** palette)194 void LoadLBM( const char *filename, byte **picture, byte **palette ){
195 byte *LBMbuffer, *picbuffer, *cmapbuffer;
196 int y;
197 byte *LBM_P, *LBMEND_P;
198 byte *pic_p;
199 byte *body_p;
200
201 int formtype,formlength;
202 int chunktype,chunklength;
203
204 // qiet compiler warnings
205 picbuffer = NULL;
206 cmapbuffer = NULL;
207
208 //
209 // load the LBM
210 //
211 LoadFile( filename, (void **)&LBMbuffer );
212
213 //
214 // parse the LBM header
215 //
216 LBM_P = LBMbuffer;
217 if ( *(int *)LBMbuffer != LittleLong( FORMID ) ) {
218 Error( "No FORM ID at start of file!\n" );
219 }
220
221 LBM_P += 4;
222 formlength = BigLong( *(int *)LBM_P );
223 LBM_P += 4;
224 LBMEND_P = LBM_P + Align( formlength );
225
226 formtype = LittleLong( *(int *)LBM_P );
227
228 if ( formtype != ILBMID && formtype != PBMID ) {
229 Error( "Unrecognized form type: %c%c%c%c\n", formtype & 0xff
230 ,( formtype >> 8 ) & 0xff,( formtype >> 16 ) & 0xff,( formtype >> 24 ) & 0xff );
231 }
232
233 LBM_P += 4;
234
235 //
236 // parse chunks
237 //
238
239 while ( LBM_P < LBMEND_P )
240 {
241 chunktype = LBM_P[0] + ( LBM_P[1] << 8 ) + ( LBM_P[2] << 16 ) + ( LBM_P[3] << 24 );
242 LBM_P += 4;
243 chunklength = LBM_P[3] + ( LBM_P[2] << 8 ) + ( LBM_P[1] << 16 ) + ( LBM_P[0] << 24 );
244 LBM_P += 4;
245
246 switch ( chunktype )
247 {
248 case BMHDID:
249 memcpy( &bmhd,LBM_P,sizeof( bmhd ) );
250 bmhd.w = BigShort( bmhd.w );
251 bmhd.h = BigShort( bmhd.h );
252 bmhd.x = BigShort( bmhd.x );
253 bmhd.y = BigShort( bmhd.y );
254 bmhd.pageWidth = BigShort( bmhd.pageWidth );
255 bmhd.pageHeight = BigShort( bmhd.pageHeight );
256 break;
257
258 case CMAPID:
259 cmapbuffer = safe_malloc( 768 );
260 memset( cmapbuffer, 0, 768 );
261 memcpy( cmapbuffer, LBM_P, chunklength );
262 break;
263
264 case BODYID:
265 body_p = LBM_P;
266
267 pic_p = picbuffer = safe_malloc( bmhd.w * bmhd.h );
268 if ( formtype == PBMID ) {
269 //
270 // unpack PBM
271 //
272 for ( y = 0 ; y < bmhd.h ; y++, pic_p += bmhd.w )
273 {
274 if ( bmhd.compression == cm_rle1 ) {
275 body_p = LBMRLEDecompress( (byte *)body_p
276 , pic_p, bmhd.w );
277 }
278 else if ( bmhd.compression == cm_none ) {
279 memcpy( pic_p,body_p,bmhd.w );
280 body_p += Align( bmhd.w );
281 }
282 }
283
284 }
285 else
286 {
287 //
288 // unpack ILBM
289 //
290 Error( "%s is an interlaced LBM, not packed", filename );
291 }
292 break;
293 }
294
295 LBM_P += Align( chunklength );
296 }
297
298 free( LBMbuffer );
299
300 *picture = picbuffer;
301
302 if ( palette ) {
303 *palette = cmapbuffer;
304 }
305 }
306
307
308 /*
309 ============================================================================
310
311 WRITE LBM
312
313 ============================================================================
314 */
315
316 /*
317 ==============
318 WriteLBMfile
319 ==============
320 */
WriteLBMfile(const char * filename,byte * data,int width,int height,byte * palette)321 void WriteLBMfile( const char *filename, byte *data,
322 int width, int height, byte *palette ){
323 byte *lbm, *lbmptr;
324 int *formlength, *bmhdlength, *cmaplength, *bodylength;
325 int length;
326 bmhd_t basebmhd;
327
328 lbm = lbmptr = safe_malloc( width * height + 1000 );
329
330 //
331 // start FORM
332 //
333 *lbmptr++ = 'F';
334 *lbmptr++ = 'O';
335 *lbmptr++ = 'R';
336 *lbmptr++ = 'M';
337
338 formlength = (int*)lbmptr;
339 lbmptr += 4; // leave space for length
340
341 *lbmptr++ = 'P';
342 *lbmptr++ = 'B';
343 *lbmptr++ = 'M';
344 *lbmptr++ = ' ';
345
346 //
347 // write BMHD
348 //
349 *lbmptr++ = 'B';
350 *lbmptr++ = 'M';
351 *lbmptr++ = 'H';
352 *lbmptr++ = 'D';
353
354 bmhdlength = (int *)lbmptr;
355 lbmptr += 4; // leave space for length
356
357 memset( &basebmhd,0,sizeof( basebmhd ) );
358 basebmhd.w = BigShort( (short)width );
359 basebmhd.h = BigShort( (short)height );
360 basebmhd.nPlanes = BigShort( 8 );
361 basebmhd.xAspect = BigShort( 5 );
362 basebmhd.yAspect = BigShort( 6 );
363 basebmhd.pageWidth = BigShort( (short)width );
364 basebmhd.pageHeight = BigShort( (short)height );
365
366 memcpy( lbmptr,&basebmhd,sizeof( basebmhd ) );
367 lbmptr += sizeof( basebmhd );
368
369 length = lbmptr - (byte *)bmhdlength - 4;
370 *bmhdlength = BigLong( length );
371 if ( length & 1 ) {
372 *lbmptr++ = 0; // pad chunk to even offset
373
374 }
375 //
376 // write CMAP
377 //
378 *lbmptr++ = 'C';
379 *lbmptr++ = 'M';
380 *lbmptr++ = 'A';
381 *lbmptr++ = 'P';
382
383 cmaplength = (int *)lbmptr;
384 lbmptr += 4; // leave space for length
385
386 memcpy( lbmptr,palette,768 );
387 lbmptr += 768;
388
389 length = lbmptr - (byte *)cmaplength - 4;
390 *cmaplength = BigLong( length );
391 if ( length & 1 ) {
392 *lbmptr++ = 0; // pad chunk to even offset
393
394 }
395 //
396 // write BODY
397 //
398 *lbmptr++ = 'B';
399 *lbmptr++ = 'O';
400 *lbmptr++ = 'D';
401 *lbmptr++ = 'Y';
402
403 bodylength = (int *)lbmptr;
404 lbmptr += 4; // leave space for length
405
406 memcpy( lbmptr,data,width * height );
407 lbmptr += width * height;
408
409 length = lbmptr - (byte *)bodylength - 4;
410 *bodylength = BigLong( length );
411 if ( length & 1 ) {
412 *lbmptr++ = 0; // pad chunk to even offset
413
414 }
415 //
416 // done
417 //
418 length = lbmptr - (byte *)formlength - 4;
419 *formlength = BigLong( length );
420 if ( length & 1 ) {
421 *lbmptr++ = 0; // pad chunk to even offset
422
423 }
424 //
425 // write output file
426 //
427 SaveFile( filename, lbm, lbmptr - lbm );
428 free( lbm );
429 }
430
431
432 /*
433 ============================================================================
434
435 LOAD PCX
436
437 ============================================================================
438 */
439
440 typedef struct
441 {
442 char manufacturer;
443 char version;
444 char encoding;
445 char bits_per_pixel;
446 unsigned short xmin,ymin,xmax,ymax;
447 unsigned short hres,vres;
448 unsigned char palette[48];
449 char reserved;
450 char color_planes;
451 unsigned short bytes_per_line;
452 unsigned short palette_type;
453 char filler[58];
454 unsigned char data; // unbounded
455 } pcx_t;
456
457
458 /*
459 ==============
460 LoadPCX
461 ==============
462 */
463
464 /* RR2DO2 */
465 #define DECODEPCX( b, d, r ) d = *b++; if ( ( d & 0xC0 ) == 0xC0 ) {r = d & 0x3F; d = *b++; }else{r = 1; }
466
LoadPCX(const char * filename,byte ** pic,byte ** palette,int * width,int * height)467 void LoadPCX( const char *filename, byte **pic, byte **palette, int *width, int *height ){
468 byte *raw;
469 pcx_t *pcx;
470 int x, y, lsize;
471 int len;
472 int dataByte, runLength;
473 byte *out, *pix;
474
475
476 /* load the file */
477 len = vfsLoadFile( filename, (void **)&raw, 0 );
478 if ( len == -1 ) {
479 Error( "LoadPCX: Couldn't read %s", filename );
480 }
481
482
483 /* parse the PCX file */
484 pcx = (pcx_t *)raw;
485 raw = &pcx->data;
486
487 pcx->xmin = LittleShort( pcx->xmin );
488 pcx->ymin = LittleShort( pcx->ymin );
489 pcx->xmax = LittleShort( pcx->xmax );
490 pcx->ymax = LittleShort( pcx->ymax );
491 pcx->hres = LittleShort( pcx->hres );
492 pcx->vres = LittleShort( pcx->vres );
493 pcx->bytes_per_line = LittleShort( pcx->bytes_per_line );
494 pcx->palette_type = LittleShort( pcx->palette_type );
495
496 if ( pcx->manufacturer != 0x0a
497 || pcx->version != 5
498 || pcx->encoding != 1
499 || pcx->bits_per_pixel != 8
500 || pcx->xmax >= 640
501 || pcx->ymax >= 480 ) {
502 Error( "Bad pcx file %s", filename );
503 }
504
505 if ( palette ) {
506 *palette = safe_malloc( 768 );
507 memcpy( *palette, (byte *)pcx + len - 768, 768 );
508 }
509
510 if ( width ) {
511 *width = pcx->xmax + 1;
512 }
513 if ( height ) {
514 *height = pcx->ymax + 1;
515 }
516
517 if ( !pic ) {
518 return;
519 }
520
521 out = safe_malloc( ( pcx->ymax + 1 ) * ( pcx->xmax + 1 ) );
522 if ( !out ) {
523 Error( "LoadPCX: couldn't allocate" );
524 }
525
526 *pic = out;
527 pix = out;
528
529 /* RR2DO2: pcx fix */
530 lsize = pcx->color_planes * pcx->bytes_per_line;
531
532 /* go scanline by scanline */
533 for ( y = 0; y <= pcx->ymax; y++, pix += pcx->xmax + 1 )
534 {
535 /* do a scanline */
536 runLength = 0;
537 for ( x = 0; x <= pcx->xmax; )
538 {
539 /* RR2DO2 */
540 DECODEPCX( raw, dataByte, runLength );
541 while ( runLength-- > 0 )
542 pix[ x++ ] = dataByte;
543 }
544
545 /* RR2DO2: discard any other data */
546 while ( x < lsize )
547 {
548 DECODEPCX( raw, dataByte, runLength );
549 x++;
550 }
551 while ( runLength-- > 0 )
552 x++;
553 }
554
555 /* validity check */
556 if ( raw - (byte *) pcx > len ) {
557 Error( "PCX file %s was malformed", filename );
558 }
559 free( pcx );
560 }
561
562
563
564 /*
565 ==============
566 WritePCXfile
567 ==============
568 */
WritePCXfile(const char * filename,byte * data,int width,int height,byte * palette)569 void WritePCXfile( const char *filename, byte *data,
570 int width, int height, byte *palette ){
571 int i, j, length;
572 pcx_t *pcx;
573 byte *pack;
574
575 pcx = safe_malloc( width * height * 2 + 1000 );
576 memset( pcx, 0, sizeof( *pcx ) );
577
578 pcx->manufacturer = 0x0a; // PCX id
579 pcx->version = 5; // 256 color
580 pcx->encoding = 1; // uncompressed
581 pcx->bits_per_pixel = 8; // 256 color
582 pcx->xmin = 0;
583 pcx->ymin = 0;
584 pcx->xmax = LittleShort( (short)( width - 1 ) );
585 pcx->ymax = LittleShort( (short)( height - 1 ) );
586 pcx->hres = LittleShort( (short)width );
587 pcx->vres = LittleShort( (short)height );
588 pcx->color_planes = 1; // chunky image
589 pcx->bytes_per_line = LittleShort( (short)width );
590 pcx->palette_type = LittleShort( 1 ); // not a grey scale
591
592 // pack the image
593 pack = &pcx->data;
594
595 for ( i = 0 ; i < height ; i++ )
596 {
597 for ( j = 0 ; j < width ; j++ )
598 {
599 if ( ( *data & 0xc0 ) != 0xc0 ) {
600 *pack++ = *data++;
601 }
602 else
603 {
604 *pack++ = 0xc1;
605 *pack++ = *data++;
606 }
607 }
608 }
609
610 // write the palette
611 *pack++ = 0x0c; // palette ID byte
612 for ( i = 0 ; i < 768 ; i++ )
613 *pack++ = *palette++;
614
615 // write output file
616 length = pack - (byte *)pcx;
617 SaveFile( filename, pcx, length );
618
619 free( pcx );
620 }
621
622 /*
623 ============================================================================
624
625 LOAD BMP
626
627 ============================================================================
628 */
629
630
631 /*
632
633 // we can't just use these structures, because
634 // compiler structure alignment will not be portable
635 // on this unaligned stuff
636
637 typedef struct tagBITMAPFILEHEADER { // bmfh
638 WORD bfType; // BM
639 DWORD bfSize;
640 WORD bfReserved1;
641 WORD bfReserved2;
642 DWORD bfOffBits;
643 } BITMAPFILEHEADER;
644
645 typedef struct tagBITMAPINFOHEADER{ // bmih
646 DWORD biSize;
647 LONG biWidth;
648 LONG biHeight;
649 WORD biPlanes;
650 WORD biBitCount
651 DWORD biCompression;
652 DWORD biSizeImage;
653 LONG biXPelsPerMeter;
654 LONG biYPelsPerMeter;
655 DWORD biClrUsed;
656 DWORD biClrImportant;
657 } BITMAPINFOHEADER;
658
659 typedef struct tagBITMAPINFO { // bmi
660 BITMAPINFOHEADER bmiHeader;
661 RGBQUAD bmiColors[1];
662 } BITMAPINFO;
663
664 typedef struct tagBITMAPCOREHEADER { // bmch
665 DWORD bcSize;
666 WORD bcWidth;
667 WORD bcHeight;
668 WORD bcPlanes;
669 WORD bcBitCount;
670 } BITMAPCOREHEADER;
671
672 typedef struct _BITMAPCOREINFO { // bmci
673 BITMAPCOREHEADER bmciHeader;
674 RGBTRIPLE bmciColors[1];
675 } BITMAPCOREINFO;
676
677 */
678
679 /*
680 ==============
681 LoadBMP
682 ==============
683 */
LoadBMP(const char * filename,byte ** pic,byte ** palette,int * width,int * height)684 void LoadBMP( const char *filename, byte **pic, byte **palette, int *width, int *height ){
685 byte *out;
686 int i;
687 int bfOffBits;
688 int structSize;
689 int bcWidth;
690 int bcHeight;
691 int bcPlanes;
692 int bcBitCount;
693 byte bcPalette[1024];
694 qboolean flipped;
695 byte *in;
696 int len, pos = 0;
697
698 len = vfsLoadFile( filename, (void **)&in, 0 );
699 if ( len == -1 ) {
700 Error( "Couldn't read %s", filename );
701 }
702
703 i = bufLittleShort( in, len, &pos );
704 if ( i != 'B' + ( 'M' << 8 ) ) {
705 Error( "%s is not a bmp file", filename );
706 }
707
708 /* bfSize = */ bufLittleLong( in, len, &pos );
709 bufLittleShort( in, len, &pos );
710 bufLittleShort( in, len, &pos );
711 bfOffBits = bufLittleLong( in, len, &pos );
712
713 // the size will tell us if it is a
714 // bitmapinfo or a bitmapcore
715 structSize = bufLittleLong( in, len, &pos );
716 if ( structSize == 40 ) {
717 // bitmapinfo
718 bcWidth = bufLittleLong( in, len, &pos );
719 bcHeight = bufLittleLong( in, len, &pos );
720 bcPlanes = bufLittleShort( in, len, &pos );
721 bcBitCount = bufLittleShort( in, len, &pos );
722
723 pos += 24;
724
725 if ( palette ) {
726 memcpy( bcPalette, in + pos, 1024 );
727 pos += 1024;
728 *palette = safe_malloc( 768 );
729
730 for ( i = 0 ; i < 256 ; i++ )
731 {
732 ( *palette )[i * 3 + 0] = bcPalette[i * 4 + 2];
733 ( *palette )[i * 3 + 1] = bcPalette[i * 4 + 1];
734 ( *palette )[i * 3 + 2] = bcPalette[i * 4 + 0];
735 }
736 }
737 }
738 else if ( structSize == 12 ) {
739 // bitmapcore
740 bcWidth = bufLittleShort( in, len, &pos );
741 bcHeight = bufLittleShort( in, len, &pos );
742 bcPlanes = bufLittleShort( in, len, &pos );
743 bcBitCount = bufLittleShort( in, len, &pos );
744
745 if ( palette ) {
746 memcpy( bcPalette, in + pos, 768 );
747 pos += 768;
748 *palette = safe_malloc( 768 );
749
750 for ( i = 0 ; i < 256 ; i++ ) {
751 ( *palette )[i * 3 + 0] = bcPalette[i * 3 + 2];
752 ( *palette )[i * 3 + 1] = bcPalette[i * 3 + 1];
753 ( *palette )[i * 3 + 2] = bcPalette[i * 3 + 0];
754 }
755 }
756 }
757 else {
758 Error( "%s had strange struct size", filename );
759 }
760
761 if ( bcPlanes != 1 ) {
762 Error( "%s was not a single plane image", filename );
763 }
764
765 if ( bcBitCount != 8 ) {
766 Error( "%s was not an 8 bit image", filename );
767 }
768
769 if ( bcHeight < 0 ) {
770 bcHeight = -bcHeight;
771 flipped = qtrue;
772 }
773 else {
774 flipped = qfalse;
775 }
776
777 if ( width ) {
778 *width = bcWidth;
779 }
780 if ( height ) {
781 *height = bcHeight;
782 }
783
784 if ( !pic ) {
785 free( in );
786 return;
787 }
788
789 out = safe_malloc( bcWidth * bcHeight );
790 *pic = out;
791 pos = bfOffBits;
792
793 if ( flipped ) {
794 for ( i = 0 ; i < bcHeight ; i++ ) {
795 memcpy( out + bcWidth * ( bcHeight - 1 - i ), in + pos, bcWidth );
796 pos += bcWidth;
797 }
798 }
799 else {
800 memcpy( out, in + pos, bcWidth * bcHeight );
801 pos += bcWidth * bcHeight;
802 }
803
804 free( in );
805 }
806
807
808 /*
809 ============================================================================
810
811 LOAD IMAGE
812
813 ============================================================================
814 */
815
816 /*
817 ==============
818 Load256Image
819
820 Will load either an lbm or pcx, depending on extension.
821 Any of the return pointers can be NULL if you don't want them.
822 ==============
823 */
Load256Image(const char * name,byte ** pixels,byte ** palette,int * width,int * height)824 void Load256Image( const char *name, byte **pixels, byte **palette, int *width, int *height ){
825 char ext[128];
826
827 ExtractFileExtension( name, ext );
828 if ( !Q_stricmp( ext, "lbm" ) ) {
829 LoadLBM( name, pixels, palette );
830 if ( width ) {
831 *width = bmhd.w;
832 }
833 if ( height ) {
834 *height = bmhd.h;
835 }
836 }
837 else if ( !Q_stricmp( ext, "pcx" ) ) {
838 LoadPCX( name, pixels, palette, width, height );
839 }
840 else if ( !Q_stricmp( ext, "bmp" ) ) {
841 LoadBMP( name, pixels, palette, width, height );
842 }
843 else{
844 Error( "%s doesn't have a known image extension", name );
845 }
846 }
847
848
849 /*
850 ==============
851 Save256Image
852
853 Will save either an lbm or pcx, depending on extension.
854 ==============
855 */
Save256Image(const char * name,byte * pixels,byte * palette,int width,int height)856 void Save256Image( const char *name, byte *pixels, byte *palette,
857 int width, int height ){
858 char ext[128];
859
860 ExtractFileExtension( name, ext );
861 if ( !Q_stricmp( ext, "lbm" ) ) {
862 WriteLBMfile( name, pixels, width, height, palette );
863 }
864 else if ( !Q_stricmp( ext, "pcx" ) ) {
865 WritePCXfile( name, pixels, width, height, palette );
866 }
867 else{
868 Error( "%s doesn't have a known image extension", name );
869 }
870 }
871
872
873
874
875 /*
876 ============================================================================
877
878 TARGA IMAGE
879
880 ============================================================================
881 */
882
883 typedef struct _TargaHeader {
884 unsigned char id_length, colormap_type, image_type;
885 unsigned short colormap_index, colormap_length;
886 unsigned char colormap_size;
887 unsigned short x_origin, y_origin, width, height;
888 unsigned char pixel_size, attributes;
889 } TargaHeader;
890
TargaError(TargaHeader * t,const char * message)891 void TargaError( TargaHeader *t, const char *message ){
892 Sys_Printf( "%s\n:TargaHeader:\nuint8 id_length = %i;\nuint8 colormap_type = %i;\nuint8 image_type = %i;\nuint16 colormap_index = %i;\nuint16 colormap_length = %i;\nuint8 colormap_size = %i;\nuint16 x_origin = %i;\nuint16 y_origin = %i;\nuint16 width = %i;\nuint16 height = %i;\nuint8 pixel_size = %i;\nuint8 attributes = %i;\n", message, t->id_length, t->colormap_type, t->image_type, t->colormap_index, t->colormap_length, t->colormap_size, t->x_origin, t->y_origin, t->width, t->height, t->pixel_size, t->attributes );
893 }
894
895 /*
896 =============
897 LoadTGABuffer
898 =============
899 */
LoadTGABuffer(const byte * f,const byte * enddata,byte ** pic,int * width,int * height)900 void LoadTGABuffer( const byte *f, const byte *enddata, byte **pic, int *width, int *height ){
901 int x, y, row_inc, compressed, readpixelcount, red, green, blue, alpha, runlen, pindex, alphabits, image_width, image_height;
902 byte *pixbuf, *image_rgba;
903 const byte *fin;
904 unsigned char *p;
905 TargaHeader targa_header;
906 unsigned char palette[256 * 4];
907
908 *pic = NULL;
909
910 // abort if it is too small to parse
911 if ( enddata - f < 19 ) {
912 return;
913 }
914
915 targa_header.id_length = f[0];
916 targa_header.colormap_type = f[1];
917 targa_header.image_type = f[2];
918
919 targa_header.colormap_index = f[3] + f[4] * 256;
920 targa_header.colormap_length = f[5] + f[6] * 256;
921 targa_header.colormap_size = f[7];
922 targa_header.x_origin = f[8] + f[9] * 256;
923 targa_header.y_origin = f[10] + f[11] * 256;
924 targa_header.width = image_width = f[12] + f[13] * 256;
925 targa_header.height = image_height = f[14] + f[15] * 256;
926
927 targa_header.pixel_size = f[16];
928 targa_header.attributes = f[17];
929
930 // advance to end of header
931 fin = f + 18;
932
933 // skip TARGA image comment (usually 0 bytes)
934 fin += targa_header.id_length;
935
936 // read/skip the colormap if present (note: according to the TARGA spec it
937 // can be present even on truecolor or greyscale images, just not used by
938 // the image data)
939 if ( targa_header.colormap_type ) {
940 if ( targa_header.colormap_length > 256 ) {
941 TargaError( &targa_header, "LoadTGA: only up to 256 colormap_length supported\n" );
942 return;
943 }
944 if ( targa_header.colormap_index ) {
945 TargaError( &targa_header, "LoadTGA: colormap_index not supported\n" );
946 return;
947 }
948 if ( targa_header.colormap_size == 24 ) {
949 for ( x = 0; x < targa_header.colormap_length; x++ )
950 {
951 palette[x * 4 + 2] = *fin++;
952 palette[x * 4 + 1] = *fin++;
953 palette[x * 4 + 0] = *fin++;
954 palette[x * 4 + 3] = 255;
955 }
956 }
957 else if ( targa_header.colormap_size == 32 ) {
958 for ( x = 0; x < targa_header.colormap_length; x++ )
959 {
960 palette[x * 4 + 2] = *fin++;
961 palette[x * 4 + 1] = *fin++;
962 palette[x * 4 + 0] = *fin++;
963 palette[x * 4 + 3] = *fin++;
964 }
965 }
966 else
967 {
968 TargaError( &targa_header, "LoadTGA: Only 32 and 24 bit colormap_size supported\n" );
969 return;
970 }
971 }
972
973 // check our pixel_size restrictions according to image_type
974 if ( targa_header.image_type == 2 || targa_header.image_type == 10 ) {
975 if ( targa_header.pixel_size != 24 && targa_header.pixel_size != 32 ) {
976 TargaError( &targa_header, "LoadTGA: only 24bit and 32bit pixel sizes supported for type 2 and type 10 images\n" );
977 return;
978 }
979 }
980 else if ( targa_header.image_type == 1 || targa_header.image_type == 9 ) {
981 if ( targa_header.pixel_size != 8 ) {
982 TargaError( &targa_header, "LoadTGA: only 8bit pixel size for type 1, 3, 9, and 11 images supported\n" );
983 return;
984 }
985 }
986 else if ( targa_header.image_type == 3 || targa_header.image_type == 11 ) {
987 if ( targa_header.pixel_size != 8 ) {
988 TargaError( &targa_header, "LoadTGA: only 8bit pixel size for type 1, 3, 9, and 11 images supported\n" );
989 return;
990 }
991 }
992 else
993 {
994 TargaError( &targa_header, "LoadTGA: Only type 1, 2, 3, 9, 10, and 11 targa RGB images supported" );
995 return;
996 }
997
998 if ( targa_header.attributes & 0x10 ) {
999 TargaError( &targa_header, "LoadTGA: origin must be in top left or bottom left, top right and bottom right are not supported\n" );
1000 return;
1001 }
1002
1003 // number of attribute bits per pixel, we only support 0 or 8
1004 alphabits = targa_header.attributes & 0x0F;
1005 if ( alphabits != 8 && alphabits != 0 ) {
1006 TargaError( &targa_header, "LoadTGA: only 0 or 8 attribute (alpha) bits supported\n" );
1007 return;
1008 }
1009
1010 image_rgba = safe_malloc( image_width * image_height * 4 );
1011 if ( !image_rgba ) {
1012 Sys_Printf( "LoadTGA: not enough memory for %i by %i image\n", image_width, image_height );
1013 return;
1014 }
1015
1016 // If bit 5 of attributes isn't set, the image has been stored from bottom to top
1017 if ( ( targa_header.attributes & 0x20 ) == 0 ) {
1018 pixbuf = image_rgba + ( image_height - 1 ) * image_width * 4;
1019 row_inc = -image_width * 4 * 2;
1020 }
1021 else
1022 {
1023 pixbuf = image_rgba;
1024 row_inc = 0;
1025 }
1026
1027 compressed = targa_header.image_type == 9 || targa_header.image_type == 10 || targa_header.image_type == 11;
1028 x = 0;
1029 y = 0;
1030 red = green = blue = alpha = 255;
1031 while ( y < image_height )
1032 {
1033 // decoder is mostly the same whether it's compressed or not
1034 readpixelcount = 1000000;
1035 runlen = 1000000;
1036 if ( compressed && fin < enddata ) {
1037 runlen = *fin++;
1038 // high bit indicates this is an RLE compressed run
1039 if ( runlen & 0x80 ) {
1040 readpixelcount = 1;
1041 }
1042 runlen = 1 + ( runlen & 0x7f );
1043 }
1044
1045 while ( ( runlen-- ) && y < image_height )
1046 {
1047 if ( readpixelcount > 0 ) {
1048 readpixelcount--;
1049 red = green = blue = alpha = 255;
1050 if ( fin < enddata ) {
1051 switch ( targa_header.image_type )
1052 {
1053 case 1:
1054 case 9:
1055 // colormapped
1056 pindex = *fin++;
1057 if ( pindex >= targa_header.colormap_length ) {
1058 pindex = 0; // error
1059 }
1060 p = palette + pindex * 4;
1061 red = p[0];
1062 green = p[1];
1063 blue = p[2];
1064 alpha = p[3];
1065 break;
1066 case 2:
1067 case 10:
1068 // BGR or BGRA
1069 blue = *fin++;
1070 if ( fin < enddata ) {
1071 green = *fin++;
1072 }
1073 if ( fin < enddata ) {
1074 red = *fin++;
1075 }
1076 if ( targa_header.pixel_size == 32 && fin < enddata ) {
1077 alpha = *fin++;
1078 }
1079 break;
1080 case 3:
1081 case 11:
1082 // greyscale
1083 red = green = blue = *fin++;
1084 break;
1085 }
1086 if ( !alphabits ) {
1087 alpha = 255;
1088 }
1089 }
1090 }
1091 *pixbuf++ = red;
1092 *pixbuf++ = green;
1093 *pixbuf++ = blue;
1094 *pixbuf++ = alpha;
1095 x++;
1096 if ( x == image_width ) {
1097 // end of line, advance to next
1098 x = 0;
1099 y++;
1100 pixbuf += row_inc;
1101 }
1102 }
1103 }
1104
1105 *pic = image_rgba;
1106 if ( width ) {
1107 *width = image_width;
1108 }
1109 if ( height ) {
1110 *height = image_height;
1111 }
1112 }
1113
1114
1115 /*
1116 =============
1117 LoadTGA
1118 =============
1119 */
LoadTGA(const char * name,byte ** pixels,int * width,int * height)1120 void LoadTGA( const char *name, byte **pixels, int *width, int *height ){
1121 byte *buffer;
1122 int nLen;
1123 //
1124 // load the file
1125 //
1126 nLen = vfsLoadFile( name, (void **)&buffer, 0 );
1127 if ( nLen == -1 ) {
1128 Error( "Couldn't read %s", name );
1129 }
1130
1131 LoadTGABuffer( buffer, buffer + nLen, pixels, width, height );
1132
1133 }
1134
1135
1136 /*
1137 ================
1138 WriteTGA
1139 ================
1140 */
WriteTGA(const char * filename,byte * data,int width,int height)1141 void WriteTGA( const char *filename, byte *data, int width, int height ) {
1142 byte *buffer;
1143 int i;
1144 int c;
1145 FILE *f;
1146
1147 buffer = safe_malloc( width * height * 4 + 18 );
1148 memset( buffer, 0, 18 );
1149 buffer[2] = 2; // uncompressed type
1150 buffer[12] = width & 255;
1151 buffer[13] = width >> 8;
1152 buffer[14] = height & 255;
1153 buffer[15] = height >> 8;
1154 buffer[16] = 32; // pixel size
1155
1156 // swap rgb to bgr
1157 c = 18 + width * height * 4;
1158 for ( i = 18 ; i < c ; i += 4 )
1159 {
1160 buffer[i] = data[i - 18 + 2]; // blue
1161 buffer[i + 1] = data[i - 18 + 1]; // green
1162 buffer[i + 2] = data[i - 18 + 0]; // red
1163 buffer[i + 3] = data[i - 18 + 3]; // alpha
1164 }
1165
1166 f = fopen( filename, "wb" );
1167 fwrite( buffer, 1, c, f );
1168 fclose( f );
1169
1170 free( buffer );
1171 }
1172
WriteTGAGray(const char * filename,byte * data,int width,int height)1173 void WriteTGAGray( const char *filename, byte *data, int width, int height ) {
1174 byte buffer[18];
1175 FILE *f;
1176
1177 memset( buffer, 0, 18 );
1178 buffer[2] = 3; // uncompressed type
1179 buffer[12] = width & 255;
1180 buffer[13] = width >> 8;
1181 buffer[14] = height & 255;
1182 buffer[15] = height >> 8;
1183 buffer[16] = 8; // pixel size
1184
1185 f = fopen( filename, "wb" );
1186 fwrite( buffer, 1, 18, f );
1187 fwrite( data, 1, width * height, f );
1188 fclose( f );
1189 }
1190
1191 /*
1192 ============================================================================
1193
1194 LOAD32BITIMAGE
1195
1196 ============================================================================
1197 */
1198
1199 /*
1200 ==============
1201 Load32BitImage
1202
1203 Any of the return pointers can be NULL if you don't want them.
1204 ==============
1205 */
Load32BitImage(const char * name,unsigned ** pixels,int * width,int * height)1206 void Load32BitImage( const char *name, unsigned **pixels, int *width, int *height ){
1207 char ext[128];
1208 byte *palette;
1209 byte *pixels8;
1210 byte *pixels32;
1211 int size;
1212 int i;
1213 int v;
1214
1215 ExtractFileExtension( name, ext );
1216 if ( !Q_stricmp( ext, "tga" ) ) {
1217 LoadTGA( name, (byte **)pixels, width, height );
1218 }
1219 else {
1220 Load256Image( name, &pixels8, &palette, width, height );
1221 if ( !pixels ) {
1222 return;
1223 }
1224 size = *width * *height;
1225 pixels32 = safe_malloc( size * 4 );
1226 *pixels = (unsigned *)pixels32;
1227 for ( i = 0 ; i < size ; i++ ) {
1228 v = pixels8[i];
1229 pixels32[i * 4 + 0] = palette[ v * 3 + 0 ];
1230 pixels32[i * 4 + 1] = palette[ v * 3 + 1 ];
1231 pixels32[i * 4 + 2] = palette[ v * 3 + 2 ];
1232 pixels32[i * 4 + 3] = 0xff;
1233 }
1234 }
1235 }
1236
1237
1238 /*
1239 ============================================================================
1240
1241 KHRONOS TEXTURE
1242
1243 ============================================================================
1244 */
1245
1246
1247 #define KTX_UINT32_LE( buf ) ( ( unsigned int )( (buf)[0] | ( (buf)[1] << 8 ) | ( (buf)[2] << 16 ) | ( (buf)[3] << 24 ) ) )
1248 #define KTX_UINT32_BE( buf ) ( ( unsigned int )( (buf)[3] | ( (buf)[2] << 8 ) | ( (buf)[1] << 16 ) | ( (buf)[0] << 24 ) ) )
1249
1250 #define KTX_TYPE_UNSIGNED_BYTE 0x1401
1251 #define KTX_TYPE_UNSIGNED_SHORT_4_4_4_4 0x8033
1252 #define KTX_TYPE_UNSIGNED_SHORT_5_5_5_1 0x8034
1253 #define KTX_TYPE_UNSIGNED_SHORT_5_6_5 0x8363
1254
1255 #define KTX_FORMAT_ALPHA 0x1906
1256 #define KTX_FORMAT_RGB 0x1907
1257 #define KTX_FORMAT_RGBA 0x1908
1258 #define KTX_FORMAT_LUMINANCE 0x1909
1259 #define KTX_FORMAT_LUMINANCE_ALPHA 0x190A
1260 #define KTX_FORMAT_BGR 0x80E0
1261 #define KTX_FORMAT_BGRA 0x80E1
1262
1263 #define KTX_FORMAT_ETC1_RGB8 0x8D64
1264
KTX_DecodeA8(const byte * in,qboolean bigEndian,byte * out)1265 static void KTX_DecodeA8( const byte *in, qboolean bigEndian, byte *out ){
1266 out[0] = out[1] = out[2] = 0;
1267 out[3] = in[0];
1268 }
1269
KTX_DecodeRGB8(const byte * in,qboolean bigEndian,byte * out)1270 static void KTX_DecodeRGB8( const byte *in, qboolean bigEndian, byte *out ){
1271 out[0] = in[0];
1272 out[1] = in[1];
1273 out[2] = in[2];
1274 out[3] = 255;
1275 }
1276
KTX_DecodeRGBA8(const byte * in,qboolean bigEndian,byte * out)1277 static void KTX_DecodeRGBA8( const byte *in, qboolean bigEndian, byte *out ){
1278 out[0] = in[0];
1279 out[1] = in[1];
1280 out[2] = in[2];
1281 out[3] = in[3];
1282 }
1283
KTX_DecodeL8(const byte * in,qboolean bigEndian,byte * out)1284 static void KTX_DecodeL8( const byte *in, qboolean bigEndian, byte *out ){
1285 out[0] = out[1] = out[2] = in[0];
1286 out[3] = 255;
1287 }
1288
KTX_DecodeLA8(const byte * in,qboolean bigEndian,byte * out)1289 static void KTX_DecodeLA8( const byte *in, qboolean bigEndian, byte *out ){
1290 out[0] = out[1] = out[2] = in[0];
1291 out[3] = in[1];
1292 }
1293
KTX_DecodeBGR8(const byte * in,qboolean bigEndian,byte * out)1294 static void KTX_DecodeBGR8( const byte *in, qboolean bigEndian, byte *out ){
1295 out[0] = in[2];
1296 out[1] = in[1];
1297 out[2] = in[0];
1298 out[3] = 255;
1299 }
1300
KTX_DecodeBGRA8(const byte * in,qboolean bigEndian,byte * out)1301 static void KTX_DecodeBGRA8( const byte *in, qboolean bigEndian, byte *out ){
1302 out[0] = in[2];
1303 out[1] = in[1];
1304 out[2] = in[0];
1305 out[3] = in[3];
1306 }
1307
KTX_DecodeRGBA4(const byte * in,qboolean bigEndian,byte * out)1308 static void KTX_DecodeRGBA4( const byte *in, qboolean bigEndian, byte *out ){
1309 unsigned short rgba;
1310 int r, g, b, a;
1311
1312 if ( bigEndian ) {
1313 rgba = ( in[0] << 8 ) | in[1];
1314 }
1315 else {
1316 rgba = ( in[1] << 8 ) | in[0];
1317 }
1318
1319 r = ( rgba >> 12 ) & 0xf;
1320 g = ( rgba >> 8 ) & 0xf;
1321 b = ( rgba >> 4 ) & 0xf;
1322 a = rgba & 0xf;
1323 out[0] = ( r << 4 ) | r;
1324 out[1] = ( g << 4 ) | g;
1325 out[2] = ( b << 4 ) | b;
1326 out[3] = ( a << 4 ) | a;
1327 }
1328
KTX_DecodeRGBA5(const byte * in,qboolean bigEndian,byte * out)1329 static void KTX_DecodeRGBA5( const byte *in, qboolean bigEndian, byte *out ){
1330 unsigned short rgba;
1331 int r, g, b;
1332
1333 if ( bigEndian ) {
1334 rgba = ( in[0] << 8 ) | in[1];
1335 }
1336 else {
1337 rgba = ( in[1] << 8 ) | in[0];
1338 }
1339
1340 r = ( rgba >> 11 ) & 0x1f;
1341 g = ( rgba >> 6 ) & 0x1f;
1342 b = ( rgba >> 1 ) & 0x1f;
1343 out[0] = ( r << 3 ) | ( r >> 2 );
1344 out[1] = ( g << 3 ) | ( g >> 2 );
1345 out[2] = ( b << 3 ) | ( b >> 2 );
1346 out[3] = ( rgba & 1 ) * 255;
1347 }
1348
KTX_DecodeRGB5(const byte * in,qboolean bigEndian,byte * out)1349 static void KTX_DecodeRGB5( const byte *in, qboolean bigEndian, byte *out ){
1350 unsigned short rgba;
1351 int r, g, b;
1352
1353 if ( bigEndian ) {
1354 rgba = ( in[0] << 8 ) | in[1];
1355 }
1356 else {
1357 rgba = ( in[1] << 8 ) | in[0];
1358 }
1359
1360 r = ( rgba >> 11 ) & 0x1f;
1361 g = ( rgba >> 5 ) & 0x3f;
1362 b = rgba & 0x1f;
1363 out[0] = ( r << 3 ) | ( r >> 2 );
1364 out[1] = ( g << 2 ) | ( g >> 4 );
1365 out[2] = ( b << 3 ) | ( b >> 2 );
1366 out[3] = 255;
1367 }
1368
1369 typedef struct
1370 {
1371 unsigned int type;
1372 unsigned int format;
1373 unsigned int pixelSize;
1374 void ( *decode )( const byte *in, qboolean bigEndian, byte *out );
1375 } KTX_UncompressedFormat_t;
1376
1377 static const KTX_UncompressedFormat_t KTX_UncompressedFormats[] =
1378 {
1379 { KTX_TYPE_UNSIGNED_BYTE, KTX_FORMAT_ALPHA, 1, KTX_DecodeA8 },
1380 { KTX_TYPE_UNSIGNED_BYTE, KTX_FORMAT_RGB, 3, KTX_DecodeRGB8 },
1381 { KTX_TYPE_UNSIGNED_BYTE, KTX_FORMAT_RGBA, 4, KTX_DecodeRGBA8 },
1382 { KTX_TYPE_UNSIGNED_BYTE, KTX_FORMAT_LUMINANCE, 1, KTX_DecodeL8 },
1383 { KTX_TYPE_UNSIGNED_BYTE, KTX_FORMAT_LUMINANCE_ALPHA, 2, KTX_DecodeLA8 },
1384 { KTX_TYPE_UNSIGNED_BYTE, KTX_FORMAT_BGR, 3, KTX_DecodeBGR8 },
1385 { KTX_TYPE_UNSIGNED_BYTE, KTX_FORMAT_BGRA, 4, KTX_DecodeBGRA8 },
1386 { KTX_TYPE_UNSIGNED_SHORT_4_4_4_4, KTX_FORMAT_RGBA, 2, KTX_DecodeRGBA4 },
1387 { KTX_TYPE_UNSIGNED_SHORT_5_5_5_1, KTX_FORMAT_RGBA, 2, KTX_DecodeRGBA5 },
1388 { KTX_TYPE_UNSIGNED_SHORT_5_6_5, KTX_FORMAT_RGB, 2, KTX_DecodeRGB5 },
1389 { 0, 0, 0, NULL }
1390 };
1391
KTX_DecodeETC1(const byte * in,size_t inSize,unsigned int width,unsigned int height,byte * out)1392 static qboolean KTX_DecodeETC1( const byte* in, size_t inSize, unsigned int width, unsigned int height, byte* out ){
1393 unsigned int y, stride = width * 4;
1394 byte rgba[64];
1395
1396 if ( inSize < ( ( ( ( width + 3 ) & ~3 ) * ( ( height + 3 ) & ~3 ) ) >> 1 ) ) {
1397 return qfalse;
1398 }
1399
1400 for ( y = 0; y < height; y += 4, out += stride * 4 )
1401 {
1402 byte *p;
1403 unsigned int x, blockrows;
1404
1405 blockrows = height - y;
1406 if ( blockrows > 4 ) {
1407 blockrows = 4;
1408 }
1409
1410 p = out;
1411 for ( x = 0; x < width; x += 4, p += 16 )
1412 {
1413 unsigned int blockrowsize, blockrow;
1414
1415 ETC_DecodeETC1Block( in, rgba, qtrue );
1416 in += 8;
1417
1418 blockrowsize = width - x;
1419 if ( blockrowsize > 4 ) {
1420 blockrowsize = 4;
1421 }
1422 blockrowsize *= 4;
1423 for ( blockrow = 0; blockrow < blockrows; blockrow++ )
1424 {
1425 memcpy( p + blockrow * stride, rgba + blockrow * 16, blockrowsize );
1426 }
1427 }
1428 }
1429
1430 return qtrue;
1431 }
1432
1433 #define KTX_HEADER_UINT32( buf ) ( bigEndian ? KTX_UINT32_BE( buf ) : KTX_UINT32_LE( buf ) )
1434
LoadKTXBufferFirstImage(const byte * buffer,size_t bufSize,byte ** pic,int * picWidth,int * picHeight)1435 void LoadKTXBufferFirstImage( const byte *buffer, size_t bufSize, byte **pic, int *picWidth, int *picHeight ){
1436 unsigned int type, format, width, height, imageOffset;
1437 byte *pixels;
1438
1439 if ( bufSize < 64 ) {
1440 Error( "LoadKTX: Image doesn't have a header" );
1441 }
1442
1443 if ( memcmp( buffer, "\xABKTX 11\xBB\r\n\x1A\n", 12 ) ) {
1444 Error( "LoadKTX: Image has the wrong identifier" );
1445 }
1446
1447 qboolean bigEndian = ( buffer[4] == 4 );
1448
1449 type = KTX_HEADER_UINT32( buffer + 16 );
1450 if ( type ) {
1451 format = KTX_HEADER_UINT32( buffer + 32 );
1452 }
1453 else {
1454 format = KTX_HEADER_UINT32( buffer + 28 );
1455 }
1456
1457 width = KTX_HEADER_UINT32( buffer + 36 );
1458 height = KTX_HEADER_UINT32( buffer + 40 );
1459 if ( !width ) {
1460 Error( "LoadKTX: Image has zero width" );
1461 }
1462 if ( !height ) {
1463 height = 1;
1464 }
1465 if ( picWidth ) {
1466 *picWidth = width;
1467 }
1468 if ( picHeight ) {
1469 *picHeight = height;
1470 }
1471
1472 imageOffset = 64 + KTX_HEADER_UINT32( buffer + 60 ) + 4;
1473 if ( bufSize < imageOffset ) {
1474 Error( "LoadKTX: No image in the file" );
1475 }
1476 buffer += imageOffset;
1477 bufSize -= imageOffset;
1478
1479 pixels = safe_malloc( width * height * 4 );
1480 *pic = pixels;
1481
1482 if ( type ) {
1483 const KTX_UncompressedFormat_t *ktxFormat = KTX_UncompressedFormats;
1484 unsigned int pixelSize;
1485 unsigned int inRowLength, inPadding;
1486 unsigned int y;
1487
1488 while ( ktxFormat->type )
1489 {
1490 if ( ktxFormat->type == type && ktxFormat->format == format ) {
1491 break;
1492 }
1493 ktxFormat++;
1494 }
1495 if ( !ktxFormat->type ) {
1496 Error( "LoadKTX: Image has an unsupported pixel type 0x%X or format 0x%X", type, format );
1497 }
1498
1499 pixelSize = ktxFormat->pixelSize;
1500 inRowLength = width * pixelSize;
1501 inPadding = ( ( inRowLength + 3 ) & ~3 ) - inRowLength;
1502
1503 if ( bufSize < height * ( inRowLength + inPadding ) ) {
1504 Error( "LoadKTX: Image is truncated" );
1505 }
1506
1507 for ( y = 0; y < height; y++ )
1508 {
1509 unsigned int x;
1510 for ( x = 0; x < width; x++, buffer += pixelSize, pixels += 4 )
1511 {
1512 ktxFormat->decode( buffer, bigEndian, pixels );
1513 }
1514 buffer += inPadding;
1515 }
1516 }
1517 else {
1518 qboolean decoded = qfalse;
1519
1520 switch ( format )
1521 {
1522 case KTX_FORMAT_ETC1_RGB8:
1523 decoded = KTX_DecodeETC1( buffer, bufSize, width, height, pixels );
1524 break;
1525 default:
1526 Error( "LoadKTX: Image has an unsupported compressed format format 0x%X", format );
1527 break;
1528 }
1529
1530 if ( !decoded ) {
1531 Error( "LoadKTX: Image is truncated" );
1532 }
1533 }
1534 }
1535