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.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 DecompressedDataLength = 0;
544 *Buffer = DecompressedData;
545
546 CompressedData = NULL;
547 CompressedDataLength = 0;
548
549 BytesToRewind = 0;
550
551 /*
552 * Find the first IDAT chunk.
553 */
554
555 if(!FindChunk(BF, PNG_ChunkType_IDAT))
556 {
557 return(-1);
558 }
559
560 /*
561 * Count the size of the uncompressed data
562 */
563
564 while(qtrue)
565 {
566 /*
567 * Read chunk header
568 */
569
570 CH = BufferedFileRead(BF, PNG_ChunkHeader_Size);
571 if(!CH)
572 {
573 /*
574 * Rewind to the start of this adventure
575 * and return unsuccessfull
576 */
577
578 BufferedFileRewind(BF, BytesToRewind);
579
580 return(-1);
581 }
582
583 /*
584 * Length and Type of chunk
585 */
586
587 Length = BigLong(CH->Length);
588 Type = BigLong(CH->Type);
589
590 /*
591 * We have reached the end of the IDAT chunks
592 */
593
594 if(!(Type == PNG_ChunkType_IDAT))
595 {
596 BufferedFileRewind(BF, PNG_ChunkHeader_Size);
597
598 break;
599 }
600
601 /*
602 * Add chunk header to count.
603 */
604
605 BytesToRewind += PNG_ChunkHeader_Size;
606
607 /*
608 * Skip to next chunk
609 */
610
611 if(Length)
612 {
613 if(!BufferedFileSkip(BF, Length + PNG_ChunkCRC_Size))
614 {
615 BufferedFileRewind(BF, BytesToRewind);
616
617 return(-1);
618 }
619
620 BytesToRewind += Length + PNG_ChunkCRC_Size;
621 CompressedDataLength += Length;
622 }
623 }
624
625 BufferedFileRewind(BF, BytesToRewind);
626
627 CompressedData = ri.Malloc(CompressedDataLength);
628 if(!CompressedData)
629 {
630 return(-1);
631 }
632
633 CompressedDataPtr = CompressedData;
634
635 /*
636 * Collect the compressed Data
637 */
638
639 while(qtrue)
640 {
641 /*
642 * Read chunk header
643 */
644
645 CH = BufferedFileRead(BF, PNG_ChunkHeader_Size);
646 if(!CH)
647 {
648 ri.Free(CompressedData);
649
650 return(-1);
651 }
652
653 /*
654 * Length and Type of chunk
655 */
656
657 Length = BigLong(CH->Length);
658 Type = BigLong(CH->Type);
659
660 /*
661 * We have reached the end of the IDAT chunks
662 */
663
664 if(!(Type == PNG_ChunkType_IDAT))
665 {
666 BufferedFileRewind(BF, PNG_ChunkHeader_Size);
667
668 break;
669 }
670
671 /*
672 * Copy the Data
673 */
674
675 if(Length)
676 {
677 uint8_t *OrigCompressedData;
678
679 OrigCompressedData = BufferedFileRead(BF, Length);
680 if(!OrigCompressedData)
681 {
682 ri.Free(CompressedData);
683
684 return(-1);
685 }
686
687 if(!BufferedFileSkip(BF, PNG_ChunkCRC_Size))
688 {
689 ri.Free(CompressedData);
690
691 return(-1);
692 }
693
694 memcpy(CompressedDataPtr, OrigCompressedData, Length);
695 CompressedDataPtr += Length;
696 }
697 }
698
699 /*
700 * Let puff() calculate the decompressed data length.
701 */
702
703 puffDest = NULL;
704 puffDestLen = 0;
705
706 /*
707 * The zlib header and checkvalue don't belong to the compressed data.
708 */
709
710 puffSrc = CompressedData + PNG_ZlibHeader_Size;
711 puffSrcLen = CompressedDataLength - PNG_ZlibHeader_Size - PNG_ZlibCheckValue_Size;
712
713 /*
714 * first puff() to calculate the size of the uncompressed data
715 */
716
717 puffResult = puff(puffDest, &puffDestLen, puffSrc, &puffSrcLen);
718 if(!((puffResult == 0) && (puffDestLen > 0)))
719 {
720 ri.Free(CompressedData);
721
722 return(-1);
723 }
724
725 /*
726 * Allocate the buffer for the uncompressed data.
727 */
728
729 DecompressedData = ri.Malloc(puffDestLen);
730 if(!DecompressedData)
731 {
732 ri.Free(CompressedData);
733
734 return(-1);
735 }
736
737 /*
738 * Set the input again in case something was changed by the last puff() .
739 */
740
741 puffDest = DecompressedData;
742 puffSrc = CompressedData + PNG_ZlibHeader_Size;
743 puffSrcLen = CompressedDataLength - PNG_ZlibHeader_Size - PNG_ZlibCheckValue_Size;
744
745 /*
746 * decompression puff()
747 */
748
749 puffResult = puff(puffDest, &puffDestLen, puffSrc, &puffSrcLen);
750
751 /*
752 * The compressed data is not needed anymore.
753 */
754
755 ri.Free(CompressedData);
756
757 /*
758 * Check if the last puff() was successfull.
759 */
760
761 if(!((puffResult == 0) && (puffDestLen > 0)))
762 {
763 ri.Free(DecompressedData);
764
765 return(-1);
766 }
767
768 /*
769 * Set the output of this function.
770 */
771
772 DecompressedDataLength = puffDestLen;
773 *Buffer = DecompressedData;
774
775 return(DecompressedDataLength);
776 }
777
778 /*
779 * the Paeth predictor
780 */
781
PredictPaeth(uint8_t a,uint8_t b,uint8_t c)782 static uint8_t PredictPaeth(uint8_t a, uint8_t b, uint8_t c)
783 {
784 /*
785 * a == Left
786 * b == Up
787 * c == UpLeft
788 */
789
790 uint8_t Pr;
791 int p;
792 int pa, pb, pc;
793
794 Pr = 0;
795
796 p = ((int) a) + ((int) b) - ((int) c);
797 pa = abs(p - ((int) a));
798 pb = abs(p - ((int) b));
799 pc = abs(p - ((int) c));
800
801 if((pa <= pb) && (pa <= pc))
802 {
803 Pr = a;
804 }
805 else if(pb <= pc)
806 {
807 Pr = b;
808 }
809 else
810 {
811 Pr = c;
812 }
813
814 return(Pr);
815
816 }
817
818 /*
819 * Reverse the filters.
820 */
821
UnfilterImage(uint8_t * DecompressedData,uint32_t ImageHeight,uint32_t BytesPerScanline,uint32_t BytesPerPixel)822 static qboolean UnfilterImage(uint8_t *DecompressedData,
823 uint32_t ImageHeight,
824 uint32_t BytesPerScanline,
825 uint32_t BytesPerPixel)
826 {
827 uint8_t *DecompPtr;
828 uint8_t FilterType;
829 uint8_t *PixelLeft, *PixelUp, *PixelUpLeft;
830 uint32_t w, h, p;
831
832 /*
833 * some zeros for the filters
834 */
835
836 uint8_t Zeros[8] = {0, 0, 0, 0, 0, 0, 0, 0};
837
838 /*
839 * input verification
840 */
841
842 if(!(DecompressedData && BytesPerPixel))
843 {
844 return(qfalse);
845 }
846
847 /*
848 * ImageHeight and BytesPerScanline can be zero in small interlaced images.
849 */
850
851 if((!ImageHeight) || (!BytesPerScanline))
852 {
853 return(qtrue);
854 }
855
856 /*
857 * Set the pointer to the start of the decompressed Data.
858 */
859
860 DecompPtr = DecompressedData;
861
862 /*
863 * Un-filtering is done in place.
864 */
865
866 /*
867 * Go trough all scanlines.
868 */
869
870 for(h = 0; h < ImageHeight; h++)
871 {
872 /*
873 * Every scanline starts with a FilterType byte.
874 */
875
876 FilterType = *DecompPtr;
877 DecompPtr++;
878
879 /*
880 * Left pixel of the first byte in a scanline is zero.
881 */
882
883 PixelLeft = Zeros;
884
885 /*
886 * Set PixelUp to previous line only if we are on the second line or above.
887 *
888 * Plus one byte for the FilterType
889 */
890
891 if(h > 0)
892 {
893 PixelUp = DecompPtr - (BytesPerScanline + 1);
894 }
895 else
896 {
897 PixelUp = Zeros;
898 }
899
900 /*
901 * The pixel left to the first pixel of the previous scanline is zero too.
902 */
903
904 PixelUpLeft = Zeros;
905
906 /*
907 * Cycle trough all pixels of the scanline.
908 */
909
910 for(w = 0; w < (BytesPerScanline / BytesPerPixel); w++)
911 {
912 /*
913 * Cycle trough the bytes of the pixel.
914 */
915
916 for(p = 0; p < BytesPerPixel; p++)
917 {
918 switch(FilterType)
919 {
920 case PNG_FilterType_None :
921 {
922 /*
923 * The byte is unfiltered.
924 */
925
926 break;
927 }
928
929 case PNG_FilterType_Sub :
930 {
931 DecompPtr[p] += PixelLeft[p];
932
933 break;
934 }
935
936 case PNG_FilterType_Up :
937 {
938 DecompPtr[p] += PixelUp[p];
939
940 break;
941 }
942
943 case PNG_FilterType_Average :
944 {
945 DecompPtr[p] += ((uint8_t) ((((uint16_t) PixelLeft[p]) + ((uint16_t) PixelUp[p])) / 2));
946
947 break;
948 }
949
950 case PNG_FilterType_Paeth :
951 {
952 DecompPtr[p] += PredictPaeth(PixelLeft[p], PixelUp[p], PixelUpLeft[p]);
953
954 break;
955 }
956
957 default :
958 {
959 return(qfalse);
960 }
961 }
962 }
963
964 PixelLeft = DecompPtr;
965
966 /*
967 * We only have a upleft pixel if we are on the second line or above.
968 */
969
970 if(h > 0)
971 {
972 PixelUpLeft = DecompPtr - (BytesPerScanline + 1);
973 }
974
975 /*
976 * Skip to the next pixel.
977 */
978
979 DecompPtr += BytesPerPixel;
980
981 /*
982 * We only have a previous line if we are on the second line and above.
983 */
984
985 if(h > 0)
986 {
987 PixelUp = DecompPtr - (BytesPerScanline + 1);
988 }
989 }
990 }
991
992 return(qtrue);
993 }
994
995 /*
996 * Convert a raw input pixel to Quake 3 RGA format.
997 */
998
ConvertPixel(struct PNG_Chunk_IHDR * IHDR,byte * OutPtr,uint8_t * DecompPtr,qboolean HasTransparentColour,uint8_t * TransparentColour,uint8_t * OutPal)999 static qboolean ConvertPixel(struct PNG_Chunk_IHDR *IHDR,
1000 byte *OutPtr,
1001 uint8_t *DecompPtr,
1002 qboolean HasTransparentColour,
1003 uint8_t *TransparentColour,
1004 uint8_t *OutPal)
1005 {
1006 /*
1007 * input verification
1008 */
1009
1010 if(!(IHDR && OutPtr && DecompPtr && TransparentColour && OutPal))
1011 {
1012 return(qfalse);
1013 }
1014
1015 switch(IHDR->ColourType)
1016 {
1017 case PNG_ColourType_Grey :
1018 {
1019 switch(IHDR->BitDepth)
1020 {
1021 case PNG_BitDepth_1 :
1022 case PNG_BitDepth_2 :
1023 case PNG_BitDepth_4 :
1024 {
1025 uint8_t Step;
1026 uint8_t GreyValue;
1027
1028 Step = 0xFF / ((1 << IHDR->BitDepth) - 1);
1029
1030 GreyValue = DecompPtr[0] * Step;
1031
1032 OutPtr[0] = GreyValue;
1033 OutPtr[1] = GreyValue;
1034 OutPtr[2] = GreyValue;
1035 OutPtr[3] = 0xFF;
1036
1037 /*
1038 * Grey supports full transparency for one specified colour
1039 */
1040
1041 if(HasTransparentColour)
1042 {
1043 if(TransparentColour[1] == DecompPtr[0])
1044 {
1045 OutPtr[3] = 0x00;
1046 }
1047 }
1048
1049
1050 break;
1051 }
1052
1053 case PNG_BitDepth_8 :
1054 case PNG_BitDepth_16 :
1055 {
1056 OutPtr[0] = DecompPtr[0];
1057 OutPtr[1] = DecompPtr[0];
1058 OutPtr[2] = DecompPtr[0];
1059 OutPtr[3] = 0xFF;
1060
1061 /*
1062 * Grey supports full transparency for one specified colour
1063 */
1064
1065 if(HasTransparentColour)
1066 {
1067 if(IHDR->BitDepth == PNG_BitDepth_8)
1068 {
1069 if(TransparentColour[1] == DecompPtr[0])
1070 {
1071 OutPtr[3] = 0x00;
1072 }
1073 }
1074 else
1075 {
1076 if((TransparentColour[0] == DecompPtr[0]) && (TransparentColour[1] == DecompPtr[1]))
1077 {
1078 OutPtr[3] = 0x00;
1079 }
1080 }
1081 }
1082
1083 break;
1084 }
1085
1086 default :
1087 {
1088 return(qfalse);
1089 }
1090 }
1091
1092 break;
1093 }
1094
1095 case PNG_ColourType_True :
1096 {
1097 switch(IHDR->BitDepth)
1098 {
1099 case PNG_BitDepth_8 :
1100 {
1101 OutPtr[0] = DecompPtr[0];
1102 OutPtr[1] = DecompPtr[1];
1103 OutPtr[2] = DecompPtr[2];
1104 OutPtr[3] = 0xFF;
1105
1106 /*
1107 * True supports full transparency for one specified colour
1108 */
1109
1110 if(HasTransparentColour)
1111 {
1112 if((TransparentColour[1] == DecompPtr[0]) &&
1113 (TransparentColour[3] == DecompPtr[1]) &&
1114 (TransparentColour[5] == DecompPtr[2]))
1115 {
1116 OutPtr[3] = 0x00;
1117 }
1118 }
1119
1120 break;
1121 }
1122
1123 case PNG_BitDepth_16 :
1124 {
1125 /*
1126 * We use only the upper byte.
1127 */
1128
1129 OutPtr[0] = DecompPtr[0];
1130 OutPtr[1] = DecompPtr[2];
1131 OutPtr[2] = DecompPtr[4];
1132 OutPtr[3] = 0xFF;
1133
1134 /*
1135 * True supports full transparency for one specified colour
1136 */
1137
1138 if(HasTransparentColour)
1139 {
1140 if((TransparentColour[0] == DecompPtr[0]) && (TransparentColour[1] == DecompPtr[1]) &&
1141 (TransparentColour[2] == DecompPtr[2]) && (TransparentColour[3] == DecompPtr[3]) &&
1142 (TransparentColour[4] == DecompPtr[4]) && (TransparentColour[5] == DecompPtr[5]))
1143 {
1144 OutPtr[3] = 0x00;
1145 }
1146 }
1147
1148 break;
1149 }
1150
1151 default :
1152 {
1153 return(qfalse);
1154 }
1155 }
1156
1157 break;
1158 }
1159
1160 case PNG_ColourType_Indexed :
1161 {
1162 OutPtr[0] = OutPal[DecompPtr[0] * Q3IMAGE_BYTESPERPIXEL + 0];
1163 OutPtr[1] = OutPal[DecompPtr[0] * Q3IMAGE_BYTESPERPIXEL + 1];
1164 OutPtr[2] = OutPal[DecompPtr[0] * Q3IMAGE_BYTESPERPIXEL + 2];
1165 OutPtr[3] = OutPal[DecompPtr[0] * Q3IMAGE_BYTESPERPIXEL + 3];
1166
1167 break;
1168 }
1169
1170 case PNG_ColourType_GreyAlpha :
1171 {
1172 switch(IHDR->BitDepth)
1173 {
1174 case PNG_BitDepth_8 :
1175 {
1176 OutPtr[0] = DecompPtr[0];
1177 OutPtr[1] = DecompPtr[0];
1178 OutPtr[2] = DecompPtr[0];
1179 OutPtr[3] = DecompPtr[1];
1180
1181 break;
1182 }
1183
1184 case PNG_BitDepth_16 :
1185 {
1186 /*
1187 * We use only the upper byte.
1188 */
1189
1190 OutPtr[0] = DecompPtr[0];
1191 OutPtr[1] = DecompPtr[0];
1192 OutPtr[2] = DecompPtr[0];
1193 OutPtr[3] = DecompPtr[2];
1194
1195 break;
1196 }
1197
1198 default :
1199 {
1200 return(qfalse);
1201 }
1202 }
1203
1204 break;
1205 }
1206
1207 case PNG_ColourType_TrueAlpha :
1208 {
1209 switch(IHDR->BitDepth)
1210 {
1211 case PNG_BitDepth_8 :
1212 {
1213 OutPtr[0] = DecompPtr[0];
1214 OutPtr[1] = DecompPtr[1];
1215 OutPtr[2] = DecompPtr[2];
1216 OutPtr[3] = DecompPtr[3];
1217
1218 break;
1219 }
1220
1221 case PNG_BitDepth_16 :
1222 {
1223 /*
1224 * We use only the upper byte.
1225 */
1226
1227 OutPtr[0] = DecompPtr[0];
1228 OutPtr[1] = DecompPtr[2];
1229 OutPtr[2] = DecompPtr[4];
1230 OutPtr[3] = DecompPtr[6];
1231
1232 break;
1233 }
1234
1235 default :
1236 {
1237 return(qfalse);
1238 }
1239 }
1240
1241 break;
1242 }
1243
1244 default :
1245 {
1246 return(qfalse);
1247 }
1248 }
1249
1250 return(qtrue);
1251 }
1252
1253
1254 /*
1255 * Decode a non-interlaced image.
1256 */
1257
DecodeImageNonInterlaced(struct PNG_Chunk_IHDR * IHDR,byte * OutBuffer,uint8_t * DecompressedData,uint32_t DecompressedDataLength,qboolean HasTransparentColour,uint8_t * TransparentColour,uint8_t * OutPal)1258 static qboolean DecodeImageNonInterlaced(struct PNG_Chunk_IHDR *IHDR,
1259 byte *OutBuffer,
1260 uint8_t *DecompressedData,
1261 uint32_t DecompressedDataLength,
1262 qboolean HasTransparentColour,
1263 uint8_t *TransparentColour,
1264 uint8_t *OutPal)
1265 {
1266 uint32_t IHDR_Width;
1267 uint32_t IHDR_Height;
1268 uint32_t BytesPerScanline, BytesPerPixel, PixelsPerByte;
1269 uint32_t w, h, p;
1270 byte *OutPtr;
1271 uint8_t *DecompPtr;
1272
1273 /*
1274 * input verification
1275 */
1276
1277 if(!(IHDR && OutBuffer && DecompressedData && DecompressedDataLength && TransparentColour && OutPal))
1278 {
1279 return(qfalse);
1280 }
1281
1282 /*
1283 * byte swapping
1284 */
1285
1286 IHDR_Width = BigLong(IHDR->Width);
1287 IHDR_Height = BigLong(IHDR->Height);
1288
1289 /*
1290 * information for un-filtering
1291 */
1292
1293 switch(IHDR->ColourType)
1294 {
1295 case PNG_ColourType_Grey :
1296 {
1297 switch(IHDR->BitDepth)
1298 {
1299 case PNG_BitDepth_1 :
1300 case PNG_BitDepth_2 :
1301 case PNG_BitDepth_4 :
1302 {
1303 BytesPerPixel = 1;
1304 PixelsPerByte = 8 / IHDR->BitDepth;
1305
1306 break;
1307 }
1308
1309 case PNG_BitDepth_8 :
1310 case PNG_BitDepth_16 :
1311 {
1312 BytesPerPixel = (IHDR->BitDepth / 8) * PNG_NumColourComponents_Grey;
1313 PixelsPerByte = 1;
1314
1315 break;
1316 }
1317
1318 default :
1319 {
1320 return(qfalse);
1321 }
1322 }
1323
1324 break;
1325 }
1326
1327 case PNG_ColourType_True :
1328 {
1329 switch(IHDR->BitDepth)
1330 {
1331 case PNG_BitDepth_8 :
1332 case PNG_BitDepth_16 :
1333 {
1334 BytesPerPixel = (IHDR->BitDepth / 8) * PNG_NumColourComponents_True;
1335 PixelsPerByte = 1;
1336
1337 break;
1338 }
1339
1340 default :
1341 {
1342 return(qfalse);
1343 }
1344 }
1345
1346 break;
1347 }
1348
1349 case PNG_ColourType_Indexed :
1350 {
1351 switch(IHDR->BitDepth)
1352 {
1353 case PNG_BitDepth_1 :
1354 case PNG_BitDepth_2 :
1355 case PNG_BitDepth_4 :
1356 {
1357 BytesPerPixel = 1;
1358 PixelsPerByte = 8 / IHDR->BitDepth;
1359
1360 break;
1361 }
1362
1363 case PNG_BitDepth_8 :
1364 {
1365 BytesPerPixel = PNG_NumColourComponents_Indexed;
1366 PixelsPerByte = 1;
1367
1368 break;
1369 }
1370
1371 default :
1372 {
1373 return(qfalse);
1374 }
1375 }
1376
1377 break;
1378 }
1379
1380 case PNG_ColourType_GreyAlpha :
1381 {
1382 switch(IHDR->BitDepth)
1383 {
1384 case PNG_BitDepth_8 :
1385 case PNG_BitDepth_16 :
1386 {
1387 BytesPerPixel = (IHDR->BitDepth / 8) * PNG_NumColourComponents_GreyAlpha;
1388 PixelsPerByte = 1;
1389
1390 break;
1391 }
1392
1393 default :
1394 {
1395 return(qfalse);
1396 }
1397 }
1398
1399 break;
1400 }
1401
1402 case PNG_ColourType_TrueAlpha :
1403 {
1404 switch(IHDR->BitDepth)
1405 {
1406 case PNG_BitDepth_8 :
1407 case PNG_BitDepth_16 :
1408 {
1409 BytesPerPixel = (IHDR->BitDepth / 8) * PNG_NumColourComponents_TrueAlpha;
1410 PixelsPerByte = 1;
1411
1412 break;
1413 }
1414
1415 default :
1416 {
1417 return(qfalse);
1418 }
1419 }
1420
1421 break;
1422 }
1423
1424 default :
1425 {
1426 return(qfalse);
1427 }
1428 }
1429
1430 /*
1431 * Calculate the size of one scanline
1432 */
1433
1434 BytesPerScanline = (IHDR_Width * BytesPerPixel + (PixelsPerByte - 1)) / PixelsPerByte;
1435
1436 /*
1437 * Check if we have enough data for the whole image.
1438 */
1439
1440 if(!(DecompressedDataLength == ((BytesPerScanline + 1) * IHDR_Height)))
1441 {
1442 return(qfalse);
1443 }
1444
1445 /*
1446 * Unfilter the image.
1447 */
1448
1449 if(!UnfilterImage(DecompressedData, IHDR_Height, BytesPerScanline, BytesPerPixel))
1450 {
1451 return(qfalse);
1452 }
1453
1454 /*
1455 * Set the working pointers to the beginning of the buffers.
1456 */
1457
1458 OutPtr = OutBuffer;
1459 DecompPtr = DecompressedData;
1460
1461 /*
1462 * Create the output image.
1463 */
1464
1465 for(h = 0; h < IHDR_Height; h++)
1466 {
1467 /*
1468 * Count the pixels on the scanline for those multipixel bytes
1469 */
1470
1471 uint32_t CurrPixel;
1472
1473 /*
1474 * skip FilterType
1475 */
1476
1477 DecompPtr++;
1478
1479 /*
1480 * Reset the pixel count.
1481 */
1482
1483 CurrPixel = 0;
1484
1485 for(w = 0; w < (BytesPerScanline / BytesPerPixel); w++)
1486 {
1487 if(PixelsPerByte > 1)
1488 {
1489 uint8_t Mask;
1490 uint32_t Shift;
1491 uint8_t SinglePixel;
1492
1493 for(p = 0; p < PixelsPerByte; p++)
1494 {
1495 if(CurrPixel < IHDR_Width)
1496 {
1497 Mask = (1 << IHDR->BitDepth) - 1;
1498 Shift = (PixelsPerByte - 1 - p) * IHDR->BitDepth;
1499
1500 SinglePixel = ((DecompPtr[0] & (Mask << Shift)) >> Shift);
1501
1502 if(!ConvertPixel(IHDR, OutPtr, &SinglePixel, HasTransparentColour, TransparentColour, OutPal))
1503 {
1504 return(qfalse);
1505 }
1506
1507 OutPtr += Q3IMAGE_BYTESPERPIXEL;
1508 CurrPixel++;
1509 }
1510 }
1511
1512 }
1513 else
1514 {
1515 if(!ConvertPixel(IHDR, OutPtr, DecompPtr, HasTransparentColour, TransparentColour, OutPal))
1516 {
1517 return(qfalse);
1518 }
1519
1520
1521 OutPtr += Q3IMAGE_BYTESPERPIXEL;
1522 }
1523
1524 DecompPtr += BytesPerPixel;
1525 }
1526 }
1527
1528 return(qtrue);
1529 }
1530
1531 /*
1532 * Decode an interlaced image.
1533 */
1534
DecodeImageInterlaced(struct PNG_Chunk_IHDR * IHDR,byte * OutBuffer,uint8_t * DecompressedData,uint32_t DecompressedDataLength,qboolean HasTransparentColour,uint8_t * TransparentColour,uint8_t * OutPal)1535 static qboolean DecodeImageInterlaced(struct PNG_Chunk_IHDR *IHDR,
1536 byte *OutBuffer,
1537 uint8_t *DecompressedData,
1538 uint32_t DecompressedDataLength,
1539 qboolean HasTransparentColour,
1540 uint8_t *TransparentColour,
1541 uint8_t *OutPal)
1542 {
1543 uint32_t IHDR_Width;
1544 uint32_t IHDR_Height;
1545 uint32_t BytesPerScanline[PNG_Adam7_NumPasses], BytesPerPixel, PixelsPerByte;
1546 uint32_t PassWidth[PNG_Adam7_NumPasses], PassHeight[PNG_Adam7_NumPasses];
1547 uint32_t WSkip[PNG_Adam7_NumPasses], WOffset[PNG_Adam7_NumPasses], HSkip[PNG_Adam7_NumPasses], HOffset[PNG_Adam7_NumPasses];
1548 uint32_t w, h, p, a;
1549 byte *OutPtr;
1550 uint8_t *DecompPtr;
1551 uint32_t TargetLength;
1552
1553 /*
1554 * input verification
1555 */
1556
1557 if(!(IHDR && OutBuffer && DecompressedData && DecompressedDataLength && TransparentColour && OutPal))
1558 {
1559 return(qfalse);
1560 }
1561
1562 /*
1563 * byte swapping
1564 */
1565
1566 IHDR_Width = BigLong(IHDR->Width);
1567 IHDR_Height = BigLong(IHDR->Height);
1568
1569 /*
1570 * Skip and Offset for the passes.
1571 */
1572
1573 WSkip[0] = 8;
1574 WOffset[0] = 0;
1575 HSkip[0] = 8;
1576 HOffset[0] = 0;
1577
1578 WSkip[1] = 8;
1579 WOffset[1] = 4;
1580 HSkip[1] = 8;
1581 HOffset[1] = 0;
1582
1583 WSkip[2] = 4;
1584 WOffset[2] = 0;
1585 HSkip[2] = 8;
1586 HOffset[2] = 4;
1587
1588 WSkip[3] = 4;
1589 WOffset[3] = 2;
1590 HSkip[3] = 4;
1591 HOffset[3] = 0;
1592
1593 WSkip[4] = 2;
1594 WOffset[4] = 0;
1595 HSkip[4] = 4;
1596 HOffset[4] = 2;
1597
1598 WSkip[5] = 2;
1599 WOffset[5] = 1;
1600 HSkip[5] = 2;
1601 HOffset[5] = 0;
1602
1603 WSkip[6] = 1;
1604 WOffset[6] = 0;
1605 HSkip[6] = 2;
1606 HOffset[6] = 1;
1607
1608 /*
1609 * Calculate the sizes of the passes.
1610 */
1611
1612 PassWidth[0] = (IHDR_Width + 7) / 8;
1613 PassHeight[0] = (IHDR_Height + 7) / 8;
1614
1615 PassWidth[1] = (IHDR_Width + 3) / 8;
1616 PassHeight[1] = (IHDR_Height + 7) / 8;
1617
1618 PassWidth[2] = (IHDR_Width + 3) / 4;
1619 PassHeight[2] = (IHDR_Height + 3) / 8;
1620
1621 PassWidth[3] = (IHDR_Width + 1) / 4;
1622 PassHeight[3] = (IHDR_Height + 3) / 4;
1623
1624 PassWidth[4] = (IHDR_Width + 1) / 2;
1625 PassHeight[4] = (IHDR_Height + 1) / 4;
1626
1627 PassWidth[5] = (IHDR_Width + 0) / 2;
1628 PassHeight[5] = (IHDR_Height + 1) / 2;
1629
1630 PassWidth[6] = (IHDR_Width + 0) / 1;
1631 PassHeight[6] = (IHDR_Height + 0) / 2;
1632
1633 /*
1634 * information for un-filtering
1635 */
1636
1637 switch(IHDR->ColourType)
1638 {
1639 case PNG_ColourType_Grey :
1640 {
1641 switch(IHDR->BitDepth)
1642 {
1643 case PNG_BitDepth_1 :
1644 case PNG_BitDepth_2 :
1645 case PNG_BitDepth_4 :
1646 {
1647 BytesPerPixel = 1;
1648 PixelsPerByte = 8 / IHDR->BitDepth;
1649
1650 break;
1651 }
1652
1653 case PNG_BitDepth_8 :
1654 case PNG_BitDepth_16 :
1655 {
1656 BytesPerPixel = (IHDR->BitDepth / 8) * PNG_NumColourComponents_Grey;
1657 PixelsPerByte = 1;
1658
1659 break;
1660 }
1661
1662 default :
1663 {
1664 return(qfalse);
1665 }
1666 }
1667
1668 break;
1669 }
1670
1671 case PNG_ColourType_True :
1672 {
1673 switch(IHDR->BitDepth)
1674 {
1675 case PNG_BitDepth_8 :
1676 case PNG_BitDepth_16 :
1677 {
1678 BytesPerPixel = (IHDR->BitDepth / 8) * PNG_NumColourComponents_True;
1679 PixelsPerByte = 1;
1680
1681 break;
1682 }
1683
1684 default :
1685 {
1686 return(qfalse);
1687 }
1688 }
1689
1690 break;
1691 }
1692
1693 case PNG_ColourType_Indexed :
1694 {
1695 switch(IHDR->BitDepth)
1696 {
1697 case PNG_BitDepth_1 :
1698 case PNG_BitDepth_2 :
1699 case PNG_BitDepth_4 :
1700 {
1701 BytesPerPixel = 1;
1702 PixelsPerByte = 8 / IHDR->BitDepth;
1703
1704 break;
1705 }
1706
1707 case PNG_BitDepth_8 :
1708 {
1709 BytesPerPixel = PNG_NumColourComponents_Indexed;
1710 PixelsPerByte = 1;
1711
1712 break;
1713 }
1714
1715 default :
1716 {
1717 return(qfalse);
1718 }
1719 }
1720
1721 break;
1722 }
1723
1724 case PNG_ColourType_GreyAlpha :
1725 {
1726 switch(IHDR->BitDepth)
1727 {
1728 case PNG_BitDepth_8 :
1729 case PNG_BitDepth_16 :
1730 {
1731 BytesPerPixel = (IHDR->BitDepth / 8) * PNG_NumColourComponents_GreyAlpha;
1732 PixelsPerByte = 1;
1733
1734 break;
1735 }
1736
1737 default :
1738 {
1739 return(qfalse);
1740 }
1741 }
1742
1743 break;
1744 }
1745
1746 case PNG_ColourType_TrueAlpha :
1747 {
1748 switch(IHDR->BitDepth)
1749 {
1750 case PNG_BitDepth_8 :
1751 case PNG_BitDepth_16 :
1752 {
1753 BytesPerPixel = (IHDR->BitDepth / 8) * PNG_NumColourComponents_TrueAlpha;
1754 PixelsPerByte = 1;
1755
1756 break;
1757 }
1758
1759 default :
1760 {
1761 return(qfalse);
1762 }
1763 }
1764
1765 break;
1766 }
1767
1768 default :
1769 {
1770 return(qfalse);
1771 }
1772 }
1773
1774 /*
1775 * Calculate the size of the scanlines per pass
1776 */
1777
1778 for(a = 0; a < PNG_Adam7_NumPasses; a++)
1779 {
1780 BytesPerScanline[a] = (PassWidth[a] * BytesPerPixel + (PixelsPerByte - 1)) / PixelsPerByte;
1781 }
1782
1783 /*
1784 * Calculate the size of all passes
1785 */
1786
1787 TargetLength = 0;
1788
1789 for(a = 0; a < PNG_Adam7_NumPasses; a++)
1790 {
1791 TargetLength += ((BytesPerScanline[a] + (BytesPerScanline[a] ? 1 : 0)) * PassHeight[a]);
1792 }
1793
1794 /*
1795 * Check if we have enough data for the whole image.
1796 */
1797
1798 if(!(DecompressedDataLength == TargetLength))
1799 {
1800 return(qfalse);
1801 }
1802
1803 /*
1804 * Unfilter the image.
1805 */
1806
1807 DecompPtr = DecompressedData;
1808
1809 for(a = 0; a < PNG_Adam7_NumPasses; a++)
1810 {
1811 if(!UnfilterImage(DecompPtr, PassHeight[a], BytesPerScanline[a], BytesPerPixel))
1812 {
1813 return(qfalse);
1814 }
1815
1816 DecompPtr += ((BytesPerScanline[a] + (BytesPerScanline[a] ? 1 : 0)) * PassHeight[a]);
1817 }
1818
1819 /*
1820 * Set the working pointers to the beginning of the buffers.
1821 */
1822
1823 DecompPtr = DecompressedData;
1824
1825 /*
1826 * Create the output image.
1827 */
1828
1829 for(a = 0; a < PNG_Adam7_NumPasses; a++)
1830 {
1831 for(h = 0; h < PassHeight[a]; h++)
1832 {
1833 /*
1834 * Count the pixels on the scanline for those multipixel bytes
1835 */
1836
1837 uint32_t CurrPixel;
1838
1839 /*
1840 * skip FilterType
1841 * but only when the pass has a width bigger than zero
1842 */
1843
1844 if(BytesPerScanline[a])
1845 {
1846 DecompPtr++;
1847 }
1848
1849 /*
1850 * Reset the pixel count.
1851 */
1852
1853 CurrPixel = 0;
1854
1855 for(w = 0; w < (BytesPerScanline[a] / BytesPerPixel); w++)
1856 {
1857 if(PixelsPerByte > 1)
1858 {
1859 uint8_t Mask;
1860 uint32_t Shift;
1861 uint8_t SinglePixel;
1862
1863 for(p = 0; p < PixelsPerByte; p++)
1864 {
1865 if(CurrPixel < PassWidth[a])
1866 {
1867 Mask = (1 << IHDR->BitDepth) - 1;
1868 Shift = (PixelsPerByte - 1 - p) * IHDR->BitDepth;
1869
1870 SinglePixel = ((DecompPtr[0] & (Mask << Shift)) >> Shift);
1871
1872 OutPtr = OutBuffer + (((((h * HSkip[a]) + HOffset[a]) * IHDR_Width) + ((CurrPixel * WSkip[a]) + WOffset[a])) * Q3IMAGE_BYTESPERPIXEL);
1873
1874 if(!ConvertPixel(IHDR, OutPtr, &SinglePixel, HasTransparentColour, TransparentColour, OutPal))
1875 {
1876 return(qfalse);
1877 }
1878
1879 CurrPixel++;
1880 }
1881 }
1882
1883 }
1884 else
1885 {
1886 OutPtr = OutBuffer + (((((h * HSkip[a]) + HOffset[a]) * IHDR_Width) + ((w * WSkip[a]) + WOffset[a])) * Q3IMAGE_BYTESPERPIXEL);
1887
1888 if(!ConvertPixel(IHDR, OutPtr, DecompPtr, HasTransparentColour, TransparentColour, OutPal))
1889 {
1890 return(qfalse);
1891 }
1892 }
1893
1894 DecompPtr += BytesPerPixel;
1895 }
1896 }
1897 }
1898
1899 return(qtrue);
1900 }
1901
1902 /*
1903 * The PNG loader
1904 */
1905
R_LoadPNG(const char * name,byte ** pic,int * width,int * height)1906 void R_LoadPNG(const char *name, byte **pic, int *width, int *height)
1907 {
1908 struct BufferedFile *ThePNG;
1909 byte *OutBuffer;
1910 uint8_t *Signature;
1911 struct PNG_ChunkHeader *CH;
1912 uint32_t ChunkHeaderLength;
1913 uint32_t ChunkHeaderType;
1914 struct PNG_Chunk_IHDR *IHDR;
1915 uint32_t IHDR_Width;
1916 uint32_t IHDR_Height;
1917 PNG_ChunkCRC *CRC;
1918 uint8_t *InPal;
1919 uint8_t *DecompressedData;
1920 uint32_t DecompressedDataLength;
1921 uint32_t i;
1922
1923 /*
1924 * palette with 256 RGBA entries
1925 */
1926
1927 uint8_t OutPal[1024];
1928
1929 /*
1930 * transparent colour from the tRNS chunk
1931 */
1932
1933 qboolean HasTransparentColour = qfalse;
1934 uint8_t TransparentColour[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
1935
1936 /*
1937 * input verification
1938 */
1939
1940 if(!(name && pic))
1941 {
1942 return;
1943 }
1944
1945 /*
1946 * Zero out return values.
1947 */
1948
1949 *pic = NULL;
1950
1951 if(width)
1952 {
1953 *width = 0;
1954 }
1955
1956 if(height)
1957 {
1958 *height = 0;
1959 }
1960
1961 /*
1962 * Read the file.
1963 */
1964
1965 ThePNG = ReadBufferedFile(name);
1966 if(!ThePNG)
1967 {
1968 return;
1969 }
1970
1971 /*
1972 * Read the siganture of the file.
1973 */
1974
1975 Signature = BufferedFileRead(ThePNG, PNG_Signature_Size);
1976 if(!Signature)
1977 {
1978 CloseBufferedFile(ThePNG);
1979
1980 return;
1981 }
1982
1983 /*
1984 * Is it a PNG?
1985 */
1986
1987 if(memcmp(Signature, PNG_Signature, PNG_Signature_Size))
1988 {
1989 CloseBufferedFile(ThePNG);
1990
1991 return;
1992 }
1993
1994 /*
1995 * Read the first chunk-header.
1996 */
1997
1998 CH = BufferedFileRead(ThePNG, PNG_ChunkHeader_Size);
1999 if(!CH)
2000 {
2001 CloseBufferedFile(ThePNG);
2002
2003 return;
2004 }
2005
2006 /*
2007 * PNG multi-byte types are in Big Endian
2008 */
2009
2010 ChunkHeaderLength = BigLong(CH->Length);
2011 ChunkHeaderType = BigLong(CH->Type);
2012
2013 /*
2014 * Check if the first chunk is an IHDR.
2015 */
2016
2017 if(!((ChunkHeaderType == PNG_ChunkType_IHDR) && (ChunkHeaderLength == PNG_Chunk_IHDR_Size)))
2018 {
2019 CloseBufferedFile(ThePNG);
2020
2021 return;
2022 }
2023
2024 /*
2025 * Read the IHDR.
2026 */
2027
2028 IHDR = BufferedFileRead(ThePNG, PNG_Chunk_IHDR_Size);
2029 if(!IHDR)
2030 {
2031 CloseBufferedFile(ThePNG);
2032
2033 return;
2034 }
2035
2036 /*
2037 * Read the CRC for IHDR
2038 */
2039
2040 CRC = BufferedFileRead(ThePNG, PNG_ChunkCRC_Size);
2041 if(!CRC)
2042 {
2043 CloseBufferedFile(ThePNG);
2044
2045 return;
2046 }
2047
2048 /*
2049 * Here we could check the CRC if we wanted to.
2050 */
2051
2052 /*
2053 * multi-byte type swapping
2054 */
2055
2056 IHDR_Width = BigLong(IHDR->Width);
2057 IHDR_Height = BigLong(IHDR->Height);
2058
2059 /*
2060 * Check if Width and Height are valid.
2061 */
2062
2063 if(!((IHDR_Width > 0) && (IHDR_Height > 0))
2064 || IHDR_Width > INT_MAX / Q3IMAGE_BYTESPERPIXEL / IHDR_Height)
2065 {
2066 CloseBufferedFile(ThePNG);
2067
2068 Com_Printf(S_COLOR_YELLOW "%s: invalid image size\n", name);
2069
2070 return;
2071 }
2072
2073 /*
2074 * Do we need to check if the dimensions of the image are valid for Quake3?
2075 */
2076
2077 /*
2078 * Check if CompressionMethod and FilterMethod are valid.
2079 */
2080
2081 if(!((IHDR->CompressionMethod == PNG_CompressionMethod_0) && (IHDR->FilterMethod == PNG_FilterMethod_0)))
2082 {
2083 CloseBufferedFile(ThePNG);
2084
2085 return;
2086 }
2087
2088 /*
2089 * Check if InterlaceMethod is valid.
2090 */
2091
2092 if(!((IHDR->InterlaceMethod == PNG_InterlaceMethod_NonInterlaced) || (IHDR->InterlaceMethod == PNG_InterlaceMethod_Interlaced)))
2093 {
2094 CloseBufferedFile(ThePNG);
2095
2096 return;
2097 }
2098
2099 /*
2100 * Read palette for an indexed image.
2101 */
2102
2103 if(IHDR->ColourType == PNG_ColourType_Indexed)
2104 {
2105 /*
2106 * We need the palette first.
2107 */
2108
2109 if(!FindChunk(ThePNG, PNG_ChunkType_PLTE))
2110 {
2111 CloseBufferedFile(ThePNG);
2112
2113 return;
2114 }
2115
2116 /*
2117 * Read the chunk-header.
2118 */
2119
2120 CH = BufferedFileRead(ThePNG, PNG_ChunkHeader_Size);
2121 if(!CH)
2122 {
2123 CloseBufferedFile(ThePNG);
2124
2125 return;
2126 }
2127
2128 /*
2129 * PNG multi-byte types are in Big Endian
2130 */
2131
2132 ChunkHeaderLength = BigLong(CH->Length);
2133 ChunkHeaderType = BigLong(CH->Type);
2134
2135 /*
2136 * Check if the chunk is an PLTE.
2137 */
2138
2139 if(!(ChunkHeaderType == PNG_ChunkType_PLTE))
2140 {
2141 CloseBufferedFile(ThePNG);
2142
2143 return;
2144 }
2145
2146 /*
2147 * Check if Length is divisible by 3
2148 */
2149
2150 if(ChunkHeaderLength % 3)
2151 {
2152 CloseBufferedFile(ThePNG);
2153
2154 return;
2155 }
2156
2157 /*
2158 * Read the raw palette data
2159 */
2160
2161 InPal = BufferedFileRead(ThePNG, ChunkHeaderLength);
2162 if(!InPal)
2163 {
2164 CloseBufferedFile(ThePNG);
2165
2166 return;
2167 }
2168
2169 /*
2170 * Read the CRC for the palette
2171 */
2172
2173 CRC = BufferedFileRead(ThePNG, PNG_ChunkCRC_Size);
2174 if(!CRC)
2175 {
2176 CloseBufferedFile(ThePNG);
2177
2178 return;
2179 }
2180
2181 /*
2182 * Set some default values.
2183 */
2184
2185 for(i = 0; i < 256; i++)
2186 {
2187 OutPal[i * Q3IMAGE_BYTESPERPIXEL + 0] = 0x00;
2188 OutPal[i * Q3IMAGE_BYTESPERPIXEL + 1] = 0x00;
2189 OutPal[i * Q3IMAGE_BYTESPERPIXEL + 2] = 0x00;
2190 OutPal[i * Q3IMAGE_BYTESPERPIXEL + 3] = 0xFF;
2191 }
2192
2193 /*
2194 * Convert to the Quake3 RGBA-format.
2195 */
2196
2197 for(i = 0; i < (ChunkHeaderLength / 3); i++)
2198 {
2199 OutPal[i * Q3IMAGE_BYTESPERPIXEL + 0] = InPal[i*3+0];
2200 OutPal[i * Q3IMAGE_BYTESPERPIXEL + 1] = InPal[i*3+1];
2201 OutPal[i * Q3IMAGE_BYTESPERPIXEL + 2] = InPal[i*3+2];
2202 OutPal[i * Q3IMAGE_BYTESPERPIXEL + 3] = 0xFF;
2203 }
2204 }
2205
2206 /*
2207 * transparency information is sometimes stored in an tRNS chunk
2208 */
2209
2210 /*
2211 * Let's see if there is a tRNS chunk
2212 */
2213
2214 if(FindChunk(ThePNG, PNG_ChunkType_tRNS))
2215 {
2216 uint8_t *Trans;
2217
2218 /*
2219 * Read the chunk-header.
2220 */
2221
2222 CH = BufferedFileRead(ThePNG, PNG_ChunkHeader_Size);
2223 if(!CH)
2224 {
2225 CloseBufferedFile(ThePNG);
2226
2227 return;
2228 }
2229
2230 /*
2231 * PNG multi-byte types are in Big Endian
2232 */
2233
2234 ChunkHeaderLength = BigLong(CH->Length);
2235 ChunkHeaderType = BigLong(CH->Type);
2236
2237 /*
2238 * Check if the chunk is an tRNS.
2239 */
2240
2241 if(!(ChunkHeaderType == PNG_ChunkType_tRNS))
2242 {
2243 CloseBufferedFile(ThePNG);
2244
2245 return;
2246 }
2247
2248 /*
2249 * Read the transparency information.
2250 */
2251
2252 Trans = BufferedFileRead(ThePNG, ChunkHeaderLength);
2253 if(!Trans)
2254 {
2255 CloseBufferedFile(ThePNG);
2256
2257 return;
2258 }
2259
2260 /*
2261 * Read the CRC.
2262 */
2263
2264 CRC = BufferedFileRead(ThePNG, PNG_ChunkCRC_Size);
2265 if(!CRC)
2266 {
2267 CloseBufferedFile(ThePNG);
2268
2269 return;
2270 }
2271
2272 /*
2273 * Only for Grey, True and Indexed ColourType should tRNS exist.
2274 */
2275
2276 switch(IHDR->ColourType)
2277 {
2278 case PNG_ColourType_Grey :
2279 {
2280 if(!ChunkHeaderLength == 2)
2281 {
2282 CloseBufferedFile(ThePNG);
2283
2284 return;
2285 }
2286
2287 HasTransparentColour = qtrue;
2288
2289 /*
2290 * Grey can have one colour which is completely transparent.
2291 * This colour is always stored in 16 bits.
2292 */
2293
2294 TransparentColour[0] = Trans[0];
2295 TransparentColour[1] = Trans[1];
2296
2297 break;
2298 }
2299
2300 case PNG_ColourType_True :
2301 {
2302 if(!ChunkHeaderLength == 6)
2303 {
2304 CloseBufferedFile(ThePNG);
2305
2306 return;
2307 }
2308
2309 HasTransparentColour = qtrue;
2310
2311 /*
2312 * True can have one colour which is completely transparent.
2313 * This colour is always stored in 16 bits.
2314 */
2315
2316 TransparentColour[0] = Trans[0];
2317 TransparentColour[1] = Trans[1];
2318 TransparentColour[2] = Trans[2];
2319 TransparentColour[3] = Trans[3];
2320 TransparentColour[4] = Trans[4];
2321 TransparentColour[5] = Trans[5];
2322
2323 break;
2324 }
2325
2326 case PNG_ColourType_Indexed :
2327 {
2328 /*
2329 * Maximum of 256 one byte transparency entries.
2330 */
2331
2332 if(ChunkHeaderLength > 256)
2333 {
2334 CloseBufferedFile(ThePNG);
2335
2336 return;
2337 }
2338
2339 HasTransparentColour = qtrue;
2340
2341 /*
2342 * alpha values for palette entries
2343 */
2344
2345 for(i = 0; i < ChunkHeaderLength; i++)
2346 {
2347 OutPal[i * Q3IMAGE_BYTESPERPIXEL + 3] = Trans[i];
2348 }
2349
2350 break;
2351 }
2352
2353 /*
2354 * All other ColourTypes should not have tRNS chunks
2355 */
2356
2357 default :
2358 {
2359 CloseBufferedFile(ThePNG);
2360
2361 return;
2362 }
2363 }
2364 }
2365
2366 /*
2367 * Rewind to the start of the file.
2368 */
2369
2370 if(!BufferedFileRewind(ThePNG, -1))
2371 {
2372 CloseBufferedFile(ThePNG);
2373
2374 return;
2375 }
2376
2377 /*
2378 * Skip the signature
2379 */
2380
2381 if(!BufferedFileSkip(ThePNG, PNG_Signature_Size))
2382 {
2383 CloseBufferedFile(ThePNG);
2384
2385 return;
2386 }
2387
2388 /*
2389 * Decompress all IDAT chunks
2390 */
2391
2392 DecompressedDataLength = DecompressIDATs(ThePNG, &DecompressedData);
2393 if(!(DecompressedDataLength && DecompressedData))
2394 {
2395 CloseBufferedFile(ThePNG);
2396
2397 return;
2398 }
2399
2400 /*
2401 * Allocate output buffer.
2402 */
2403
2404 OutBuffer = ri.Malloc(IHDR_Width * IHDR_Height * Q3IMAGE_BYTESPERPIXEL);
2405 if(!OutBuffer)
2406 {
2407 ri.Free(DecompressedData);
2408 CloseBufferedFile(ThePNG);
2409
2410 return;
2411 }
2412
2413 /*
2414 * Interlaced and Non-interlaced images need to be handled differently.
2415 */
2416
2417 switch(IHDR->InterlaceMethod)
2418 {
2419 case PNG_InterlaceMethod_NonInterlaced :
2420 {
2421 if(!DecodeImageNonInterlaced(IHDR, OutBuffer, DecompressedData, DecompressedDataLength, HasTransparentColour, TransparentColour, OutPal))
2422 {
2423 ri.Free(OutBuffer);
2424 ri.Free(DecompressedData);
2425 CloseBufferedFile(ThePNG);
2426
2427 return;
2428 }
2429
2430 break;
2431 }
2432
2433 case PNG_InterlaceMethod_Interlaced :
2434 {
2435 if(!DecodeImageInterlaced(IHDR, OutBuffer, DecompressedData, DecompressedDataLength, HasTransparentColour, TransparentColour, OutPal))
2436 {
2437 ri.Free(OutBuffer);
2438 ri.Free(DecompressedData);
2439 CloseBufferedFile(ThePNG);
2440
2441 return;
2442 }
2443
2444 break;
2445 }
2446
2447 default :
2448 {
2449 ri.Free(OutBuffer);
2450 ri.Free(DecompressedData);
2451 CloseBufferedFile(ThePNG);
2452
2453 return;
2454 }
2455 }
2456
2457 /*
2458 * update the pointer to the image data
2459 */
2460
2461 *pic = OutBuffer;
2462
2463 /*
2464 * Fill width and height.
2465 */
2466
2467 if(width)
2468 {
2469 *width = IHDR_Width;
2470 }
2471
2472 if(height)
2473 {
2474 *height = IHDR_Height;
2475 }
2476
2477 /*
2478 * DecompressedData is not needed anymore.
2479 */
2480
2481 ri.Free(DecompressedData);
2482
2483 /*
2484 * We have all data, so close the file.
2485 */
2486
2487 CloseBufferedFile(ThePNG);
2488 }
2489