1 /*
2 ===========================================================================
3 ioquake3 png decoder
4 Copyright (C) 2007,2008 Joerg Dietrich
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 ===========================================================================
20 */
21
22 #include "tr_local.h"
23
24 #include "../qcommon/puff.h"
25
26 // we could limit the png size to a lower value here
27 #ifndef INT_MAX
28 #define INT_MAX 0x1fffffff
29 #endif
30
31 /*
32 =================
33 PNG LOADING
34 =================
35 */
36
37 /*
38 * Quake 3 image format : RGBA
39 */
40
41 #define Q3IMAGE_BYTESPERPIXEL (4)
42
43 /*
44 * PNG specifications
45 */
46
47 /*
48 * The first 8 Bytes of every PNG-File are a fixed signature
49 * to identify the file as a PNG.
50 */
51
52 #define PNG_Signature "\x89\x50\x4E\x47\xD\xA\x1A\xA"
53 #define PNG_Signature_Size (8)
54
55 /*
56 * After the signature diverse chunks follow.
57 * A chunk consists of a header and if Length
58 * is bigger than 0 a body and a CRC of the body follow.
59 */
60
61 struct PNG_ChunkHeader
62 {
63 uint32_t Length;
64 uint32_t Type;
65 };
66
67 #define PNG_ChunkHeader_Size (8)
68
69 typedef uint32_t PNG_ChunkCRC;
70
71 #define PNG_ChunkCRC_Size (4)
72
73 /*
74 * We use the following ChunkTypes.
75 * All others are ignored.
76 */
77
78 #define MAKE_CHUNKTYPE(a,b,c,d) (((a) << 24) | ((b) << 16) | ((c) << 8) | ((d)))
79
80 #define PNG_ChunkType_IHDR MAKE_CHUNKTYPE('I', 'H', 'D', 'R')
81 #define PNG_ChunkType_PLTE MAKE_CHUNKTYPE('P', 'L', 'T', 'E')
82 #define PNG_ChunkType_IDAT MAKE_CHUNKTYPE('I', 'D', 'A', 'T')
83 #define PNG_ChunkType_IEND MAKE_CHUNKTYPE('I', 'E', 'N', 'D')
84 #define PNG_ChunkType_tRNS MAKE_CHUNKTYPE('t', 'R', 'N', 'S')
85
86 /*
87 * Per specification the first chunk after the signature SHALL be IHDR.
88 */
89
90 struct PNG_Chunk_IHDR
91 {
92 uint32_t Width;
93 uint32_t Height;
94 uint8_t BitDepth;
95 uint8_t ColourType;
96 uint8_t CompressionMethod;
97 uint8_t FilterMethod;
98 uint8_t InterlaceMethod;
99 };
100
101 #define PNG_Chunk_IHDR_Size (13)
102
103 /*
104 * ColourTypes
105 */
106
107 #define PNG_ColourType_Grey (0)
108 #define PNG_ColourType_True (2)
109 #define PNG_ColourType_Indexed (3)
110 #define PNG_ColourType_GreyAlpha (4)
111 #define PNG_ColourType_TrueAlpha (6)
112
113 /*
114 * number of colour components
115 *
116 * Grey : 1 grey
117 * True : 1 R, 1 G, 1 B
118 * Indexed : 1 index
119 * GreyAlpha : 1 grey, 1 alpha
120 * TrueAlpha : 1 R, 1 G, 1 B, 1 alpha
121 */
122
123 #define PNG_NumColourComponents_Grey (1)
124 #define PNG_NumColourComponents_True (3)
125 #define PNG_NumColourComponents_Indexed (1)
126 #define PNG_NumColourComponents_GreyAlpha (2)
127 #define PNG_NumColourComponents_TrueAlpha (4)
128
129 /*
130 * For the different ColourTypes
131 * different BitDepths are specified.
132 */
133
134 #define PNG_BitDepth_1 ( 1)
135 #define PNG_BitDepth_2 ( 2)
136 #define PNG_BitDepth_4 ( 4)
137 #define PNG_BitDepth_8 ( 8)
138 #define PNG_BitDepth_16 (16)
139
140 /*
141 * Only one valid CompressionMethod is standardized.
142 */
143
144 #define PNG_CompressionMethod_0 (0)
145
146 /*
147 * Only one valid FilterMethod is currently standardized.
148 */
149
150 #define PNG_FilterMethod_0 (0)
151
152 /*
153 * This FilterMethod defines 5 FilterTypes
154 */
155
156 #define PNG_FilterType_None (0)
157 #define PNG_FilterType_Sub (1)
158 #define PNG_FilterType_Up (2)
159 #define PNG_FilterType_Average (3)
160 #define PNG_FilterType_Paeth (4)
161
162 /*
163 * Two InterlaceMethods are standardized :
164 * 0 - NonInterlaced
165 * 1 - Interlaced
166 */
167
168 #define PNG_InterlaceMethod_NonInterlaced (0)
169 #define PNG_InterlaceMethod_Interlaced (1)
170
171 /*
172 * The Adam7 interlace method uses 7 passes.
173 */
174
175 #define PNG_Adam7_NumPasses (7)
176
177 /*
178 * The compressed data starts with a header ...
179 */
180
181 struct PNG_ZlibHeader
182 {
183 uint8_t CompressionMethod;
184 uint8_t Flags;
185 };
186
187 #define PNG_ZlibHeader_Size (2)
188
189 /*
190 * ... and is followed by a check value
191 */
192
193 #define PNG_ZlibCheckValue_Size (4)
194
195 /*
196 * Some support functions for buffered files follow.
197 */
198
199 /*
200 * buffered file representation
201 */
202
203 struct BufferedFile
204 {
205 byte *Buffer;
206 int Length;
207 byte *Ptr;
208 int BytesLeft;
209 };
210
211 /*
212 * Read a file into a buffer.
213 */
214
ReadBufferedFile(const char * name)215 static struct BufferedFile *ReadBufferedFile(const char *name)
216 {
217 struct BufferedFile *BF;
218 union {
219 byte *b;
220 void *v;
221 } buffer;
222
223 /*
224 * input verification
225 */
226
227 if(!name)
228 {
229 return(NULL);
230 }
231
232 /*
233 * Allocate control struct.
234 */
235
236 BF = ri.Z_Malloc(sizeof(struct BufferedFile));
237 if(!BF)
238 {
239 return(NULL);
240 }
241
242 /*
243 * Initialize the structs components.
244 */
245
246 BF->Length = 0;
247 BF->Buffer = NULL;
248 BF->Ptr = NULL;
249 BF->BytesLeft = 0;
250
251 /*
252 * Read the file.
253 */
254
255 BF->Length = ri.FS_ReadFile((char *) name, &buffer.v);
256 BF->Buffer = buffer.b;
257
258 /*
259 * Did we get it? Is it big enough?
260 */
261
262 if(!(BF->Buffer && (BF->Length > 0)))
263 {
264 ri.Free(BF);
265
266 return(NULL);
267 }
268
269 /*
270 * Set the pointers and counters.
271 */
272
273 BF->Ptr = BF->Buffer;
274 BF->BytesLeft = BF->Length;
275
276 return(BF);
277 }
278
279 /*
280 * Close a buffered file.
281 */
282
CloseBufferedFile(struct BufferedFile * BF)283 static void CloseBufferedFile(struct BufferedFile *BF)
284 {
285 if(BF)
286 {
287 if(BF->Buffer)
288 {
289 ri.FS_FreeFile(BF->Buffer);
290 }
291
292 ri.Free(BF);
293 }
294 }
295
296 /*
297 * Get a pointer to the requested bytes.
298 */
299
BufferedFileRead(struct BufferedFile * BF,unsigned Length)300 static void *BufferedFileRead(struct BufferedFile *BF, unsigned Length)
301 {
302 void *RetVal;
303
304 /*
305 * input verification
306 */
307
308 if(!(BF && Length))
309 {
310 return(NULL);
311 }
312
313 /*
314 * not enough bytes left
315 */
316
317 if(Length > BF->BytesLeft)
318 {
319 return(NULL);
320 }
321
322 /*
323 * the pointer to the requested data
324 */
325
326 RetVal = BF->Ptr;
327
328 /*
329 * Raise the pointer and counter.
330 */
331
332 BF->Ptr += Length;
333 BF->BytesLeft -= Length;
334
335 return(RetVal);
336 }
337
338 /*
339 * Rewind the buffer.
340 */
341
BufferedFileRewind(struct BufferedFile * BF,unsigned Offset)342 static qboolean BufferedFileRewind(struct BufferedFile *BF, unsigned Offset)
343 {
344 unsigned BytesRead;
345
346 /*
347 * input verification
348 */
349
350 if(!BF)
351 {
352 return(qfalse);
353 }
354
355 /*
356 * special trick to rewind to the beginning of the buffer
357 */
358
359 if(Offset == (unsigned)-1)
360 {
361 BF->Ptr = BF->Buffer;
362 BF->BytesLeft = BF->Length;
363
364 return(qtrue);
365 }
366
367 /*
368 * How many bytes do we have already read?
369 */
370
371 BytesRead = BF->Ptr - BF->Buffer;
372
373 /*
374 * We can only rewind to the beginning of the BufferedFile.
375 */
376
377 if(Offset > BytesRead)
378 {
379 return(qfalse);
380 }
381
382 /*
383 * lower the pointer and counter.
384 */
385
386 BF->Ptr -= Offset;
387 BF->BytesLeft += Offset;
388
389 return(qtrue);
390 }
391
392 /*
393 * Skip some bytes.
394 */
395
BufferedFileSkip(struct BufferedFile * BF,unsigned Offset)396 static qboolean BufferedFileSkip(struct BufferedFile *BF, unsigned Offset)
397 {
398 /*
399 * input verification
400 */
401
402 if(!BF)
403 {
404 return(qfalse);
405 }
406
407 /*
408 * We can only skip to the end of the BufferedFile.
409 */
410
411 if(Offset > BF->BytesLeft)
412 {
413 return(qfalse);
414 }
415
416 /*
417 * lower the pointer and counter.
418 */
419
420 BF->Ptr += Offset;
421 BF->BytesLeft -= Offset;
422
423 return(qtrue);
424 }
425
426 /*
427 * Find a chunk
428 */
429
FindChunk(struct BufferedFile * BF,uint32_t ChunkType)430 static qboolean FindChunk(struct BufferedFile *BF, uint32_t ChunkType)
431 {
432 struct PNG_ChunkHeader *CH;
433
434 uint32_t Length;
435 uint32_t Type;
436
437 /*
438 * input verification
439 */
440
441 if(!BF)
442 {
443 return(qfalse);
444 }
445
446 /*
447 * cycle trough the chunks
448 */
449
450 while(qtrue)
451 {
452 /*
453 * Read the chunk-header.
454 */
455
456 CH = BufferedFileRead(BF, PNG_ChunkHeader_Size);
457 if(!CH)
458 {
459 return(qfalse);
460 }
461
462 /*
463 * Do not swap the original types
464 * they might be needed later.
465 */
466
467 Length = BigLong(CH->Length);
468 Type = BigLong(CH->Type);
469
470 /*
471 * We found it!
472 */
473
474 if(Type == ChunkType)
475 {
476 /*
477 * Rewind to the start of the chunk.
478 */
479
480 BufferedFileRewind(BF, PNG_ChunkHeader_Size);
481
482 break;
483 }
484 else
485 {
486 /*
487 * Skip the rest of the chunk.
488 */
489
490 if(Length)
491 {
492 if(!BufferedFileSkip(BF, Length + PNG_ChunkCRC_Size))
493 {
494 return(qfalse);
495 }
496 }
497 }
498 }
499
500 return(qtrue);
501 }
502
503 /*
504 * Decompress all IDATs
505 */
506
DecompressIDATs(struct BufferedFile * BF,uint8_t ** Buffer)507 static uint32_t DecompressIDATs(struct BufferedFile *BF, uint8_t **Buffer)
508 {
509 uint8_t *DecompressedData;
510 uint32_t DecompressedDataLength;
511
512 uint8_t *CompressedData;
513 uint8_t *CompressedDataPtr;
514 uint32_t CompressedDataLength;
515
516 struct PNG_ChunkHeader *CH;
517
518 uint32_t Length;
519 uint32_t Type;
520
521 int BytesToRewind;
522
523 int32_t puffResult;
524 uint8_t *puffDest;
525 uint32_t puffDestLen;
526 uint8_t *puffSrc;
527 uint32_t puffSrcLen;
528
529 /*
530 * input verification
531 */
532
533 if(!(BF && Buffer))
534 {
535 return(-1);
536 }
537
538 /*
539 * some zeroing
540 */
541
542 DecompressedData = NULL;
543 *Buffer = DecompressedData;
544
545 CompressedData = NULL;
546 CompressedDataLength = 0;
547
548 BytesToRewind = 0;
549
550 /*
551 * Find the first IDAT chunk.
552 */
553
554 if(!FindChunk(BF, PNG_ChunkType_IDAT))
555 {
556 return(-1);
557 }
558
559 /*
560 * Count the size of the uncompressed data
561 */
562
563 while(qtrue)
564 {
565 /*
566 * Read chunk header
567 */
568
569 CH = BufferedFileRead(BF, PNG_ChunkHeader_Size);
570 if(!CH)
571 {
572 /*
573 * Rewind to the start of this adventure
574 * and return unsuccessfull
575 */
576
577 BufferedFileRewind(BF, BytesToRewind);
578
579 return(-1);
580 }
581
582 /*
583 * Length and Type of chunk
584 */
585
586 Length = BigLong(CH->Length);
587 Type = BigLong(CH->Type);
588
589 /*
590 * We have reached the end of the IDAT chunks
591 */
592
593 if(!(Type == PNG_ChunkType_IDAT))
594 {
595 BufferedFileRewind(BF, PNG_ChunkHeader_Size);
596
597 break;
598 }
599
600 /*
601 * Add chunk header to count.
602 */
603
604 BytesToRewind += PNG_ChunkHeader_Size;
605
606 /*
607 * Skip to next chunk
608 */
609
610 if(Length)
611 {
612 if(!BufferedFileSkip(BF, Length + PNG_ChunkCRC_Size))
613 {
614 BufferedFileRewind(BF, BytesToRewind);
615
616 return(-1);
617 }
618
619 BytesToRewind += Length + PNG_ChunkCRC_Size;
620 CompressedDataLength += Length;
621 }
622 }
623
624 BufferedFileRewind(BF, BytesToRewind);
625
626 CompressedData = ri.Z_Malloc(CompressedDataLength);
627 if(!CompressedData)
628 {
629 return(-1);
630 }
631
632 CompressedDataPtr = CompressedData;
633
634 /*
635 * Collect the compressed Data
636 */
637
638 while(qtrue)
639 {
640 /*
641 * Read chunk header
642 */
643
644 CH = BufferedFileRead(BF, PNG_ChunkHeader_Size);
645 if(!CH)
646 {
647 ri.Free(CompressedData);
648
649 return(-1);
650 }
651
652 /*
653 * Length and Type of chunk
654 */
655
656 Length = BigLong(CH->Length);
657 Type = BigLong(CH->Type);
658
659 /*
660 * We have reached the end of the IDAT chunks
661 */
662
663 if(!(Type == PNG_ChunkType_IDAT))
664 {
665 BufferedFileRewind(BF, PNG_ChunkHeader_Size);
666
667 break;
668 }
669
670 /*
671 * Copy the Data
672 */
673
674 if(Length)
675 {
676 uint8_t *OrigCompressedData;
677
678 OrigCompressedData = BufferedFileRead(BF, Length);
679 if(!OrigCompressedData)
680 {
681 ri.Free(CompressedData);
682
683 return(-1);
684 }
685
686 if(!BufferedFileSkip(BF, PNG_ChunkCRC_Size))
687 {
688 ri.Free(CompressedData);
689
690 return(-1);
691 }
692
693 memcpy(CompressedDataPtr, OrigCompressedData, Length);
694 CompressedDataPtr += Length;
695 }
696 }
697
698 /*
699 * Let puff() calculate the decompressed data length.
700 */
701
702 puffDest = NULL;
703 puffDestLen = 0;
704
705 /*
706 * The zlib header and checkvalue don't belong to the compressed data.
707 */
708
709 puffSrc = CompressedData + PNG_ZlibHeader_Size;
710 puffSrcLen = CompressedDataLength - PNG_ZlibHeader_Size - PNG_ZlibCheckValue_Size;
711
712 /*
713 * first puff() to calculate the size of the uncompressed data
714 */
715
716 puffResult = puff(puffDest, &puffDestLen, puffSrc, &puffSrcLen);
717 if(!((puffResult == 0) && (puffDestLen > 0)))
718 {
719 ri.Free(CompressedData);
720
721 return(-1);
722 }
723
724 /*
725 * Allocate the buffer for the uncompressed data.
726 */
727
728 DecompressedData = ri.Z_Malloc(puffDestLen);
729 if(!DecompressedData)
730 {
731 ri.Free(CompressedData);
732
733 return(-1);
734 }
735
736 /*
737 * Set the input again in case something was changed by the last puff() .
738 */
739
740 puffDest = DecompressedData;
741 puffSrc = CompressedData + PNG_ZlibHeader_Size;
742 puffSrcLen = CompressedDataLength - PNG_ZlibHeader_Size - PNG_ZlibCheckValue_Size;
743
744 /*
745 * decompression puff()
746 */
747
748 puffResult = puff(puffDest, &puffDestLen, puffSrc, &puffSrcLen);
749
750 /*
751 * The compressed data is not needed anymore.
752 */
753
754 ri.Free(CompressedData);
755
756 /*
757 * Check if the last puff() was successfull.
758 */
759
760 if(!((puffResult == 0) && (puffDestLen > 0)))
761 {
762 ri.Free(DecompressedData);
763
764 return(-1);
765 }
766
767 /*
768 * Set the output of this function.
769 */
770
771 DecompressedDataLength = puffDestLen;
772 *Buffer = DecompressedData;
773
774 return(DecompressedDataLength);
775 }
776
777 /*
778 * the Paeth predictor
779 */
780
PredictPaeth(uint8_t a,uint8_t b,uint8_t c)781 static uint8_t PredictPaeth(uint8_t a, uint8_t b, uint8_t c)
782 {
783 /*
784 * a == Left
785 * b == Up
786 * c == UpLeft
787 */
788
789 uint8_t Pr;
790 int p;
791 int pa, pb, pc;
792
793 p = ((int) a) + ((int) b) - ((int) c);
794 pa = abs(p - ((int) a));
795 pb = abs(p - ((int) b));
796 pc = abs(p - ((int) c));
797
798 if((pa <= pb) && (pa <= pc))
799 {
800 Pr = a;
801 }
802 else if(pb <= pc)
803 {
804 Pr = b;
805 }
806 else
807 {
808 Pr = c;
809 }
810
811 return(Pr);
812
813 }
814
815 /*
816 * Reverse the filters.
817 */
818
UnfilterImage(uint8_t * DecompressedData,uint32_t ImageHeight,uint32_t BytesPerScanline,uint32_t BytesPerPixel)819 static qboolean UnfilterImage(uint8_t *DecompressedData,
820 uint32_t ImageHeight,
821 uint32_t BytesPerScanline,
822 uint32_t BytesPerPixel)
823 {
824 uint8_t *DecompPtr;
825 uint8_t FilterType;
826 uint8_t *PixelLeft, *PixelUp, *PixelUpLeft;
827 uint32_t w, h, p;
828
829 /*
830 * some zeros for the filters
831 */
832
833 uint8_t Zeros[8] = {0, 0, 0, 0, 0, 0, 0, 0};
834
835 /*
836 * input verification
837 */
838
839 if(!(DecompressedData && BytesPerPixel))
840 {
841 return(qfalse);
842 }
843
844 /*
845 * ImageHeight and BytesPerScanline can be zero in small interlaced images.
846 */
847
848 if((!ImageHeight) || (!BytesPerScanline))
849 {
850 return(qtrue);
851 }
852
853 /*
854 * Set the pointer to the start of the decompressed Data.
855 */
856
857 DecompPtr = DecompressedData;
858
859 /*
860 * Un-filtering is done in place.
861 */
862
863 /*
864 * Go trough all scanlines.
865 */
866
867 for(h = 0; h < ImageHeight; h++)
868 {
869 /*
870 * Every scanline starts with a FilterType byte.
871 */
872
873 FilterType = *DecompPtr;
874 DecompPtr++;
875
876 /*
877 * Left pixel of the first byte in a scanline is zero.
878 */
879
880 PixelLeft = Zeros;
881
882 /*
883 * Set PixelUp to previous line only if we are on the second line or above.
884 *
885 * Plus one byte for the FilterType
886 */
887
888 if(h > 0)
889 {
890 PixelUp = DecompPtr - (BytesPerScanline + 1);
891 }
892 else
893 {
894 PixelUp = Zeros;
895 }
896
897 /*
898 * The pixel left to the first pixel of the previous scanline is zero too.
899 */
900
901 PixelUpLeft = Zeros;
902
903 /*
904 * Cycle trough all pixels of the scanline.
905 */
906
907 for(w = 0; w < (BytesPerScanline / BytesPerPixel); w++)
908 {
909 /*
910 * Cycle trough the bytes of the pixel.
911 */
912
913 for(p = 0; p < BytesPerPixel; p++)
914 {
915 switch(FilterType)
916 {
917 case PNG_FilterType_None :
918 {
919 /*
920 * The byte is unfiltered.
921 */
922
923 break;
924 }
925
926 case PNG_FilterType_Sub :
927 {
928 DecompPtr[p] += PixelLeft[p];
929
930 break;
931 }
932
933 case PNG_FilterType_Up :
934 {
935 DecompPtr[p] += PixelUp[p];
936
937 break;
938 }
939
940 case PNG_FilterType_Average :
941 {
942 DecompPtr[p] += ((uint8_t) ((((uint16_t) PixelLeft[p]) + ((uint16_t) PixelUp[p])) / 2));
943
944 break;
945 }
946
947 case PNG_FilterType_Paeth :
948 {
949 DecompPtr[p] += PredictPaeth(PixelLeft[p], PixelUp[p], PixelUpLeft[p]);
950
951 break;
952 }
953
954 default :
955 {
956 return(qfalse);
957 }
958 }
959 }
960
961 PixelLeft = DecompPtr;
962
963 /*
964 * We only have an upleft pixel if we are on the second line or above.
965 */
966
967 if(h > 0)
968 {
969 PixelUpLeft = DecompPtr - (BytesPerScanline + 1);
970 }
971
972 /*
973 * Skip to the next pixel.
974 */
975
976 DecompPtr += BytesPerPixel;
977
978 /*
979 * We only have a previous line if we are on the second line and above.
980 */
981
982 if(h > 0)
983 {
984 PixelUp = DecompPtr - (BytesPerScanline + 1);
985 }
986 }
987 }
988
989 return(qtrue);
990 }
991
992 /*
993 * Convert a raw input pixel to Quake 3 RGA format.
994 */
995
ConvertPixel(struct PNG_Chunk_IHDR * IHDR,byte * OutPtr,uint8_t * DecompPtr,qboolean HasTransparentColour,uint8_t * TransparentColour,uint8_t * OutPal)996 static qboolean ConvertPixel(struct PNG_Chunk_IHDR *IHDR,
997 byte *OutPtr,
998 uint8_t *DecompPtr,
999 qboolean HasTransparentColour,
1000 uint8_t *TransparentColour,
1001 uint8_t *OutPal)
1002 {
1003 /*
1004 * input verification
1005 */
1006
1007 if(!(IHDR && OutPtr && DecompPtr && TransparentColour && OutPal))
1008 {
1009 return(qfalse);
1010 }
1011
1012 switch(IHDR->ColourType)
1013 {
1014 case PNG_ColourType_Grey :
1015 {
1016 switch(IHDR->BitDepth)
1017 {
1018 case PNG_BitDepth_1 :
1019 case PNG_BitDepth_2 :
1020 case PNG_BitDepth_4 :
1021 {
1022 uint8_t Step;
1023 uint8_t GreyValue;
1024
1025 Step = 0xFF / ((1 << IHDR->BitDepth) - 1);
1026
1027 GreyValue = DecompPtr[0] * Step;
1028
1029 OutPtr[0] = GreyValue;
1030 OutPtr[1] = GreyValue;
1031 OutPtr[2] = GreyValue;
1032 OutPtr[3] = 0xFF;
1033
1034 /*
1035 * Grey supports full transparency for one specified colour
1036 */
1037
1038 if(HasTransparentColour)
1039 {
1040 if(TransparentColour[1] == DecompPtr[0])
1041 {
1042 OutPtr[3] = 0x00;
1043 }
1044 }
1045
1046
1047 break;
1048 }
1049
1050 case PNG_BitDepth_8 :
1051 case PNG_BitDepth_16 :
1052 {
1053 OutPtr[0] = DecompPtr[0];
1054 OutPtr[1] = DecompPtr[0];
1055 OutPtr[2] = DecompPtr[0];
1056 OutPtr[3] = 0xFF;
1057
1058 /*
1059 * Grey supports full transparency for one specified colour
1060 */
1061
1062 if(HasTransparentColour)
1063 {
1064 if(IHDR->BitDepth == PNG_BitDepth_8)
1065 {
1066 if(TransparentColour[1] == DecompPtr[0])
1067 {
1068 OutPtr[3] = 0x00;
1069 }
1070 }
1071 else
1072 {
1073 if((TransparentColour[0] == DecompPtr[0]) && (TransparentColour[1] == DecompPtr[1]))
1074 {
1075 OutPtr[3] = 0x00;
1076 }
1077 }
1078 }
1079
1080 break;
1081 }
1082
1083 default :
1084 {
1085 return(qfalse);
1086 }
1087 }
1088
1089 break;
1090 }
1091
1092 case PNG_ColourType_True :
1093 {
1094 switch(IHDR->BitDepth)
1095 {
1096 case PNG_BitDepth_8 :
1097 {
1098 OutPtr[0] = DecompPtr[0];
1099 OutPtr[1] = DecompPtr[1];
1100 OutPtr[2] = DecompPtr[2];
1101 OutPtr[3] = 0xFF;
1102
1103 /*
1104 * True supports full transparency for one specified colour
1105 */
1106
1107 if(HasTransparentColour)
1108 {
1109 if((TransparentColour[1] == DecompPtr[0]) &&
1110 (TransparentColour[3] == DecompPtr[1]) &&
1111 (TransparentColour[5] == DecompPtr[2]))
1112 {
1113 OutPtr[3] = 0x00;
1114 }
1115 }
1116
1117 break;
1118 }
1119
1120 case PNG_BitDepth_16 :
1121 {
1122 /*
1123 * We use only the upper byte.
1124 */
1125
1126 OutPtr[0] = DecompPtr[0];
1127 OutPtr[1] = DecompPtr[2];
1128 OutPtr[2] = DecompPtr[4];
1129 OutPtr[3] = 0xFF;
1130
1131 /*
1132 * True supports full transparency for one specified colour
1133 */
1134
1135 if(HasTransparentColour)
1136 {
1137 if((TransparentColour[0] == DecompPtr[0]) && (TransparentColour[1] == DecompPtr[1]) &&
1138 (TransparentColour[2] == DecompPtr[2]) && (TransparentColour[3] == DecompPtr[3]) &&
1139 (TransparentColour[4] == DecompPtr[4]) && (TransparentColour[5] == DecompPtr[5]))
1140 {
1141 OutPtr[3] = 0x00;
1142 }
1143 }
1144
1145 break;
1146 }
1147
1148 default :
1149 {
1150 return(qfalse);
1151 }
1152 }
1153
1154 break;
1155 }
1156
1157 case PNG_ColourType_Indexed :
1158 {
1159 OutPtr[0] = OutPal[DecompPtr[0] * Q3IMAGE_BYTESPERPIXEL + 0];
1160 OutPtr[1] = OutPal[DecompPtr[0] * Q3IMAGE_BYTESPERPIXEL + 1];
1161 OutPtr[2] = OutPal[DecompPtr[0] * Q3IMAGE_BYTESPERPIXEL + 2];
1162 OutPtr[3] = OutPal[DecompPtr[0] * Q3IMAGE_BYTESPERPIXEL + 3];
1163
1164 break;
1165 }
1166
1167 case PNG_ColourType_GreyAlpha :
1168 {
1169 switch(IHDR->BitDepth)
1170 {
1171 case PNG_BitDepth_8 :
1172 {
1173 OutPtr[0] = DecompPtr[0];
1174 OutPtr[1] = DecompPtr[0];
1175 OutPtr[2] = DecompPtr[0];
1176 OutPtr[3] = DecompPtr[1];
1177
1178 break;
1179 }
1180
1181 case PNG_BitDepth_16 :
1182 {
1183 /*
1184 * We use only the upper byte.
1185 */
1186
1187 OutPtr[0] = DecompPtr[0];
1188 OutPtr[1] = DecompPtr[0];
1189 OutPtr[2] = DecompPtr[0];
1190 OutPtr[3] = DecompPtr[2];
1191
1192 break;
1193 }
1194
1195 default :
1196 {
1197 return(qfalse);
1198 }
1199 }
1200
1201 break;
1202 }
1203
1204 case PNG_ColourType_TrueAlpha :
1205 {
1206 switch(IHDR->BitDepth)
1207 {
1208 case PNG_BitDepth_8 :
1209 {
1210 OutPtr[0] = DecompPtr[0];
1211 OutPtr[1] = DecompPtr[1];
1212 OutPtr[2] = DecompPtr[2];
1213 OutPtr[3] = DecompPtr[3];
1214
1215 break;
1216 }
1217
1218 case PNG_BitDepth_16 :
1219 {
1220 /*
1221 * We use only the upper byte.
1222 */
1223
1224 OutPtr[0] = DecompPtr[0];
1225 OutPtr[1] = DecompPtr[2];
1226 OutPtr[2] = DecompPtr[4];
1227 OutPtr[3] = DecompPtr[6];
1228
1229 break;
1230 }
1231
1232 default :
1233 {
1234 return(qfalse);
1235 }
1236 }
1237
1238 break;
1239 }
1240
1241 default :
1242 {
1243 return(qfalse);
1244 }
1245 }
1246
1247 return(qtrue);
1248 }
1249
1250
1251 /*
1252 * Decode a non-interlaced image.
1253 */
1254
DecodeImageNonInterlaced(struct PNG_Chunk_IHDR * IHDR,byte * OutBuffer,uint8_t * DecompressedData,uint32_t DecompressedDataLength,qboolean HasTransparentColour,uint8_t * TransparentColour,uint8_t * OutPal)1255 static qboolean DecodeImageNonInterlaced(struct PNG_Chunk_IHDR *IHDR,
1256 byte *OutBuffer,
1257 uint8_t *DecompressedData,
1258 uint32_t DecompressedDataLength,
1259 qboolean HasTransparentColour,
1260 uint8_t *TransparentColour,
1261 uint8_t *OutPal)
1262 {
1263 uint32_t IHDR_Width;
1264 uint32_t IHDR_Height;
1265 uint32_t BytesPerScanline, BytesPerPixel, PixelsPerByte;
1266 uint32_t w, h, p;
1267 byte *OutPtr;
1268 uint8_t *DecompPtr;
1269
1270 /*
1271 * input verification
1272 */
1273
1274 if(!(IHDR && OutBuffer && DecompressedData && DecompressedDataLength && TransparentColour && OutPal))
1275 {
1276 return(qfalse);
1277 }
1278
1279 /*
1280 * byte swapping
1281 */
1282
1283 IHDR_Width = BigLong(IHDR->Width);
1284 IHDR_Height = BigLong(IHDR->Height);
1285
1286 /*
1287 * information for un-filtering
1288 */
1289
1290 switch(IHDR->ColourType)
1291 {
1292 case PNG_ColourType_Grey :
1293 {
1294 switch(IHDR->BitDepth)
1295 {
1296 case PNG_BitDepth_1 :
1297 case PNG_BitDepth_2 :
1298 case PNG_BitDepth_4 :
1299 {
1300 BytesPerPixel = 1;
1301 PixelsPerByte = 8 / IHDR->BitDepth;
1302
1303 break;
1304 }
1305
1306 case PNG_BitDepth_8 :
1307 case PNG_BitDepth_16 :
1308 {
1309 BytesPerPixel = (IHDR->BitDepth / 8) * PNG_NumColourComponents_Grey;
1310 PixelsPerByte = 1;
1311
1312 break;
1313 }
1314
1315 default :
1316 {
1317 return(qfalse);
1318 }
1319 }
1320
1321 break;
1322 }
1323
1324 case PNG_ColourType_True :
1325 {
1326 switch(IHDR->BitDepth)
1327 {
1328 case PNG_BitDepth_8 :
1329 case PNG_BitDepth_16 :
1330 {
1331 BytesPerPixel = (IHDR->BitDepth / 8) * PNG_NumColourComponents_True;
1332 PixelsPerByte = 1;
1333
1334 break;
1335 }
1336
1337 default :
1338 {
1339 return(qfalse);
1340 }
1341 }
1342
1343 break;
1344 }
1345
1346 case PNG_ColourType_Indexed :
1347 {
1348 switch(IHDR->BitDepth)
1349 {
1350 case PNG_BitDepth_1 :
1351 case PNG_BitDepth_2 :
1352 case PNG_BitDepth_4 :
1353 {
1354 BytesPerPixel = 1;
1355 PixelsPerByte = 8 / IHDR->BitDepth;
1356
1357 break;
1358 }
1359
1360 case PNG_BitDepth_8 :
1361 {
1362 BytesPerPixel = PNG_NumColourComponents_Indexed;
1363 PixelsPerByte = 1;
1364
1365 break;
1366 }
1367
1368 default :
1369 {
1370 return(qfalse);
1371 }
1372 }
1373
1374 break;
1375 }
1376
1377 case PNG_ColourType_GreyAlpha :
1378 {
1379 switch(IHDR->BitDepth)
1380 {
1381 case PNG_BitDepth_8 :
1382 case PNG_BitDepth_16 :
1383 {
1384 BytesPerPixel = (IHDR->BitDepth / 8) * PNG_NumColourComponents_GreyAlpha;
1385 PixelsPerByte = 1;
1386
1387 break;
1388 }
1389
1390 default :
1391 {
1392 return(qfalse);
1393 }
1394 }
1395
1396 break;
1397 }
1398
1399 case PNG_ColourType_TrueAlpha :
1400 {
1401 switch(IHDR->BitDepth)
1402 {
1403 case PNG_BitDepth_8 :
1404 case PNG_BitDepth_16 :
1405 {
1406 BytesPerPixel = (IHDR->BitDepth / 8) * PNG_NumColourComponents_TrueAlpha;
1407 PixelsPerByte = 1;
1408
1409 break;
1410 }
1411
1412 default :
1413 {
1414 return(qfalse);
1415 }
1416 }
1417
1418 break;
1419 }
1420
1421 default :
1422 {
1423 return(qfalse);
1424 }
1425 }
1426
1427 /*
1428 * Calculate the size of one scanline
1429 */
1430
1431 BytesPerScanline = (IHDR_Width * BytesPerPixel + (PixelsPerByte - 1)) / PixelsPerByte;
1432
1433 /*
1434 * Check if we have enough data for the whole image.
1435 */
1436
1437 if(!(DecompressedDataLength == ((BytesPerScanline + 1) * IHDR_Height)))
1438 {
1439 return(qfalse);
1440 }
1441
1442 /*
1443 * Unfilter the image.
1444 */
1445
1446 if(!UnfilterImage(DecompressedData, IHDR_Height, BytesPerScanline, BytesPerPixel))
1447 {
1448 return(qfalse);
1449 }
1450
1451 /*
1452 * Set the working pointers to the beginning of the buffers.
1453 */
1454
1455 OutPtr = OutBuffer;
1456 DecompPtr = DecompressedData;
1457
1458 /*
1459 * Create the output image.
1460 */
1461
1462 for(h = 0; h < IHDR_Height; h++)
1463 {
1464 /*
1465 * Count the pixels on the scanline for those multipixel bytes
1466 */
1467
1468 uint32_t CurrPixel;
1469
1470 /*
1471 * skip FilterType
1472 */
1473
1474 DecompPtr++;
1475
1476 /*
1477 * Reset the pixel count.
1478 */
1479
1480 CurrPixel = 0;
1481
1482 for(w = 0; w < (BytesPerScanline / BytesPerPixel); w++)
1483 {
1484 if(PixelsPerByte > 1)
1485 {
1486 uint8_t Mask;
1487 uint32_t Shift;
1488 uint8_t SinglePixel;
1489
1490 for(p = 0; p < PixelsPerByte; p++)
1491 {
1492 if(CurrPixel < IHDR_Width)
1493 {
1494 Mask = (1 << IHDR->BitDepth) - 1;
1495 Shift = (PixelsPerByte - 1 - p) * IHDR->BitDepth;
1496
1497 SinglePixel = ((DecompPtr[0] & (Mask << Shift)) >> Shift);
1498
1499 if(!ConvertPixel(IHDR, OutPtr, &SinglePixel, HasTransparentColour, TransparentColour, OutPal))
1500 {
1501 return(qfalse);
1502 }
1503
1504 OutPtr += Q3IMAGE_BYTESPERPIXEL;
1505 CurrPixel++;
1506 }
1507 }
1508
1509 }
1510 else
1511 {
1512 if(!ConvertPixel(IHDR, OutPtr, DecompPtr, HasTransparentColour, TransparentColour, OutPal))
1513 {
1514 return(qfalse);
1515 }
1516
1517
1518 OutPtr += Q3IMAGE_BYTESPERPIXEL;
1519 }
1520
1521 DecompPtr += BytesPerPixel;
1522 }
1523 }
1524
1525 return(qtrue);
1526 }
1527
1528 /*
1529 * Decode an interlaced image.
1530 */
1531
DecodeImageInterlaced(struct PNG_Chunk_IHDR * IHDR,byte * OutBuffer,uint8_t * DecompressedData,uint32_t DecompressedDataLength,qboolean HasTransparentColour,uint8_t * TransparentColour,uint8_t * OutPal)1532 static qboolean DecodeImageInterlaced(struct PNG_Chunk_IHDR *IHDR,
1533 byte *OutBuffer,
1534 uint8_t *DecompressedData,
1535 uint32_t DecompressedDataLength,
1536 qboolean HasTransparentColour,
1537 uint8_t *TransparentColour,
1538 uint8_t *OutPal)
1539 {
1540 uint32_t IHDR_Width;
1541 uint32_t IHDR_Height;
1542 uint32_t BytesPerScanline[PNG_Adam7_NumPasses], BytesPerPixel, PixelsPerByte;
1543 uint32_t PassWidth[PNG_Adam7_NumPasses], PassHeight[PNG_Adam7_NumPasses];
1544 uint32_t WSkip[PNG_Adam7_NumPasses], WOffset[PNG_Adam7_NumPasses], HSkip[PNG_Adam7_NumPasses], HOffset[PNG_Adam7_NumPasses];
1545 uint32_t w, h, p, a;
1546 byte *OutPtr;
1547 uint8_t *DecompPtr;
1548 uint32_t TargetLength;
1549
1550 /*
1551 * input verification
1552 */
1553
1554 if(!(IHDR && OutBuffer && DecompressedData && DecompressedDataLength && TransparentColour && OutPal))
1555 {
1556 return(qfalse);
1557 }
1558
1559 /*
1560 * byte swapping
1561 */
1562
1563 IHDR_Width = BigLong(IHDR->Width);
1564 IHDR_Height = BigLong(IHDR->Height);
1565
1566 /*
1567 * Skip and Offset for the passes.
1568 */
1569
1570 WSkip[0] = 8;
1571 WOffset[0] = 0;
1572 HSkip[0] = 8;
1573 HOffset[0] = 0;
1574
1575 WSkip[1] = 8;
1576 WOffset[1] = 4;
1577 HSkip[1] = 8;
1578 HOffset[1] = 0;
1579
1580 WSkip[2] = 4;
1581 WOffset[2] = 0;
1582 HSkip[2] = 8;
1583 HOffset[2] = 4;
1584
1585 WSkip[3] = 4;
1586 WOffset[3] = 2;
1587 HSkip[3] = 4;
1588 HOffset[3] = 0;
1589
1590 WSkip[4] = 2;
1591 WOffset[4] = 0;
1592 HSkip[4] = 4;
1593 HOffset[4] = 2;
1594
1595 WSkip[5] = 2;
1596 WOffset[5] = 1;
1597 HSkip[5] = 2;
1598 HOffset[5] = 0;
1599
1600 WSkip[6] = 1;
1601 WOffset[6] = 0;
1602 HSkip[6] = 2;
1603 HOffset[6] = 1;
1604
1605 /*
1606 * Calculate the sizes of the passes.
1607 */
1608
1609 PassWidth[0] = (IHDR_Width + 7) / 8;
1610 PassHeight[0] = (IHDR_Height + 7) / 8;
1611
1612 PassWidth[1] = (IHDR_Width + 3) / 8;
1613 PassHeight[1] = (IHDR_Height + 7) / 8;
1614
1615 PassWidth[2] = (IHDR_Width + 3) / 4;
1616 PassHeight[2] = (IHDR_Height + 3) / 8;
1617
1618 PassWidth[3] = (IHDR_Width + 1) / 4;
1619 PassHeight[3] = (IHDR_Height + 3) / 4;
1620
1621 PassWidth[4] = (IHDR_Width + 1) / 2;
1622 PassHeight[4] = (IHDR_Height + 1) / 4;
1623
1624 PassWidth[5] = (IHDR_Width + 0) / 2;
1625 PassHeight[5] = (IHDR_Height + 1) / 2;
1626
1627 PassWidth[6] = (IHDR_Width + 0) / 1;
1628 PassHeight[6] = (IHDR_Height + 0) / 2;
1629
1630 /*
1631 * information for un-filtering
1632 */
1633
1634 switch(IHDR->ColourType)
1635 {
1636 case PNG_ColourType_Grey :
1637 {
1638 switch(IHDR->BitDepth)
1639 {
1640 case PNG_BitDepth_1 :
1641 case PNG_BitDepth_2 :
1642 case PNG_BitDepth_4 :
1643 {
1644 BytesPerPixel = 1;
1645 PixelsPerByte = 8 / IHDR->BitDepth;
1646
1647 break;
1648 }
1649
1650 case PNG_BitDepth_8 :
1651 case PNG_BitDepth_16 :
1652 {
1653 BytesPerPixel = (IHDR->BitDepth / 8) * PNG_NumColourComponents_Grey;
1654 PixelsPerByte = 1;
1655
1656 break;
1657 }
1658
1659 default :
1660 {
1661 return(qfalse);
1662 }
1663 }
1664
1665 break;
1666 }
1667
1668 case PNG_ColourType_True :
1669 {
1670 switch(IHDR->BitDepth)
1671 {
1672 case PNG_BitDepth_8 :
1673 case PNG_BitDepth_16 :
1674 {
1675 BytesPerPixel = (IHDR->BitDepth / 8) * PNG_NumColourComponents_True;
1676 PixelsPerByte = 1;
1677
1678 break;
1679 }
1680
1681 default :
1682 {
1683 return(qfalse);
1684 }
1685 }
1686
1687 break;
1688 }
1689
1690 case PNG_ColourType_Indexed :
1691 {
1692 switch(IHDR->BitDepth)
1693 {
1694 case PNG_BitDepth_1 :
1695 case PNG_BitDepth_2 :
1696 case PNG_BitDepth_4 :
1697 {
1698 BytesPerPixel = 1;
1699 PixelsPerByte = 8 / IHDR->BitDepth;
1700
1701 break;
1702 }
1703
1704 case PNG_BitDepth_8 :
1705 {
1706 BytesPerPixel = PNG_NumColourComponents_Indexed;
1707 PixelsPerByte = 1;
1708
1709 break;
1710 }
1711
1712 default :
1713 {
1714 return(qfalse);
1715 }
1716 }
1717
1718 break;
1719 }
1720
1721 case PNG_ColourType_GreyAlpha :
1722 {
1723 switch(IHDR->BitDepth)
1724 {
1725 case PNG_BitDepth_8 :
1726 case PNG_BitDepth_16 :
1727 {
1728 BytesPerPixel = (IHDR->BitDepth / 8) * PNG_NumColourComponents_GreyAlpha;
1729 PixelsPerByte = 1;
1730
1731 break;
1732 }
1733
1734 default :
1735 {
1736 return(qfalse);
1737 }
1738 }
1739
1740 break;
1741 }
1742
1743 case PNG_ColourType_TrueAlpha :
1744 {
1745 switch(IHDR->BitDepth)
1746 {
1747 case PNG_BitDepth_8 :
1748 case PNG_BitDepth_16 :
1749 {
1750 BytesPerPixel = (IHDR->BitDepth / 8) * PNG_NumColourComponents_TrueAlpha;
1751 PixelsPerByte = 1;
1752
1753 break;
1754 }
1755
1756 default :
1757 {
1758 return(qfalse);
1759 }
1760 }
1761
1762 break;
1763 }
1764
1765 default :
1766 {
1767 return(qfalse);
1768 }
1769 }
1770
1771 /*
1772 * Calculate the size of the scanlines per pass
1773 */
1774
1775 for(a = 0; a < PNG_Adam7_NumPasses; a++)
1776 {
1777 BytesPerScanline[a] = (PassWidth[a] * BytesPerPixel + (PixelsPerByte - 1)) / PixelsPerByte;
1778 }
1779
1780 /*
1781 * Calculate the size of all passes
1782 */
1783
1784 TargetLength = 0;
1785
1786 for(a = 0; a < PNG_Adam7_NumPasses; a++)
1787 {
1788 TargetLength += ((BytesPerScanline[a] + (BytesPerScanline[a] ? 1 : 0)) * PassHeight[a]);
1789 }
1790
1791 /*
1792 * Check if we have enough data for the whole image.
1793 */
1794
1795 if(!(DecompressedDataLength == TargetLength))
1796 {
1797 return(qfalse);
1798 }
1799
1800 /*
1801 * Unfilter the image.
1802 */
1803
1804 DecompPtr = DecompressedData;
1805
1806 for(a = 0; a < PNG_Adam7_NumPasses; a++)
1807 {
1808 if(!UnfilterImage(DecompPtr, PassHeight[a], BytesPerScanline[a], BytesPerPixel))
1809 {
1810 return(qfalse);
1811 }
1812
1813 DecompPtr += ((BytesPerScanline[a] + (BytesPerScanline[a] ? 1 : 0)) * PassHeight[a]);
1814 }
1815
1816 /*
1817 * Set the working pointers to the beginning of the buffers.
1818 */
1819
1820 DecompPtr = DecompressedData;
1821
1822 /*
1823 * Create the output image.
1824 */
1825
1826 for(a = 0; a < PNG_Adam7_NumPasses; a++)
1827 {
1828 for(h = 0; h < PassHeight[a]; h++)
1829 {
1830 /*
1831 * Count the pixels on the scanline for those multipixel bytes
1832 */
1833
1834 uint32_t CurrPixel;
1835
1836 /*
1837 * skip FilterType
1838 * but only when the pass has a width bigger than zero
1839 */
1840
1841 if(BytesPerScanline[a])
1842 {
1843 DecompPtr++;
1844 }
1845
1846 /*
1847 * Reset the pixel count.
1848 */
1849
1850 CurrPixel = 0;
1851
1852 for(w = 0; w < (BytesPerScanline[a] / BytesPerPixel); w++)
1853 {
1854 if(PixelsPerByte > 1)
1855 {
1856 uint8_t Mask;
1857 uint32_t Shift;
1858 uint8_t SinglePixel;
1859
1860 for(p = 0; p < PixelsPerByte; p++)
1861 {
1862 if(CurrPixel < PassWidth[a])
1863 {
1864 Mask = (1 << IHDR->BitDepth) - 1;
1865 Shift = (PixelsPerByte - 1 - p) * IHDR->BitDepth;
1866
1867 SinglePixel = ((DecompPtr[0] & (Mask << Shift)) >> Shift);
1868
1869 OutPtr = OutBuffer + (((((h * HSkip[a]) + HOffset[a]) * IHDR_Width) + ((CurrPixel * WSkip[a]) + WOffset[a])) * Q3IMAGE_BYTESPERPIXEL);
1870
1871 if(!ConvertPixel(IHDR, OutPtr, &SinglePixel, HasTransparentColour, TransparentColour, OutPal))
1872 {
1873 return(qfalse);
1874 }
1875
1876 CurrPixel++;
1877 }
1878 }
1879
1880 }
1881 else
1882 {
1883 OutPtr = OutBuffer + (((((h * HSkip[a]) + HOffset[a]) * IHDR_Width) + ((w * WSkip[a]) + WOffset[a])) * Q3IMAGE_BYTESPERPIXEL);
1884
1885 if(!ConvertPixel(IHDR, OutPtr, DecompPtr, HasTransparentColour, TransparentColour, OutPal))
1886 {
1887 return(qfalse);
1888 }
1889 }
1890
1891 DecompPtr += BytesPerPixel;
1892 }
1893 }
1894 }
1895
1896 return(qtrue);
1897 }
1898
1899 /*
1900 * The PNG loader
1901 */
1902
R_LoadPNG(const char * name,byte ** pic,int * width,int * height)1903 void R_LoadPNG(const char *name, byte **pic, int *width, int *height)
1904 {
1905 struct BufferedFile *ThePNG;
1906 byte *OutBuffer;
1907 uint8_t *Signature;
1908 struct PNG_ChunkHeader *CH;
1909 uint32_t ChunkHeaderLength;
1910 uint32_t ChunkHeaderType;
1911 struct PNG_Chunk_IHDR *IHDR;
1912 uint32_t IHDR_Width;
1913 uint32_t IHDR_Height;
1914 PNG_ChunkCRC *CRC;
1915 uint8_t *InPal;
1916 uint8_t *DecompressedData;
1917 uint32_t DecompressedDataLength;
1918 uint32_t i;
1919
1920 /*
1921 * palette with 256 RGBA entries
1922 */
1923
1924 uint8_t OutPal[1024];
1925
1926 /*
1927 * transparent colour from the tRNS chunk
1928 */
1929
1930 qboolean HasTransparentColour = qfalse;
1931 uint8_t TransparentColour[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
1932
1933 /*
1934 * input verification
1935 */
1936
1937 if(!(name && pic))
1938 {
1939 return;
1940 }
1941
1942 /*
1943 * Zero out return values.
1944 */
1945
1946 *pic = NULL;
1947
1948 if(width)
1949 {
1950 *width = 0;
1951 }
1952
1953 if(height)
1954 {
1955 *height = 0;
1956 }
1957
1958 /*
1959 * Read the file.
1960 */
1961
1962 ThePNG = ReadBufferedFile(name);
1963 if(!ThePNG)
1964 {
1965 return;
1966 }
1967
1968 /*
1969 * Read the siganture of the file.
1970 */
1971
1972 Signature = BufferedFileRead(ThePNG, PNG_Signature_Size);
1973 if(!Signature)
1974 {
1975 CloseBufferedFile(ThePNG);
1976
1977 return;
1978 }
1979
1980 /*
1981 * Is it a PNG?
1982 */
1983
1984 if(memcmp(Signature, PNG_Signature, PNG_Signature_Size))
1985 {
1986 CloseBufferedFile(ThePNG);
1987
1988 return;
1989 }
1990
1991 /*
1992 * Read the first chunk-header.
1993 */
1994
1995 CH = BufferedFileRead(ThePNG, PNG_ChunkHeader_Size);
1996 if(!CH)
1997 {
1998 CloseBufferedFile(ThePNG);
1999
2000 return;
2001 }
2002
2003 /*
2004 * PNG multi-byte types are in Big Endian
2005 */
2006
2007 ChunkHeaderLength = BigLong(CH->Length);
2008 ChunkHeaderType = BigLong(CH->Type);
2009
2010 /*
2011 * Check if the first chunk is an IHDR.
2012 */
2013
2014 if(!((ChunkHeaderType == PNG_ChunkType_IHDR) && (ChunkHeaderLength == PNG_Chunk_IHDR_Size)))
2015 {
2016 CloseBufferedFile(ThePNG);
2017
2018 return;
2019 }
2020
2021 /*
2022 * Read the IHDR.
2023 */
2024
2025 IHDR = BufferedFileRead(ThePNG, PNG_Chunk_IHDR_Size);
2026 if(!IHDR)
2027 {
2028 CloseBufferedFile(ThePNG);
2029
2030 return;
2031 }
2032
2033 /*
2034 * Read the CRC for IHDR
2035 */
2036
2037 CRC = BufferedFileRead(ThePNG, PNG_ChunkCRC_Size);
2038 if(!CRC)
2039 {
2040 CloseBufferedFile(ThePNG);
2041
2042 return;
2043 }
2044
2045 /*
2046 * Here we could check the CRC if we wanted to.
2047 */
2048
2049 /*
2050 * multi-byte type swapping
2051 */
2052
2053 IHDR_Width = BigLong(IHDR->Width);
2054 IHDR_Height = BigLong(IHDR->Height);
2055
2056 /*
2057 * Check if Width and Height are valid.
2058 */
2059
2060 if(!((IHDR_Width > 0) && (IHDR_Height > 0))
2061 || IHDR_Width > INT_MAX / Q3IMAGE_BYTESPERPIXEL / IHDR_Height)
2062 {
2063 CloseBufferedFile(ThePNG);
2064
2065 ri.Printf( PRINT_WARNING, "%s: invalid image size\n", name );
2066
2067 return;
2068 }
2069
2070 /*
2071 * Do we need to check if the dimensions of the image are valid for Quake3?
2072 */
2073
2074 /*
2075 * Check if CompressionMethod and FilterMethod are valid.
2076 */
2077
2078 if(!((IHDR->CompressionMethod == PNG_CompressionMethod_0) && (IHDR->FilterMethod == PNG_FilterMethod_0)))
2079 {
2080 CloseBufferedFile(ThePNG);
2081
2082 return;
2083 }
2084
2085 /*
2086 * Check if InterlaceMethod is valid.
2087 */
2088
2089 if(!((IHDR->InterlaceMethod == PNG_InterlaceMethod_NonInterlaced) || (IHDR->InterlaceMethod == PNG_InterlaceMethod_Interlaced)))
2090 {
2091 CloseBufferedFile(ThePNG);
2092
2093 return;
2094 }
2095
2096 /*
2097 * Read palette for an indexed image.
2098 */
2099
2100 if(IHDR->ColourType == PNG_ColourType_Indexed)
2101 {
2102 /*
2103 * We need the palette first.
2104 */
2105
2106 if(!FindChunk(ThePNG, PNG_ChunkType_PLTE))
2107 {
2108 CloseBufferedFile(ThePNG);
2109
2110 return;
2111 }
2112
2113 /*
2114 * Read the chunk-header.
2115 */
2116
2117 CH = BufferedFileRead(ThePNG, PNG_ChunkHeader_Size);
2118 if(!CH)
2119 {
2120 CloseBufferedFile(ThePNG);
2121
2122 return;
2123 }
2124
2125 /*
2126 * PNG multi-byte types are in Big Endian
2127 */
2128
2129 ChunkHeaderLength = BigLong(CH->Length);
2130 ChunkHeaderType = BigLong(CH->Type);
2131
2132 /*
2133 * Check if the chunk is a PLTE.
2134 */
2135
2136 if(!(ChunkHeaderType == PNG_ChunkType_PLTE))
2137 {
2138 CloseBufferedFile(ThePNG);
2139
2140 return;
2141 }
2142
2143 /*
2144 * Check if Length is divisible by 3
2145 */
2146
2147 if(ChunkHeaderLength % 3)
2148 {
2149 CloseBufferedFile(ThePNG);
2150
2151 return;
2152 }
2153
2154 /*
2155 * Read the raw palette data
2156 */
2157
2158 InPal = BufferedFileRead(ThePNG, ChunkHeaderLength);
2159 if(!InPal)
2160 {
2161 CloseBufferedFile(ThePNG);
2162
2163 return;
2164 }
2165
2166 /*
2167 * Read the CRC for the palette
2168 */
2169
2170 CRC = BufferedFileRead(ThePNG, PNG_ChunkCRC_Size);
2171 if(!CRC)
2172 {
2173 CloseBufferedFile(ThePNG);
2174
2175 return;
2176 }
2177
2178 /*
2179 * Set some default values.
2180 */
2181
2182 for(i = 0; i < 256; i++)
2183 {
2184 OutPal[i * Q3IMAGE_BYTESPERPIXEL + 0] = 0x00;
2185 OutPal[i * Q3IMAGE_BYTESPERPIXEL + 1] = 0x00;
2186 OutPal[i * Q3IMAGE_BYTESPERPIXEL + 2] = 0x00;
2187 OutPal[i * Q3IMAGE_BYTESPERPIXEL + 3] = 0xFF;
2188 }
2189
2190 /*
2191 * Convert to the Quake3 RGBA-format.
2192 */
2193
2194 for(i = 0; i < (ChunkHeaderLength / 3); i++)
2195 {
2196 OutPal[i * Q3IMAGE_BYTESPERPIXEL + 0] = InPal[i*3+0];
2197 OutPal[i * Q3IMAGE_BYTESPERPIXEL + 1] = InPal[i*3+1];
2198 OutPal[i * Q3IMAGE_BYTESPERPIXEL + 2] = InPal[i*3+2];
2199 OutPal[i * Q3IMAGE_BYTESPERPIXEL + 3] = 0xFF;
2200 }
2201 }
2202
2203 /*
2204 * transparency information is sometimes stored in a tRNS chunk
2205 */
2206
2207 /*
2208 * Let's see if there is a tRNS chunk
2209 */
2210
2211 if(FindChunk(ThePNG, PNG_ChunkType_tRNS))
2212 {
2213 uint8_t *Trans;
2214
2215 /*
2216 * Read the chunk-header.
2217 */
2218
2219 CH = BufferedFileRead(ThePNG, PNG_ChunkHeader_Size);
2220 if(!CH)
2221 {
2222 CloseBufferedFile(ThePNG);
2223
2224 return;
2225 }
2226
2227 /*
2228 * PNG multi-byte types are in Big Endian
2229 */
2230
2231 ChunkHeaderLength = BigLong(CH->Length);
2232 ChunkHeaderType = BigLong(CH->Type);
2233
2234 /*
2235 * Check if the chunk is a tRNS.
2236 */
2237
2238 if(!(ChunkHeaderType == PNG_ChunkType_tRNS))
2239 {
2240 CloseBufferedFile(ThePNG);
2241
2242 return;
2243 }
2244
2245 /*
2246 * Read the transparency information.
2247 */
2248
2249 Trans = BufferedFileRead(ThePNG, ChunkHeaderLength);
2250 if(!Trans)
2251 {
2252 CloseBufferedFile(ThePNG);
2253
2254 return;
2255 }
2256
2257 /*
2258 * Read the CRC.
2259 */
2260
2261 CRC = BufferedFileRead(ThePNG, PNG_ChunkCRC_Size);
2262 if(!CRC)
2263 {
2264 CloseBufferedFile(ThePNG);
2265
2266 return;
2267 }
2268
2269 /*
2270 * Only for Grey, True and Indexed ColourType should tRNS exist.
2271 */
2272
2273 switch(IHDR->ColourType)
2274 {
2275 case PNG_ColourType_Grey :
2276 {
2277 if(ChunkHeaderLength != 2)
2278 {
2279 CloseBufferedFile(ThePNG);
2280
2281 return;
2282 }
2283
2284 HasTransparentColour = qtrue;
2285
2286 /*
2287 * Grey can have one colour which is completely transparent.
2288 * This colour is always stored in 16 bits.
2289 */
2290
2291 TransparentColour[0] = Trans[0];
2292 TransparentColour[1] = Trans[1];
2293
2294 break;
2295 }
2296
2297 case PNG_ColourType_True :
2298 {
2299 if(ChunkHeaderLength != 6)
2300 {
2301 CloseBufferedFile(ThePNG);
2302
2303 return;
2304 }
2305
2306 HasTransparentColour = qtrue;
2307
2308 /*
2309 * True can have one colour which is completely transparent.
2310 * This colour is always stored in 16 bits.
2311 */
2312
2313 TransparentColour[0] = Trans[0];
2314 TransparentColour[1] = Trans[1];
2315 TransparentColour[2] = Trans[2];
2316 TransparentColour[3] = Trans[3];
2317 TransparentColour[4] = Trans[4];
2318 TransparentColour[5] = Trans[5];
2319
2320 break;
2321 }
2322
2323 case PNG_ColourType_Indexed :
2324 {
2325 /*
2326 * Maximum of 256 one byte transparency entries.
2327 */
2328
2329 if(ChunkHeaderLength > 256)
2330 {
2331 CloseBufferedFile(ThePNG);
2332
2333 return;
2334 }
2335
2336 HasTransparentColour = qtrue;
2337
2338 /*
2339 * alpha values for palette entries
2340 */
2341
2342 for(i = 0; i < ChunkHeaderLength; i++)
2343 {
2344 OutPal[i * Q3IMAGE_BYTESPERPIXEL + 3] = Trans[i];
2345 }
2346
2347 break;
2348 }
2349
2350 /*
2351 * All other ColourTypes should not have tRNS chunks
2352 */
2353
2354 default :
2355 {
2356 CloseBufferedFile(ThePNG);
2357
2358 return;
2359 }
2360 }
2361 }
2362
2363 /*
2364 * Rewind to the start of the file.
2365 */
2366
2367 if(!BufferedFileRewind(ThePNG, -1))
2368 {
2369 CloseBufferedFile(ThePNG);
2370
2371 return;
2372 }
2373
2374 /*
2375 * Skip the signature
2376 */
2377
2378 if(!BufferedFileSkip(ThePNG, PNG_Signature_Size))
2379 {
2380 CloseBufferedFile(ThePNG);
2381
2382 return;
2383 }
2384
2385 /*
2386 * Decompress all IDAT chunks
2387 */
2388
2389 DecompressedDataLength = DecompressIDATs(ThePNG, &DecompressedData);
2390 if(!(DecompressedDataLength && DecompressedData))
2391 {
2392 CloseBufferedFile(ThePNG);
2393
2394 return;
2395 }
2396
2397 /*
2398 * Allocate output buffer.
2399 */
2400
2401 OutBuffer = ri.Z_Malloc(IHDR_Width * IHDR_Height * Q3IMAGE_BYTESPERPIXEL);
2402 if(!OutBuffer)
2403 {
2404 ri.Free(DecompressedData);
2405 CloseBufferedFile(ThePNG);
2406
2407 return;
2408 }
2409
2410 /*
2411 * Interlaced and Non-interlaced images need to be handled differently.
2412 */
2413
2414 switch(IHDR->InterlaceMethod)
2415 {
2416 case PNG_InterlaceMethod_NonInterlaced :
2417 {
2418 if(!DecodeImageNonInterlaced(IHDR, OutBuffer, DecompressedData, DecompressedDataLength, HasTransparentColour, TransparentColour, OutPal))
2419 {
2420 ri.Free(OutBuffer);
2421 ri.Free(DecompressedData);
2422 CloseBufferedFile(ThePNG);
2423
2424 return;
2425 }
2426
2427 break;
2428 }
2429
2430 case PNG_InterlaceMethod_Interlaced :
2431 {
2432 if(!DecodeImageInterlaced(IHDR, OutBuffer, DecompressedData, DecompressedDataLength, HasTransparentColour, TransparentColour, OutPal))
2433 {
2434 ri.Free(OutBuffer);
2435 ri.Free(DecompressedData);
2436 CloseBufferedFile(ThePNG);
2437
2438 return;
2439 }
2440
2441 break;
2442 }
2443
2444 default :
2445 {
2446 ri.Free(OutBuffer);
2447 ri.Free(DecompressedData);
2448 CloseBufferedFile(ThePNG);
2449
2450 return;
2451 }
2452 }
2453
2454 /*
2455 * update the pointer to the image data
2456 */
2457
2458 *pic = OutBuffer;
2459
2460 /*
2461 * Fill width and height.
2462 */
2463
2464 if(width)
2465 {
2466 *width = IHDR_Width;
2467 }
2468
2469 if(height)
2470 {
2471 *height = IHDR_Height;
2472 }
2473
2474 /*
2475 * DecompressedData is not needed anymore.
2476 */
2477
2478 ri.Free(DecompressedData);
2479
2480 /*
2481 * We have all data, so close the file.
2482 */
2483
2484 CloseBufferedFile(ThePNG);
2485 }
2486