1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** GUIX Component */
16 /** */
17 /** Display Management (Display) */
18 /** */
19 /**************************************************************************/
20
21 #define GX_SOURCE_CODE
22
23
24 /* Include necessary system files. */
25
26 #include "gx_api.h"
27 #include "gx_system.h"
28 #include "gx_utility.h"
29 #include "gx_image_reader.h"
30
31
32 #if defined(GX_SOFTWARE_DECODER_SUPPORT)
33 static UINT _bit_buffer;
34 static UINT _bit_count;
35
36 /**************************************************************************/
37 /* */
38 /* FUNCTION RELEASE */
39 /* */
40 /* _gx_image_reader_png_crc_table_make PORTABLE C */
41 /* 6.1 */
42 /* AUTHOR */
43 /* */
44 /* Kenneth Maxwell, Microsoft Corporation */
45 /* */
46 /* DESCRIPTION */
47 /* */
48 /* This function creates crc table that speed the crc calculation. */
49 /* */
50 /* INPUT */
51 /* */
52 /* png PNG control block */
53 /* */
54 /* OUTPUT */
55 /* */
56 /* None */
57 /* */
58 /* CALLS */
59 /* */
60 /* None */
61 /* */
62 /* CALLED BY */
63 /* */
64 /* _gx_image_reader_png_decode */
65 /* */
66 /* RELEASE HISTORY */
67 /* */
68 /* DATE NAME DESCRIPTION */
69 /* */
70 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
71 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
72 /* resulting in version 6.1 */
73 /* */
74 /**************************************************************************/
_gx_image_reader_png_crc_table_make(GX_PNG * png)75 static VOID _gx_image_reader_png_crc_table_make(GX_PNG *png)
76 {
77 UINT crc;
78 UINT n;
79 UINT k;
80
81 for (n = 0; n < 256; n++)
82 {
83 crc = n;
84 for (k = 0; k < 8; k++)
85 {
86 if (crc & 1)
87 {
88 crc = 0xedb88320 ^ (crc >> 1);
89 }
90 else
91 {
92 crc = crc >> 1;
93 }
94 }
95 png -> gx_png_crc_table[n] = crc;
96 }
97 }
98
99 /**************************************************************************/
100 /* */
101 /* FUNCTION RELEASE */
102 /* */
103 /* _gx_display_driver_png_crc_get PORTABLE C */
104 /* 6.1 */
105 /* AUTHOR */
106 /* */
107 /* Kenneth Maxwell, Microsoft Corporation */
108 /* */
109 /* DESCRIPTION */
110 /* */
111 /* This function calculates Cyclic Redundancy Check of a pecified */
112 /* data stream. */
113 /* */
114 /* INPUT */
115 /* */
116 /* png PNG control block */
117 /* crc Generated crc value */
118 /* len Data length */
119 /* */
120 /* OUTPUT */
121 /* */
122 /* None */
123 /* */
124 /* CALLS */
125 /* */
126 /* None */
127 /* */
128 /* CALLED BY */
129 /* */
130 /* _gx_image_reader_png_decode */
131 /* _gx_image_reader_png_bits_get */
132 /* */
133 /* RELEASE HISTORY */
134 /* */
135 /* DATE NAME DESCRIPTION */
136 /* */
137 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
138 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
139 /* resulting in version 6.1 */
140 /* */
141 /**************************************************************************/
_gx_image_reader_png_crc_get(GX_PNG * png,UINT * crc,UINT len)142 static VOID _gx_image_reader_png_crc_get(GX_PNG *png, UINT *crc, UINT len)
143 {
144 UINT n;
145 GX_UBYTE *buf = png -> gx_png_data + png -> gx_png_data_index;
146 UINT crc_cal = (*crc);
147
148 for (n = 0; n < len; n++)
149 {
150 crc_cal = png -> gx_png_crc_table[(crc_cal ^ buf[n]) & 0xff] ^ (crc_cal >> 8);
151 }
152
153 (*crc) = crc_cal ^ 0xffffffff;
154 }
155
156 /**************************************************************************/
157 /* */
158 /* FUNCTION RELEASE */
159 /* */
160 /* _gx_image_reader_png_4bytes_read PORTABLE C */
161 /* 6.1 */
162 /* AUTHOR */
163 /* */
164 /* Kenneth Maxwell, Microsoft Corporation */
165 /* */
166 /* DESCRIPTION */
167 /* */
168 /* This function reads 4 bytes and packed it as an INT value. */
169 /* */
170 /* INPUT */
171 /* */
172 /* png PNG control block */
173 /* value Retrieved INT value */
174 /* */
175 /* OUTPUT */
176 /* */
177 /* None */
178 /* */
179 /* CALLS */
180 /* */
181 /* None */
182 /* */
183 /* CALLED BY */
184 /* */
185 /* _gx_image_reader_png_decode */
186 /* _gx_image_reader_png_bits_get */
187 /* _gx_image_reader_png_IHDR_chunk_read */
188 /* _gx_image_reader_png_gAMA_chunk_read */
189 /* */
190 /* RELEASE HISTORY */
191 /* */
192 /* DATE NAME DESCRIPTION */
193 /* */
194 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
195 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
196 /* resulting in version 6.1 */
197 /* */
198 /**************************************************************************/
_gx_image_reader_png_4bytes_read(GX_PNG * png,INT * value)199 static VOID _gx_image_reader_png_4bytes_read(GX_PNG *png, INT *value)
200 {
201 INT get_value;
202
203 get_value = (png -> gx_png_data[png -> gx_png_data_index] << 24);
204 png -> gx_png_data_index++;
205
206 get_value |= (png -> gx_png_data[png -> gx_png_data_index] << 16);
207 png -> gx_png_data_index++;
208
209 get_value |= (png -> gx_png_data[png -> gx_png_data_index] << 8);
210 png -> gx_png_data_index++;
211
212 get_value |= png -> gx_png_data[png -> gx_png_data_index];
213 png -> gx_png_data_index++;
214
215 (*value) = get_value;
216 }
217
218 /**************************************************************************/
219 /* */
220 /* FUNCTION RELEASE */
221 /* */
222 /* _gx_image_reader_png_chunk_type_read PORTABLE C */
223 /* 6.1 */
224 /* AUTHOR */
225 /* */
226 /* Kenneth Maxwell, Microsoft Corporation */
227 /* */
228 /* DESCRIPTION */
229 /* */
230 /* This function reads the type information of a chunk. */
231 /* */
232 /* INPUT */
233 /* */
234 /* png PNG control block */
235 /* chunk_type Retrieved chunk type info */
236 /* */
237 /* OUTPUT */
238 /* */
239 /* None */
240 /* */
241 /* CALLS */
242 /* */
243 /* None */
244 /* */
245 /* CALLED BY */
246 /* */
247 /* _gx_image_reader_png_bits_get */
248 /* _gx_image_reader_png_decode */
249 /* */
250 /* RELEASE HISTORY */
251 /* */
252 /* DATE NAME DESCRIPTION */
253 /* */
254 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
255 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
256 /* resulting in version 6.1 */
257 /* */
258 /**************************************************************************/
_gx_image_reader_png_chunk_type_read(GX_PNG * png,CHAR * chunk_type)259 static VOID _gx_image_reader_png_chunk_type_read(GX_PNG *png, CHAR *chunk_type)
260 {
261 chunk_type[0] = (CHAR)png -> gx_png_data[png -> gx_png_data_index++];
262 chunk_type[1] = (CHAR)png -> gx_png_data[png -> gx_png_data_index++];
263 chunk_type[2] = (CHAR)png -> gx_png_data[png -> gx_png_data_index++];
264 chunk_type[3] = (CHAR)png -> gx_png_data[png -> gx_png_data_index++];
265 }
266
267 /**************************************************************************/
268 /* */
269 /* FUNCTION RELEASE */
270 /* */
271 /* _gx_image_reader_png_bits_get PORTABLE C */
272 /* 6.1 */
273 /* AUTHOR */
274 /* */
275 /* Kenneth Maxwell, Microsoft Corporation */
276 /* */
277 /* DESCRIPTION */
278 /* */
279 /* This function Extract a specified number of bits from PNG data */
280 /* stream and advance the read pointer of the PNG data stream. */
281 /* */
282 /* INPUT */
283 /* */
284 /* png PNG control block */
285 /* num_of_bits number of bits to retrieve */
286 /* return_value Retrieved bits data */
287 /* */
288 /* OUTPUT */
289 /* */
290 /* None */
291 /* */
292 /* CALLS */
293 /* */
294 /* _gx_image_reader_png_4bytes_read Read 4 bytes and pack it to a */
295 /* INT type value */
296 /* _gx_image_reader_png_crc_get Calculate crc value with */
297 /* specified data */
298 /* _gx_image_reader_png_chunk_type_read Read type information */
299 /* */
300 /* CALLED BY */
301 /* */
302 /* _gx_image_reader_png_clen_huffman_read */
303 /* _gx_image_reader_png_ll_huffman_read */
304 /* _gx_image_reader_png_huffcode_decode */
305 /* _gx_image_reader_png_IDAT_chunk_read */
306 /* */
307 /* RELEASE HISTORY */
308 /* */
309 /* DATE NAME DESCRIPTION */
310 /* */
311 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
312 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
313 /* resulting in version 6.1 */
314 /* */
315 /**************************************************************************/
_gx_image_reader_png_bits_get(GX_PNG * png,UINT num_of_bits,UINT * return_value)316 static UINT _gx_image_reader_png_bits_get(GX_PNG *png, UINT num_of_bits, UINT *return_value)
317 {
318 GX_UBYTE get_byte;
319 INT checksum;
320 CHAR chunk_type[4];
321 INT index = png -> gx_png_trunk_end_index;
322
323 while (_bit_count < num_of_bits)
324 {
325 if (png -> gx_png_data_index >= png -> gx_png_data_size)
326 {
327 return GX_FAILURE;
328 }
329
330 get_byte = png -> gx_png_data[png -> gx_png_data_index++];
331
332 _bit_buffer |= (UINT)(get_byte << (UINT)_bit_count);
333 _bit_count += 8;
334
335 if (png -> gx_png_data_index >= index)
336 {
337 /* data_len*/
338 _gx_image_reader_png_4bytes_read(png, &checksum);
339
340 if (png -> gx_png_trunk_crc != (UINT)checksum)
341 {
342 return GX_FAILURE;
343 }
344
345 _gx_image_reader_png_4bytes_read(png, &index);
346
347 png -> gx_png_trunk_crc = 0xffffffff;
348
349 _gx_image_reader_png_crc_get(png, &png -> gx_png_trunk_crc, (UINT)(4 + index));
350
351 _gx_image_reader_png_chunk_type_read(png, chunk_type);
352
353 if (strncmp(chunk_type, "IDAT", 4) == 0)
354 {
355 index += png -> gx_png_data_index;
356 png -> gx_png_trunk_end_index = index;
357 }
358 }
359 }
360
361 (*return_value) = _bit_buffer;
362
363 return GX_SUCCESS;
364 }
365
366 /**************************************************************************/
367 /* */
368 /* FUNCTION RELEASE */
369 /* */
370 /* _gx_image_reader_png_bits_revert PORTABLE C */
371 /* 6.1 */
372 /* AUTHOR */
373 /* */
374 /* Kenneth Maxwell, Microsoft Corporation */
375 /* */
376 /* DESCRIPTION */
377 /* */
378 /* This function reorders bits stream in opposite order. */
379 /* */
380 /* INPUT */
381 /* */
382 /* bits Variable contain bits stream */
383 /* bits_len The number of bits to revert */
384 /* */
385 /* OUTPUT */
386 /* */
387 /* None */
388 /* */
389 /* CALLS */
390 /* */
391 /* None */
392 /* */
393 /* CALLED BY */
394 /* */
395 /* _gx_image_reader_png_dynamic_huffman_code_find */
396 /* _gx_image_reader_png_fixed_ll_huffman_code_find */
397 /* _gx_image_reader_png_huffcode_decode */
398 /* */
399 /* RELEASE HISTORY */
400 /* */
401 /* DATE NAME DESCRIPTION */
402 /* */
403 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
404 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
405 /* resulting in version 6.1 */
406 /* */
407 /**************************************************************************/
_gx_image_reader_png_bits_revert(UINT * bits,UINT bits_len)408 static void _gx_image_reader_png_bits_revert(UINT *bits, UINT bits_len)
409 {
410 UINT reverted = 0;
411 UINT i;
412
413 for (i = 0; i < bits_len; i++)
414 {
415 reverted |= ((*bits) & 0x1) << (bits_len - i - 1);
416 (*bits) >>= 1;
417 }
418
419 (*bits) = reverted;
420 }
421
422 /**************************************************************************/
423 /* */
424 /* FUNCTION RELEASE */
425 /* */
426 /* _gx_image_reader_png_bits_skip PORTABLE C */
427 /* 6.1 */
428 /* AUTHOR */
429 /* */
430 /* Kenneth Maxwell, Microsoft Corporation */
431 /* */
432 /* DESCRIPTION */
433 /* */
434 /* This function skips bits from tempory PNG data buffer. */
435 /* */
436 /* INPUT */
437 /* */
438 /* num_of_skip_bits The number of bits to skip */
439 /* */
440 /* OUTPUT */
441 /* */
442 /* None */
443 /* */
444 /* CALLS */
445 /* */
446 /* None */
447 /* */
448 /* CALLED BY */
449 /* */
450 /* _gx_image_reader_png_clen_huffman_read */
451 /* _gx_image_reader_png_huffcode_decode */
452 /* _gx_image_reader_png_tRNS_chunk_read */
453 /* _gx_image_reader_png_IDAT_chunk_read */
454 /* */
455 /* RELEASE HISTORY */
456 /* */
457 /* DATE NAME DESCRIPTION */
458 /* */
459 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
460 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
461 /* resulting in version 6.1 */
462 /* */
463 /**************************************************************************/
_gx_image_reader_png_bits_skip(UINT num_of_skip_bits)464 static VOID _gx_image_reader_png_bits_skip(UINT num_of_skip_bits)
465 {
466 _bit_buffer >>= num_of_skip_bits;
467
468 _bit_count -= num_of_skip_bits;
469 }
470
471 /**************************************************************************/
472 /* */
473 /* FUNCTION RELEASE */
474 /* */
475 /* _gx_image_reader_png_IHDR_chunk_read PORTABLE C */
476 /* 6.2.0 */
477 /* AUTHOR */
478 /* */
479 /* Kenneth Maxwell, Microsoft Corporation */
480 /* */
481 /* DESCRIPTION */
482 /* */
483 /* This function reads in IHDR chunk information. */
484 /* */
485 /* INPUT */
486 /* */
487 /* png PNG control block */
488 /* */
489 /* OUTPUT */
490 /* */
491 /* status Completion status */
492 /* */
493 /* CALLS */
494 /* */
495 /* _gx_display_driver_png_4bytes_read Read 4 bytes and pack it to a */
496 /* INT type value */
497 /* */
498 /* CALLED BY */
499 /* */
500 /* _gx_image_reader_png_decode */
501 /* */
502 /* RELEASE HISTORY */
503 /* */
504 /* DATE NAME DESCRIPTION */
505 /* */
506 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
507 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
508 /* added data boundary check, */
509 /* resulting in version 6.1 */
510 /* 10-31-2022 Ting Zhu Modified comment(s), */
511 /* added invalid value check, */
512 /* resulting in version 6.2.0 */
513 /* */
514 /**************************************************************************/
_gx_image_reader_png_IHDR_chunk_read(GX_PNG * png)515 static UINT _gx_image_reader_png_IHDR_chunk_read(GX_PNG *png)
516 {
517 /* The IHDR chunk contains:
518 Width: 4 bytes
519 Height: 4 bytes
520 Bit depth: 1 byte
521 Color type: 1 byte
522 Compression method: 1 byte
523 Filter method: 1 byte
524 Interlace method: 1 byte */
525
526 if (png -> gx_png_data_index + 13 > png -> gx_png_trunk_end_index)
527 {
528 return GX_INVALID_SIZE;
529 }
530
531 _gx_image_reader_png_4bytes_read(png, &png -> gx_png_width);
532 _gx_image_reader_png_4bytes_read(png, &png -> gx_png_height);
533
534 /* Limited max png width to 14 bits. */
535 if ((png -> gx_png_width < 0) || (png -> gx_png_width > GX_MAX_PIXELMAP_RESOLUTION))
536 {
537 return GX_INVALID_WIDTH;
538 }
539
540 /* Limited max png height to 14 bits. */
541 if ((png -> gx_png_height < 0) || (png -> gx_png_height > GX_MAX_PIXELMAP_RESOLUTION))
542 {
543 return GX_INVALID_HEIGHT;
544 }
545
546 /* Bits per sample or per palette index, valid values are 1, 2 ,4, 8, 16. */
547 png -> gx_png_bit_depth = png -> gx_png_data[png -> gx_png_data_index++];
548
549 switch (png -> gx_png_bit_depth)
550 {
551 case 1:
552 case 2:
553 case 4:
554 case 8:
555 case 16:
556 break;
557
558 default:
559 return GX_INVALID_FORMAT;
560 }
561
562 /* 0 gray sample
563 2 RGB tripple
564 3 palette index
565 4 gray sample followed by an alpha sample
566 6 RGB triple followed by an alpha sample */
567 png -> gx_png_color_type = png -> gx_png_data[png -> gx_png_data_index++];
568
569 switch (png -> gx_png_color_type)
570 {
571 case 0:
572 /* Each pixel is agrayscale sample. */
573 case 3:
574 /* Each pixel is a palette index, a PLTE chunk must appear. */
575 png -> gx_png_bpp = png -> gx_png_bit_depth;
576 break;
577 case 2:
578 /* Each pixel is an RGB triple. */
579 png -> gx_png_bpp = (GX_UBYTE)(png -> gx_png_bit_depth * 3);
580 break;
581
582 case 4:
583 /* Each pixel is a grayscale sample, followed by an alpha sample. */
584 png -> gx_png_bpp = (GX_UBYTE)(png -> gx_png_bit_depth * 2);
585 break;
586 case 6:
587 /* Each pixel is an R,G,B triple, followed by an alpha sample. */
588 png -> gx_png_bpp = (GX_UBYTE)(png -> gx_png_bit_depth * 4);
589 break;
590
591 default:
592 return GX_FAILURE;
593 }
594
595 /* At present, only method 0 is defined. */
596 png -> gx_png_compression_method = png -> gx_png_data[png -> gx_png_data_index++];
597
598 /* At present, only method 0 is defined. */
599 png -> gx_png_filter_method = png -> gx_png_data[png -> gx_png_data_index++];
600
601 if ((png -> gx_png_compression_method != 0) || (png -> gx_png_filter_method != 0))
602 {
603 /* Invalid value. */
604 return GX_FAILURE;
605 }
606
607 /* 0 no interlace
608 1 Adam7 interlace */
609 png -> gx_png_interlace_method = png -> gx_png_data[png -> gx_png_data_index++];
610
611 return GX_SUCCESS;
612 }
613
614 /**************************************************************************/
615 /* */
616 /* FUNCTION RELEASE */
617 /* */
618 /* _gx_image_reader_png_dynamic_huffman_code_find PORTABLE C */
619 /* 6.1 */
620 /* AUTHOR */
621 /* */
622 /* Kenneth Maxwell, Microsoft Corporation */
623 /* */
624 /* DESCRIPTION */
625 /* */
626 /* This function retrieves code value from dynamic huffman table. */
627 /* */
628 /* INPUT */
629 /* */
630 /* png PNG control block */
631 /* huffman_bits_count Array records codes number for*/
632 /* every code len */
633 /* scan_buffer Buffer to search from */
634 /* bit_len Retrieved Huffman Code Length */
635 /* code_value Retrieved Huffman Code */
636 /* */
637 /* OUTPUT */
638 /* */
639 /* Status code */
640 /* */
641 /* CALLS */
642 /* */
643 /* _gx_image_reader_png_bits_revert Reorder bits stream in */
644 /* opposite order */
645 /* */
646 /* CALLED BY */
647 /* */
648 /* _gx_image_reader_png_huffcode_decode */
649 /* _gx_image_reader_png_ll_huffman_read */
650 /* */
651 /* RELEASE HISTORY */
652 /* */
653 /* DATE NAME DESCRIPTION */
654 /* */
655 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
656 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
657 /* resulting in version 6.1 */
658 /* */
659 /**************************************************************************/
_gx_image_reader_png_dynamic_huffman_code_find(INT * huffman_table,UINT * huffman_bits_count,UINT scan_buffer,UINT * bit_len,UINT * code_value)660 static UINT _gx_image_reader_png_dynamic_huffman_code_find(INT *huffman_table,
661 UINT *huffman_bits_count,
662 UINT scan_buffer,
663 UINT *bit_len,
664 UINT *code_value)
665 {
666 UINT i_bit;
667 UINT bit_count;
668 UINT code;
669 UINT code_cal = 0;
670 UINT code_index = 0;
671
672 for (i_bit = 1; i_bit < 16; i_bit++)
673 {
674 bit_count = huffman_bits_count[i_bit] - huffman_bits_count[i_bit - 1];
675
676 if (bit_count)
677 {
678 code = (scan_buffer) << (32 - i_bit);
679 code = (code) >> (32 - i_bit);
680
681 _gx_image_reader_png_bits_revert(&code, i_bit);
682
683 if (code <= code_cal + bit_count - 1)
684 {
685 *bit_len = i_bit;
686 *code_value = (UINT)huffman_table[code_index + code - code_cal];
687
688 return GX_SUCCESS;
689 }
690 else
691 {
692 code_index += bit_count;
693 code_cal += bit_count;
694 }
695 }
696
697 code_cal <<= 1;
698 }
699
700 return GX_NOT_FOUND;
701 }
702
703 /**************************************************************************/
704 /* */
705 /* FUNCTION RELEASE */
706 /* */
707 /* _gx_image_reader_png_fixed_ll_huffman_code_find PORTABLE C */
708 /* 6.1 */
709 /* AUTHOR */
710 /* */
711 /* Kenneth Maxwell, Microsoft Corporation */
712 /* */
713 /* DESCRIPTION */
714 /* */
715 /* This function retrieves code value from fixed huffman table. */
716 /* */
717 /* INPUT */
718 /* */
719 /* scan_buffer Buffer that contains Huffman */
720 /* code */
721 /* bit_len Retrieved Huffman Code length */
722 /* code_value Retrieved code value of the */
723 /* matched Huffman Code */
724 /* */
725 /* OUTPUT */
726 /* */
727 /* status Completion status */
728 /* */
729 /* CALLS */
730 /* */
731 /* _gx_image_reader_png_bits_revert Reorder bits stream in */
732 /* opposite order */
733 /* */
734 /* CALLED BY */
735 /* */
736 /* _gx_image_reader_png_huffcode_decode */
737 /* */
738 /* RELEASE HISTORY */
739 /* */
740 /* DATE NAME DESCRIPTION */
741 /* */
742 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
743 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
744 /* resulting in version 6.1 */
745 /* */
746 /**************************************************************************/
_gx_image_reader_png_fixed_ll_huffman_code_find(UINT scan_buffer,UINT * bit_len,UINT * code_value)747 static UINT _gx_image_reader_png_fixed_ll_huffman_code_find(UINT scan_buffer,
748 UINT *bit_len,
749 UINT *code_value)
750 {
751 UINT i_bit;
752 UINT code;
753
754 for (i_bit = 7; i_bit <= 9; i_bit++)
755 {
756 code = scan_buffer << (32 - i_bit);
757 code = code >> (32 - i_bit);
758
759 _gx_image_reader_png_bits_revert(&code, i_bit);
760
761 if (i_bit == 7)
762 {
763 if (code <= 0x17)
764 {
765 *bit_len = 7;
766 *code_value = 256 + code;
767 break;
768 }
769 }
770 else if (i_bit == 8)
771 {
772 if (code <= 0xbf)
773 {
774 /* code >= 0x30. */
775 *bit_len = 8;
776 *code_value = code - 0x30;
777 break;
778 }
779 else if (code <= 0xc7)
780 {
781 /* code >= 0xc0. */
782 *bit_len = 8;
783 *code_value = 280 + code - 0xc0;
784 break;
785 }
786 }
787 else
788 {
789 /* code >= 0x190 && code <= 0x1ff. */
790 *bit_len = 9;
791 *code_value = 144 + code - 0x190;
792 }
793 }
794
795 return GX_SUCCESS;
796 }
797
798 /**************************************************************************/
799 /* */
800 /* FUNCTION RELEASE */
801 /* */
802 /* _gx_image_reader_png_clen_huffman_read PORTABLE C */
803 /* 6.1 */
804 /* AUTHOR */
805 /* */
806 /* Kenneth Maxwell, Microsoft Corporation */
807 /* */
808 /* DESCRIPTION */
809 /* */
810 /* This function reads code length huffman table. */
811 /* */
812 /* INPUT */
813 /* */
814 /* png PNG control block */
815 /* hclen The number of "length" codes */
816 /* */
817 /* OUTPUT */
818 /* */
819 /* None */
820 /* */
821 /* CALLS */
822 /* */
823 /* _gx_image_reader_png_bits_get Extract bits from PNG data */
824 /* stream */
825 /* _gx_image_reader_png_bits_skip Skip bits from PNG data stream*/
826 /* */
827 /* CALLED BY */
828 /* */
829 /* _gx_image_reader_png_IDAT_chunk_read */
830 /* */
831 /* RELEASE HISTORY */
832 /* */
833 /* DATE NAME DESCRIPTION */
834 /* */
835 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
836 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
837 /* resulting in version 6.1 */
838 /* */
839 /**************************************************************************/
_gx_image_reader_png_clen_huffman_read(GX_PNG * png,UINT hclen)840 static UINT _gx_image_reader_png_clen_huffman_read(GX_PNG *png, UINT hclen)
841 {
842
843 INT code_value[19] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
844 INT code_len[19] = {0};
845 UINT len;
846 UINT i;
847 INT pos[16];
848
849 for (i = 0; i < hclen; i++)
850 {
851 if (_gx_image_reader_png_bits_get(png, 3, &len) != GX_SUCCESS)
852 {
853 return GX_FAILURE;
854 }
855 _gx_image_reader_png_bits_skip(3);
856 len &= 0x7;
857
858 /* record code len for code len alphabet */
859 code_len[code_value[i]] = (INT)len;
860
861 /* record codes number for every code len */
862 if (len)
863 {
864 png -> gx_png_huffman_clen_bits_count[len]++;
865 }
866 }
867
868 for (i = 1; i < 16; i++)
869 {
870 png -> gx_png_huffman_clen_bits_count[i] += png -> gx_png_huffman_clen_bits_count[i - 1];
871 }
872
873 memset(pos, -1, 16 * sizeof(INT));
874
875 for (i = 0; i < 19; i++)
876 {
877 if (code_len[i])
878 {
879 if (pos[code_len[i]] == -1)
880 {
881 pos[code_len[i]] = png -> gx_png_huffman_clen_bits_count[code_len[i] - 1];
882 }
883 png -> gx_png_huffman_clen_table[pos[code_len[i]]++] = (INT)i;
884 }
885 }
886
887 return GX_SUCCESS;
888 }
889
890 /**************************************************************************/
891 /* */
892 /* FUNCTION RELEASE */
893 /* */
894 /* _gx_image_reader_png_ll_huffman_read PORTABLE C */
895 /* 6.2.0 */
896 /* AUTHOR */
897 /* */
898 /* Kenneth Maxwell, Microsoft Corporation */
899 /* */
900 /* DESCRIPTION */
901 /* */
902 /* This function reads in literal and length huffman table. */
903 /* */
904 /* INPUT */
905 /* */
906 /* png PNG control block. */
907 /* hlit The number of "literal" codes */
908 /* hdist The number of "distance" codes*/
909 /* */
910 /* OUTPUT */
911 /* */
912 /* None */
913 /* */
914 /* CALLS */
915 /* */
916 /* _gx_image_reader_png_bits_get Extract bits from PNG data */
917 /* stream */
918 /* _gx_image_reader_png_bits_skip Skip bits from PNG data stream*/
919 /* _gx_image_reader_png_dynamic_huffman_code_find */
920 /* Retrieve code value from */
921 /* dynamic huffman table */
922 /* */
923 /* CALLED BY */
924 /* */
925 /* _gx_image_reader_png_IDAT_chunk_read */
926 /* */
927 /* RELEASE HISTORY */
928 /* */
929 /* DATE NAME DESCRIPTION */
930 /* */
931 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
932 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
933 /* resulting in version 6.1 */
934 /* 06-02-2021 Ting Zhu Modified comment(s), */
935 /* added invalid value check, */
936 /* resulting in version 6.1.7 */
937 /* 10-31-2022 Ting Zhu Modified comment(s), */
938 /* added invalid value check, */
939 /* resulting in version 6.2.0 */
940 /* */
941 /**************************************************************************/
_gx_image_reader_png_ll_huffman_read(GX_PNG * png,UINT hlit,UINT hdist)942 static UINT _gx_image_reader_png_ll_huffman_read(GX_PNG *png, UINT hlit, UINT hdist)
943 {
944 UINT scan_buffer;
945 UINT bit_len;
946 UINT code_value;
947 UINT repeat;
948 UINT i;
949 UINT count = 0;
950 INT pos[16];
951 INT index;
952
953 memset(png -> gx_png_huffman_lit_code_len, 0, sizeof(INT) * GX_PNG_HUFFMAN_LIT_CODE_LEN_TABLE_SIZE);
954 memset(png -> gx_png_huffman_dist_code_len, 0, sizeof(INT) * GX_PNG_HUFFMAN_DIST_CODE_LEN_TABLE_SIZE);
955
956 for (i = 0; i < hlit + hdist;)
957 {
958 count++;
959 if (_gx_image_reader_png_bits_get(png, 16, &scan_buffer) != GX_SUCCESS)
960 {
961 return GX_FAILURE;
962 }
963
964 if (_gx_image_reader_png_dynamic_huffman_code_find(png -> gx_png_huffman_clen_table,
965 (UINT *)png -> gx_png_huffman_clen_bits_count,
966 scan_buffer,
967 &bit_len,
968 &code_value) == 0)
969 {
970 _gx_image_reader_png_bits_skip(bit_len);
971
972 if (code_value <= 15)
973 {
974 /* Represent code lengths of 0-15 */
975 if (i < hlit)
976 {
977 png -> gx_png_huffman_lit_code_len[i] = (INT)code_value;
978
979 png -> gx_png_huffman_lit_bits_count[code_value]++;
980 }
981 else
982 {
983 png -> gx_png_huffman_dist_code_len[i - hlit] = (INT)code_value;
984 png -> gx_png_huffman_dist_bits_count[code_value]++;
985 }
986
987 i++;
988 }
989 else
990 {
991 if (code_value == 16)
992 {
993 /* repeat previous */
994 /* 2 bits repeat length*/
995 _gx_image_reader_png_bits_get(png, 2, &repeat);
996 _gx_image_reader_png_bits_skip(2);
997 repeat &= 0x3;
998 repeat += 3;
999
1000 if (i < 1)
1001 {
1002 return GX_FALSE;
1003 }
1004 else if ((i - 1) < hlit)
1005 {
1006 code_value = (UINT)png -> gx_png_huffman_lit_code_len[i - 1];
1007 }
1008 else
1009 {
1010 code_value = (UINT)png -> gx_png_huffman_dist_code_len[i - 1 - hlit];
1011 }
1012
1013 if (i < hlit)
1014 {
1015 png -> gx_png_huffman_lit_bits_count[code_value] += (INT)repeat;
1016
1017 while (repeat--)
1018 {
1019 png -> gx_png_huffman_lit_code_len[i++] = (INT)code_value;
1020 }
1021 }
1022 else
1023 {
1024 png -> gx_png_huffman_dist_bits_count[code_value] += (INT)repeat;
1025
1026 while (repeat--)
1027 {
1028 png -> gx_png_huffman_dist_code_len[i - hlit] = (INT)code_value;
1029 i++;
1030 }
1031 }
1032 }
1033 else
1034 {
1035 if (code_value == 17)
1036 {
1037 /* repeat 0 */
1038 /* 3 bits repeat length */
1039 _gx_image_reader_png_bits_get(png, 3, &repeat);
1040 _gx_image_reader_png_bits_skip(3);
1041 repeat &= 0x7;
1042 repeat += 3;
1043 }
1044 else
1045 {
1046 /* code_value = 18. */
1047 /* repeat 0*/
1048 /* 7 bits repeat length */
1049 _gx_image_reader_png_bits_get(png, 7, &repeat);
1050 _gx_image_reader_png_bits_skip(7);
1051 repeat &= 0x7f;
1052 repeat += 11;
1053 }
1054
1055 if (i < hlit)
1056 {
1057 memset(png -> gx_png_huffman_lit_code_len + i, 0, repeat * sizeof(INT));
1058 }
1059 else
1060 {
1061 memset(png -> gx_png_huffman_dist_code_len + i - hlit, 0, repeat * sizeof(INT));
1062 }
1063
1064 i += repeat;
1065 }
1066 }
1067 }
1068 else
1069 {
1070 /*error*/
1071 return GX_FAILURE;
1072 }
1073 }
1074
1075 png -> gx_png_huffman_lit_bits_count[0] = 0;
1076 png -> gx_png_huffman_dist_bits_count[0] = 0;
1077
1078 for (i = 2; i <= 16; i++)
1079 {
1080 png -> gx_png_huffman_lit_bits_count[i] += png -> gx_png_huffman_lit_bits_count[i - 1];
1081 png -> gx_png_huffman_dist_bits_count[i] += png -> gx_png_huffman_dist_bits_count[i - 1];
1082 }
1083
1084 memset(pos, -1, 16 * sizeof(INT));
1085
1086 for (i = 0; i < hlit; i++)
1087 {
1088 index = png -> gx_png_huffman_lit_code_len[i];
1089 if (index)
1090 {
1091 if (pos[index] == -1)
1092 {
1093 pos[index] = png -> gx_png_huffman_lit_bits_count[index - 1];
1094 }
1095 png -> gx_png_huffman_lit_table[pos[index]++] = (INT)i;
1096 }
1097 }
1098
1099 memset(pos, -1, 16 * sizeof(INT));
1100
1101 for (i = 0; i < hdist; i++)
1102 {
1103 index = png -> gx_png_huffman_dist_code_len[i];
1104 if (index)
1105 {
1106 if (pos[index] == -1)
1107 {
1108 pos[index] = png -> gx_png_huffman_dist_bits_count[index - 1];
1109 }
1110
1111 if (pos[index] >= GX_PNG_HUFFMAN_DIST_TABLE_SIZE)
1112 {
1113 /* Invalid data. */
1114 return GX_FAILURE;
1115 }
1116
1117 png -> gx_png_huffman_dist_table[pos[index]++] = (INT)i;
1118 }
1119 }
1120
1121 return GX_SUCCESS;
1122 }
1123
1124 /**************************************************************************/
1125 /* */
1126 /* FUNCTION RELEASE */
1127 /* */
1128 /* _gx_image_reader_png_huffcode_decode PORTABLE C */
1129 /* 6.1 */
1130 /* AUTHOR */
1131 /* */
1132 /* Kenneth Maxwell, Microsoft Corporation */
1133 /* */
1134 /* DESCRIPTION */
1135 /* */
1136 /* This function decodes the Huffman codes. */
1137 /* */
1138 /* INPUT */
1139 /* */
1140 /* png PNG control block. */
1141 /* dynamic True, use dynamic huff table */
1142 /* False, use fixed huff table */
1143 /* decoded_data_size Expected decoded data size */
1144 /* */
1145 /* OUTPUT */
1146 /* */
1147 /* None */
1148 /* */
1149 /* CALLS */
1150 /* */
1151 /* _gx_image_reader_png_bits_get Extract bits from PNG data */
1152 /* stream */
1153 /* _gx_image_reader_png_bits_skip Skip bits from PNG data stream*/
1154 /* _gx_image_reader_png_dynamic_huffman_code_find */
1155 /* Retrieve code value from */
1156 /* dynamic huffman table */
1157 /* _gx_image_reader_png_fixed_ll_huffman_code_find */
1158 /* Retrieve code value from */
1159 /* fixed huffman table */
1160 /* */
1161 /* CALLED BY */
1162 /* */
1163 /* _gx_image_reader_png_IDAT_chunk_read */
1164 /* */
1165 /* RELEASE HISTORY */
1166 /* */
1167 /* DATE NAME DESCRIPTION */
1168 /* */
1169 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
1170 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
1171 /* added data boundary check, */
1172 /* fixed gcc compile warning, */
1173 /* resulting in version 6.1 */
1174 /* */
1175 /**************************************************************************/
_gx_image_reader_png_huffcode_decode(GX_PNG * png,GX_BOOL dynamic,UINT decoded_data_size)1176 static UINT _gx_image_reader_png_huffcode_decode(GX_PNG *png, GX_BOOL dynamic, UINT decoded_data_size)
1177 {
1178 UINT scan_buffer;
1179 UINT bit_len = 0;
1180 UINT code_value = 300;
1181 UINT length;
1182 UINT distance;
1183 UINT extra_bits;
1184 UINT copy_len;
1185
1186 while (1)
1187 {
1188 if (_gx_image_reader_png_bits_get(png, 16, &scan_buffer) != GX_SUCCESS)
1189 {
1190 return GX_FAILURE;
1191 }
1192
1193 /* Decode literal/length value from input stream */
1194 if (dynamic)
1195 {
1196 _gx_image_reader_png_dynamic_huffman_code_find(png -> gx_png_huffman_lit_table,
1197 (UINT *)png -> gx_png_huffman_lit_bits_count,
1198 scan_buffer,
1199 &bit_len,
1200 &code_value);
1201 }
1202 else
1203 {
1204 _gx_image_reader_png_fixed_ll_huffman_code_find(scan_buffer, &bit_len, &code_value);
1205 }
1206
1207 _gx_image_reader_png_bits_skip(bit_len);
1208
1209 if (code_value < 256)
1210 {
1211 if ((UINT)(png -> gx_png_decoded_data_len + 1) > decoded_data_size)
1212 {
1213 /* Decoded data size exceed allocated buffer size. */
1214 return GX_FAILURE;
1215 }
1216
1217 png -> gx_png_decoded_data[png -> gx_png_decoded_data_len++] = (GX_UBYTE)code_value;
1218 }
1219 else if (code_value == 256)
1220 {
1221 /* End of the block */
1222 break;
1223 }
1224 else
1225 {
1226 if (code_value < 265)
1227 {
1228 /* 0 extra bits */
1229 length = 3 + code_value - 257;
1230 }
1231 else if (code_value < 285)
1232 {
1233 extra_bits = 1 + (code_value - 265) / 4;
1234 _gx_image_reader_png_bits_get(png, extra_bits, &length);
1235 _gx_image_reader_png_bits_skip(extra_bits);
1236 length <<= (32 - extra_bits);
1237 length >>= (32 - extra_bits);
1238
1239 length += 3u + (1u << (extra_bits + 2)) + ((1u << extra_bits) * ((code_value - 265) & 0x3));
1240 }
1241 else if (code_value == 285)
1242 {
1243 /* 0 extra bits */
1244 length = 258;
1245 }
1246 else
1247 {
1248 /* This should not happen. */
1249 return GX_FAILURE;
1250 }
1251
1252 if (dynamic)
1253 {
1254 _gx_image_reader_png_bits_get(png, 16, &scan_buffer);
1255
1256 /*decode distance from input stream */
1257 _gx_image_reader_png_dynamic_huffman_code_find(png -> gx_png_huffman_dist_table,
1258 (UINT *)png -> gx_png_huffman_dist_bits_count,
1259 scan_buffer,
1260 &bit_len,
1261 &code_value);
1262
1263 _gx_image_reader_png_bits_skip(bit_len);
1264 }
1265 else
1266 {
1267 /* Decodes 5-bits distance codes. */
1268 _gx_image_reader_png_bits_get(png, 5, &scan_buffer);
1269 _gx_image_reader_png_bits_skip(5);
1270 code_value = scan_buffer & 0x1f;
1271 _gx_image_reader_png_bits_revert(&code_value, 5);
1272 }
1273
1274 if (code_value < 4)
1275 {
1276 distance = 1 + code_value;
1277 }
1278 else if (code_value < 30)
1279 {
1280 extra_bits = 1 + (code_value - 4) / 2;
1281
1282 _gx_image_reader_png_bits_get(png, extra_bits, &distance);
1283 _gx_image_reader_png_bits_skip(extra_bits);
1284
1285 distance <<= (32 - extra_bits);
1286 distance >>= (32 - extra_bits);
1287
1288 distance += 1u + (1u << (extra_bits + 1)) + (1u << extra_bits) * ((code_value - 4) & 0x1);
1289 }
1290 else
1291 {
1292 /* This should not happen. */
1293 return GX_FALSE;
1294 }
1295
1296 /* move backwards distance bytes in the output stream, and copy
1297 length bytes from this position to the output stream. */
1298
1299 while (length)
1300 {
1301 if (length > distance)
1302 {
1303 copy_len = distance;
1304 length -= distance;
1305 }
1306 else
1307 {
1308 copy_len = length;
1309 length = 0;
1310 }
1311
1312 if ((distance > (UINT)png -> gx_png_decoded_data_len) ||
1313 ((UINT)png -> gx_png_decoded_data_len + copy_len > decoded_data_size))
1314 {
1315
1316 /* Distance exceed current decoded data length or copied length exceed remaining buffer size. */
1317 return GX_FAILURE;
1318 }
1319
1320 memcpy(png -> gx_png_decoded_data + png -> gx_png_decoded_data_len, /* Use case of memcpy is verified. */
1321 png -> gx_png_decoded_data + png -> gx_png_decoded_data_len - distance,
1322 copy_len * sizeof(GX_UBYTE));
1323 png -> gx_png_decoded_data_len += (INT)copy_len;
1324 }
1325 }
1326 }
1327
1328 return GX_SUCCESS;
1329 }
1330
1331 /**************************************************************************/
1332 /* */
1333 /* FUNCTION RELEASE */
1334 /* */
1335 /* _gx_image_reader_png_tRNS_chunk_read PORTABLE C */
1336 /* 6.1 */
1337 /* AUTHOR */
1338 /* */
1339 /* Kenneth Maxwell, Microsoft Corporation */
1340 /* */
1341 /* DESCRIPTION */
1342 /* */
1343 /* This function reads in the tRNS chunk information. */
1344 /* */
1345 /* INPUT */
1346 /* */
1347 /* png PNG control block. */
1348 /* */
1349 /* OUTPUT */
1350 /* */
1351 /* status Completion status */
1352 /* */
1353 /* CALLS */
1354 /* */
1355 /* _gx_system_memory_allocator Application defined memory */
1356 /* allocation function */
1357 /* */
1358 /* CALLED BY */
1359 /* */
1360 /* _gx_image_reader_png_decode */
1361 /* */
1362 /* RELEASE HISTORY */
1363 /* */
1364 /* DATE NAME DESCRIPTION */
1365 /* */
1366 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
1367 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
1368 /* resulting in version 6.1 */
1369 /* */
1370 /**************************************************************************/
_gx_image_reader_png_tRNS_chunk_read(GX_PNG * png)1371 static UINT _gx_image_reader_png_tRNS_chunk_read(GX_PNG *png)
1372 {
1373 INT index;
1374
1375 if ((png -> gx_png_color_type == 4) || (png -> gx_png_color_type == 6))
1376 {
1377 /* tRNS is prohibited for the other color types. */
1378 return GX_FAILURE;
1379 }
1380
1381 if (png -> gx_png_color_type == 3)
1382 {
1383 /* Contains a series of one-byte alpha values. */
1384 png -> gx_png_trans_num = png -> gx_png_trunk_end_index - png -> gx_png_data_index;
1385
1386 /* For color type 3, tRNS can contain fewer values than there are palette entries. */
1387 if (png -> gx_png_trans_num > 256)
1388 {
1389 return GX_INVALID_VALUE;
1390 }
1391 }
1392 else
1393 {
1394 /* For color type 0, the tRNS chunk contains a single two-bytes gray level value.
1395 For color type 2, the tRNS chunk contains a single two-bytes RGB color value. */
1396 png -> gx_png_trans_num = (png -> gx_png_trunk_end_index - png -> gx_png_data_index) >> 1;
1397
1398 if (png -> gx_png_trans_num > 3)
1399 {
1400 return GX_INVALID_VALUE;
1401 }
1402 }
1403
1404 /* Then trans num is no bigger than 256, multiplication will not overflow. */
1405 png -> gx_png_trans = (GX_COLOR *)_gx_system_memory_allocator((ULONG)png -> gx_png_trans_num * sizeof(GX_COLOR));
1406
1407 if (png -> gx_png_trans == GX_NULL)
1408 {
1409 return GX_SYSTEM_MEMORY_ERROR;
1410 }
1411
1412 for (index = 0; index < png -> gx_png_trans_num; index++)
1413 {
1414 png -> gx_png_trans[index] = png -> gx_png_data[png -> gx_png_data_index++];
1415
1416 if (png -> gx_png_color_type != 3)
1417 {
1418 png -> gx_png_trans[index] <<= 8;
1419 png -> gx_png_trans[index] |= png -> gx_png_data[png -> gx_png_data_index++];
1420 }
1421 }
1422
1423 return GX_SUCCESS;
1424 }
1425
1426 /**************************************************************************/
1427 /* */
1428 /* FUNCTION RELEASE */
1429 /* */
1430 /* _gx_image_reader_png_IDAT_chunk_read PORTABLE C */
1431 /* 6.1 */
1432 /* AUTHOR */
1433 /* */
1434 /* Kenneth Maxwell, Microsoft Corporation */
1435 /* */
1436 /* DESCRIPTION */
1437 /* */
1438 /* This function reads in the IDAT chunk information and start */
1439 /* decoding. */
1440 /* */
1441 /* INPUT */
1442 /* */
1443 /* png PNG control block. */
1444 /* */
1445 /* OUTPUT */
1446 /* */
1447 /* status Completion status */
1448 /* */
1449 /* CALLS */
1450 /* */
1451 /* _gx_image_reader_png_bits_get Extract bits from PNG data */
1452 /* stream */
1453 /* _gx_image_reader_png_bits_skip Skip bits from PNG data stream*/
1454 /* _gx_image_reader_png_clen_huffman_read */
1455 /* Read code length huffman table*/
1456 /* _gx_image_reader_png_ll_huffman_read Read literal and length */
1457 /* huffman table */
1458 /* _gx_image_reader_png_huffcode_decode Decode huffman codes */
1459 /* */
1460 /* CALLED BY */
1461 /* */
1462 /* _gx_image_reader_png_decode */
1463 /* */
1464 /* RELEASE HISTORY */
1465 /* */
1466 /* DATE NAME DESCRIPTION */
1467 /* */
1468 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
1469 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
1470 /* added data boundary check, */
1471 /* resulting in version 6.1 */
1472 /* */
1473 /**************************************************************************/
_gx_image_reader_png_IDAT_chunk_read(GX_PNG * png)1474 static UINT _gx_image_reader_png_IDAT_chunk_read(GX_PNG *png)
1475 {
1476 /*zlib format
1477 +---+---+
1478 |CMF|FLG|
1479 +---+---+
1480 if FLG.FDICT set
1481 +---+---+---+---+
1482 | DTCTID |
1483 +---+---+---+---+
1484 +=====================+---+---+---+---+
1485 |...compressed data...| 32bit checksum|
1486 +=====================+---+---+---+---+
1487 */
1488 UINT CMF;
1489 UINT FLG;
1490 INT compress_method;
1491 INT window_size;
1492 INT fdict;
1493 UINT header;
1494 INT hlit;
1495 INT hdist;
1496 INT hclen;
1497 UINT alloc_size;
1498 INT len;
1499 INT nlen;
1500
1501 if (_gx_image_reader_png_bits_get(png, 8, &CMF) != GX_SUCCESS)
1502 {
1503 return GX_FAILURE;
1504 }
1505
1506 _gx_image_reader_png_bits_skip(8);
1507
1508 if (_gx_image_reader_png_bits_get(png, 8, &FLG) != GX_SUCCESS)
1509 {
1510 return GX_FAILURE;
1511 }
1512
1513 _gx_image_reader_png_bits_skip(8);
1514
1515 compress_method = CMF & 0x0f;
1516 window_size = 2 << (((CMF & 0xf0) >> 4) + 8);
1517 fdict = FLG & 0x20;
1518
1519 if ((fdict != 0) ||
1520 (window_size > 65536) ||
1521 (compress_method != 8))
1522 {
1523 return GX_FAILURE;
1524 }
1525
1526 /* Safe int math is not required here, calling function limits max width, height to 14 bits so
1527 overflow cannot occur. */
1528 alloc_size = (UINT)(png -> gx_png_height * ((png -> gx_png_width * png -> gx_png_bpp + 7) / 8));
1529 alloc_size = alloc_size + (UINT)png -> gx_png_height;
1530 png -> gx_png_decoded_data = (GX_UBYTE *)_gx_system_memory_allocator(alloc_size);
1531 png -> gx_png_decoded_data_len = 0;
1532
1533 if (png -> gx_png_decoded_data == GX_NULL)
1534 {
1535 return GX_SYSTEM_MEMORY_ERROR;
1536 }
1537
1538 do
1539 {
1540 /* The header of one block */
1541 if (_gx_image_reader_png_bits_get(png, 8, &header) != GX_SUCCESS)
1542 {
1543 return GX_FAILURE;
1544 }
1545
1546 if ((header & 0x6) == 0x00)
1547 {
1548 _gx_image_reader_png_bits_skip(3);
1549
1550 /* no compression */
1551 _gx_image_reader_png_bits_skip(_bit_count & 0x7);
1552 if (_bit_count)
1553 {
1554 png -> gx_png_data_index -= (INT)(_bit_count / 8);
1555 _gx_image_reader_png_bits_skip(_bit_count);
1556 }
1557
1558 /* 4 = 2 bytes len + 2 bytes nlen. */
1559 if (png -> gx_png_data_index + 4 > png -> gx_png_data_size)
1560 {
1561 return GX_INVALID_SIZE;
1562 }
1563
1564 /* Read "LEN". */
1565 len = png -> gx_png_data[png -> gx_png_data_index];
1566 png -> gx_png_data_index++;
1567 len |= (png -> gx_png_data[png -> gx_png_data_index] << 8);
1568 png -> gx_png_data_index++;
1569
1570 /* Read "NLEN". */
1571 nlen = png -> gx_png_data[png -> gx_png_data_index];
1572 png -> gx_png_data_index++;
1573 nlen |= (png -> gx_png_data[png -> gx_png_data_index] << 8);
1574 png -> gx_png_data_index++;
1575
1576 if (len + nlen != 65535)
1577 {
1578 /* NLEN is not one's complement of LEN. */
1579 return GX_FAILURE;
1580 }
1581
1582 /* Read data to outbuffer directly */
1583 if (len)
1584 {
1585 if ((UINT)(png -> gx_png_decoded_data_len + len) > alloc_size)
1586 {
1587 /* Copied size exceed remaining buffer size. */
1588 return GX_FAILURE;
1589 }
1590
1591 if (png -> gx_png_data_index + len > png -> gx_png_data_size)
1592 {
1593 return GX_INVALID_SIZE;
1594 }
1595
1596 memcpy(png -> gx_png_decoded_data + png -> gx_png_decoded_data_len, png -> gx_png_data + png -> gx_png_data_index, (UINT)len); /* Use case of memcpy is verified. */
1597 png -> gx_png_data_index += len;
1598 png -> gx_png_decoded_data_len += len;
1599 }
1600 }
1601 else if ((header & 0x6) == 0x2)
1602 {
1603 _gx_image_reader_png_bits_skip(3);
1604
1605 /* compressed with fixed Huffman codes */
1606 if (_gx_image_reader_png_huffcode_decode(png, GX_FALSE, alloc_size) != GX_SUCCESS)
1607 {
1608 return GX_FAILURE;
1609 }
1610 }
1611 else if ((header & 0x6) == 0x4)
1612 {
1613 /* compressed with dynamic Huffman codes */
1614 _gx_image_reader_png_bits_skip(3);
1615
1616 /* # of Literal/Length codes */
1617 _gx_image_reader_png_bits_get(png, 5, (unsigned int *)&hlit);
1618
1619 _gx_image_reader_png_bits_skip(5);
1620 hlit = (hlit & 0x1f) + 257;
1621
1622 /* # of Distance codes */
1623 if (_gx_image_reader_png_bits_get(png, 5, (unsigned int *)&hdist) != GX_SUCCESS)
1624 {
1625 return GX_FAILURE;
1626 }
1627 _gx_image_reader_png_bits_skip(5);
1628 hdist = (hdist & 0x1f) + 1;
1629
1630 /* # of Code Length codes */
1631 if (_gx_image_reader_png_bits_get(png, 4, (unsigned int *)&hclen) != GX_SUCCESS)
1632 {
1633 return GX_FAILURE;
1634 }
1635 _gx_image_reader_png_bits_skip(4);
1636 hclen = (hclen & 0xf) + 4;
1637
1638 memset(png -> gx_png_huffman_clen_bits_count, 0, 17 * sizeof(INT));
1639 memset(png -> gx_png_huffman_clen_table, 0, 20 * sizeof(INT));
1640 memset(png -> gx_png_huffman_lit_bits_count, 0, 17 * sizeof(INT));
1641 memset(png -> gx_png_huffman_lit_table, 0, GX_PNG_HUFFMAN_LIT_TABLE_SIZE * sizeof(int));
1642 memset(png -> gx_png_huffman_dist_bits_count, 0, 17 * sizeof(INT));
1643 memset(png -> gx_png_huffman_dist_table, 0, 30 * sizeof(INT));
1644
1645 if (_gx_image_reader_png_clen_huffman_read(png, (UINT)hclen) != GX_SUCCESS)
1646 {
1647 return GX_FAILURE;
1648 }
1649
1650 if (_gx_image_reader_png_ll_huffman_read(png, (UINT)hlit, (UINT)hdist) != GX_SUCCESS)
1651 {
1652 return GX_FAILURE;
1653 }
1654
1655 if (_gx_image_reader_png_huffcode_decode(png, GX_TRUE, alloc_size) != GX_SUCCESS)
1656 {
1657 return GX_FAILURE;
1658 }
1659 }
1660 else
1661 {
1662 /* error */
1663 return GX_FAILURE;
1664 }
1665 } while ((header & 0x1) != 0x1);
1666
1667 /* Skip checksum */
1668 png -> gx_png_data_index = png -> gx_png_trunk_end_index;
1669 _gx_image_reader_png_bits_skip(_bit_count);
1670
1671 if (alloc_size != (UINT)png -> gx_png_decoded_data_len)
1672 {
1673 /* Decoded data size doesn't match prediction. */
1674 return GX_FAILURE;
1675 }
1676
1677 return GX_SUCCESS;
1678 }
1679
1680 /**************************************************************************/
1681 /* */
1682 /* FUNCTION RELEASE */
1683 /* */
1684 /* _gx_image_reader_png_gAMA_chunk_read PORTABLE C */
1685 /* 6.1 */
1686 /* AUTHOR */
1687 /* */
1688 /* Kenneth Maxwell, Microsoft Corporation */
1689 /* */
1690 /* DESCRIPTION */
1691 /* */
1692 /* This function reads in the gAMA chunk information. */
1693 /* */
1694 /* INPUT */
1695 /* */
1696 /* png PNG control block. */
1697 /* */
1698 /* OUTPUT */
1699 /* */
1700 /* status Completion status */
1701 /* */
1702 /* CALLS */
1703 /* */
1704 /* _gx_image_reader_png_4bytes_read Read 4 bytes and pact it to */
1705 /* an INT value */
1706 /* */
1707 /* CALLED BY */
1708 /* */
1709 /* _gx_image_reader_png_decode */
1710 /* */
1711 /* RELEASE HISTORY */
1712 /* */
1713 /* DATE NAME DESCRIPTION */
1714 /* */
1715 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
1716 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
1717 /* added data boundary check, */
1718 /* resulting in version 6.1 */
1719 /* */
1720 /**************************************************************************/
_gx_image_reader_png_gAMA_chunk_read(GX_PNG * png)1721 static UINT _gx_image_reader_png_gAMA_chunk_read(GX_PNG *png)
1722 {
1723 if (png -> gx_png_data_index + 4 > png -> gx_png_trunk_end_index)
1724 {
1725 return GX_INVALID_SIZE;
1726 }
1727
1728 /* Specifies the gamma of the camera that produced the image. */
1729
1730 /* A gamma of 0.45 would be stored as teh integer 45000. */
1731 _gx_image_reader_png_4bytes_read(png, &png -> gx_png_gamma);
1732
1733 return GX_SUCCESS;
1734 }
1735
1736 /**************************************************************************/
1737 /* */
1738 /* FUNCTION RELEASE */
1739 /* */
1740 /* _gx_image_reader_png_PLTE_chunk_read PORTABLE C */
1741 /* 6.1 */
1742 /* AUTHOR */
1743 /* */
1744 /* Kenneth Maxwell, Microsoft Corporation */
1745 /* */
1746 /* DESCRIPTION */
1747 /* */
1748 /* This function reads in the PLTE chunk information. */
1749 /* */
1750 /* INPUT */
1751 /* */
1752 /* png PNG control block. */
1753 /* */
1754 /* OUTPUT */
1755 /* */
1756 /* status Completion status */
1757 /* */
1758 /* CALLS */
1759 /* */
1760 /* None */
1761 /* */
1762 /* CALLED BY */
1763 /* */
1764 /* _gx_image_reader_png_decode */
1765 /* */
1766 /* RELEASE HISTORY */
1767 /* */
1768 /* DATE NAME DESCRIPTION */
1769 /* */
1770 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
1771 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
1772 /* resulting in version 6.1 */
1773 /* */
1774 /**************************************************************************/
_gx_image_reader_png_PLTE_chunk_read(GX_PNG * png)1775 static UINT _gx_image_reader_png_PLTE_chunk_read(GX_PNG *png)
1776 {
1777 INT index;
1778 GX_UBYTE red;
1779 GX_UBYTE green;
1780 GX_UBYTE blue;
1781
1782 png -> gx_png_palette_table_size = (png -> gx_png_trunk_end_index - png -> gx_png_data_index) / 3;
1783
1784 /* The PLTE chunk contains from 1 to 256 palette entries. */
1785 if (png -> gx_png_palette_table_size > 256)
1786 {
1787 return GX_INVALID_VALUE;
1788 }
1789
1790 for (index = 0; index < png -> gx_png_palette_table_size; index++)
1791 {
1792 red = png -> gx_png_data[png -> gx_png_data_index++];
1793 green = png -> gx_png_data[png -> gx_png_data_index++];
1794 blue = png -> gx_png_data[png -> gx_png_data_index++];
1795
1796 png -> gx_png_palette_table[index] = (GX_COLOR)((red << 16) | (green << 8) | blue);
1797 }
1798
1799 return GX_SUCCESS;
1800 }
1801
1802 /**************************************************************************/
1803 /* */
1804 /* FUNCTION RELEASE */
1805 /* */
1806 /* _gx_image_reader_png_paeth_predictor PORTABLE C */
1807 /* 6.1.8 */
1808 /* AUTHOR */
1809 /* */
1810 /* Kenneth Maxwell, Microsoft Corporation */
1811 /* */
1812 /* DESCRIPTION */
1813 /* */
1814 /* This function performs Paeth filter algorithm. */
1815 /* */
1816 /* INPUT */
1817 /* */
1818 /* a Byte of left pixel. */
1819 /* b Byte of above pixel. */
1820 /* c Byte of upper left pixel. */
1821 /* */
1822 /* OUTPUT */
1823 /* */
1824 /* status The nearest of a, b, c. */
1825 /* */
1826 /* CALLS */
1827 /* */
1828 /* None */
1829 /* */
1830 /* CALLED BY */
1831 /* */
1832 /* _gx_image_reader_png_unfilter */
1833 /* */
1834 /* RELEASE HISTORY */
1835 /* */
1836 /* DATE NAME DESCRIPTION */
1837 /* */
1838 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
1839 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
1840 /* resulting in version 6.1 */
1841 /* 08-02-2021 Kenneth Maxwell Modified comment(s), */
1842 /* replaced abs with GX_ABS, */
1843 /* resulting in version 6.1.8 */
1844 /* */
1845 /**************************************************************************/
_gx_image_reader_png_paeth_predictor(GX_UBYTE a,GX_UBYTE b,GX_UBYTE c)1846 static GX_UBYTE _gx_image_reader_png_paeth_predictor(GX_UBYTE a, GX_UBYTE b, GX_UBYTE c)
1847 {
1848 INT p;
1849 INT pa, pb, pc;
1850
1851 p = a + b - c;
1852 pa = GX_ABS(p - a);
1853 pb = GX_ABS(p - b);
1854 pc = GX_ABS(p - c);
1855
1856 /*return nearest of a, b, c */
1857
1858 if ((pa <= pb) && (pa <= pc))
1859 {
1860 return a;
1861 }
1862 else if (pb <= pc)
1863 {
1864 return b;
1865 }
1866 else
1867 {
1868 return c;
1869 }
1870 }
1871
1872 /**************************************************************************/
1873 /* */
1874 /* FUNCTION RELEASE */
1875 /* */
1876 /* _gx_image_reader_png_unfilter PORTABLE C */
1877 /* 6.2.0 */
1878 /* AUTHOR */
1879 /* */
1880 /* Kenneth Maxwell, Microsoft Corporation */
1881 /* */
1882 /* DESCRIPTION */
1883 /* */
1884 /* This function reverts the effect of filter. */
1885 /* */
1886 /* INPUT */
1887 /* */
1888 /* png PNG control block. */
1889 /* */
1890 /* OUTPUT */
1891 /* */
1892 /* None */
1893 /* */
1894 /* CALLS */
1895 /* */
1896 /* memmove */
1897 /* _gx_image_reader_png_paeth_predictor Perform Paeth filter algorithm*/
1898 /* */
1899 /* CALLED BY */
1900 /* */
1901 /* _gx_image_reader_png_decode */
1902 /* */
1903 /* RELEASE HISTORY */
1904 /* */
1905 /* DATE NAME DESCRIPTION */
1906 /* */
1907 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
1908 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
1909 /* resulting in version 6.1 */
1910 /* 10-31-2022 Kenneth Maxwell Modified comment(s), */
1911 /* added null pointer check, */
1912 /* resulting in version 6.2.0 */
1913 /* */
1914 /**************************************************************************/
_gx_image_reader_png_unfilter(GX_PNG * png)1915 static UINT _gx_image_reader_png_unfilter(GX_PNG *png)
1916 {
1917 INT filter_type;
1918 INT byte_width;
1919 INT pos;
1920 INT bpp = png -> gx_png_bpp;
1921 INT x;
1922 INT y;
1923
1924 if (png -> gx_png_decoded_data == GX_NULL)
1925 {
1926 /* This happens when IDAT chunk is missing. */
1927 return GX_FAILURE;
1928 }
1929
1930 byte_width = (png -> gx_png_width * bpp + 7) >> 3;
1931 bpp = (bpp + 7) >> 3;
1932
1933 for (y = 0; y < png -> gx_png_height; y++)
1934 {
1935 filter_type = png -> gx_png_decoded_data[y * byte_width + y];
1936
1937 pos = y * byte_width;
1938 memmove(png -> gx_png_decoded_data + pos, png -> gx_png_decoded_data + pos + y + 1, (UINT)byte_width);
1939
1940 switch (filter_type)
1941 {
1942 case 0:
1943 break;
1944 case 1:
1945 /* sub(x) + raw(x-bpp)*/
1946 for (x = bpp; x < byte_width; x++)
1947 {
1948 png -> gx_png_decoded_data[pos + x] = (GX_UBYTE)(png -> gx_png_decoded_data[pos + x] + png -> gx_png_decoded_data[pos + x - bpp]);
1949 }
1950 break;
1951 case 2:
1952 /*up(x) + prior(x)*/
1953 if (y == 0)
1954 {
1955 break;
1956 }
1957
1958 for (x = 0; x < byte_width; x++)
1959 {
1960 png -> gx_png_decoded_data[pos + x] = (GX_UBYTE)(png -> gx_png_decoded_data[pos + x] + png -> gx_png_decoded_data[pos + x - byte_width]);
1961 }
1962 break;
1963 case 3:
1964 /* average(x) + floor((raw(x-bpp)+prior(x))/2 */
1965 if (y == 0)
1966 {
1967 for (x = bpp; x < byte_width; x++)
1968 {
1969 png -> gx_png_decoded_data[pos + x] = (GX_UBYTE)(png -> gx_png_decoded_data[pos + x] + (png -> gx_png_decoded_data[pos + x - bpp] >> 1));
1970 }
1971 }
1972 else
1973 {
1974 for (x = 0; x < bpp; x++)
1975 {
1976 png -> gx_png_decoded_data[pos + x] = (GX_UBYTE)(png -> gx_png_decoded_data[pos + x] + (png -> gx_png_decoded_data[pos + x - byte_width] >> 1));
1977 }
1978
1979 for (x = bpp; x < byte_width; x++)
1980 {
1981 png -> gx_png_decoded_data[pos + x] = (GX_UBYTE)(png -> gx_png_decoded_data[pos + x] + ((png -> gx_png_decoded_data[pos + x - bpp] +
1982 png -> gx_png_decoded_data[pos + x - byte_width]) >> 1));
1983 }
1984 }
1985 break;
1986 case 4:
1987 /* paeth(x) + paethpredictor(raw(x-bpp), prior(x), prior(x-bpp)) */
1988 if (y == 0)
1989 {
1990 for (x = bpp; x < byte_width; x++)
1991 {
1992 png -> gx_png_decoded_data[pos + x] = (GX_UBYTE)(png -> gx_png_decoded_data[pos + x] + png -> gx_png_decoded_data[pos + x - bpp]);
1993 }
1994 }
1995 else
1996 {
1997 for (x = 0; x < bpp; x++)
1998 {
1999 png -> gx_png_decoded_data[pos + x] = (GX_UBYTE)(png -> gx_png_decoded_data[pos + x] + png -> gx_png_decoded_data[pos + x - byte_width]);
2000 }
2001
2002 for (x = bpp; x < byte_width; x++)
2003 {
2004 png -> gx_png_decoded_data[pos + x] = (GX_UBYTE)(png -> gx_png_decoded_data[pos + x] + _gx_image_reader_png_paeth_predictor(png -> gx_png_decoded_data[pos + x - bpp],
2005 png -> gx_png_decoded_data[pos + x - byte_width],
2006 png -> gx_png_decoded_data[pos + x - byte_width - bpp]));
2007 }
2008 }
2009 break;
2010 default:
2011 return GX_FAILURE;
2012 }
2013 }
2014
2015 png -> gx_png_decoded_data_len -= png -> gx_png_height;
2016
2017 return GX_SUCCESS;
2018 }
2019
2020 /**************************************************************************/
2021 /* */
2022 /* FUNCTION RELEASE */
2023 /* */
2024 /* _gx_image_reader_png_decode PORTABLE C */
2025 /* 6.2.0 */
2026 /* AUTHOR */
2027 /* */
2028 /* Kenneth Maxwell, Microsoft Corporation */
2029 /* */
2030 /* DESCRIPTION */
2031 /* */
2032 /* This function decode a PNG format image. */
2033 /* */
2034 /* INPUT */
2035 /* */
2036 /* inmap Input pixelmap */
2037 /* outmap Output pixelmap */
2038 /* */
2039 /* OUTPUT */
2040 /* */
2041 /* status Completion status */
2042 /* */
2043 /* CALLS */
2044 /* */
2045 /* strncmp */
2046 /* _gx_system_memory_allocator Application defined memory */
2047 /* allocation function */
2048 /* _gx_system_memory_free Application defined memory */
2049 /* free function */
2050 /* _gx_image_reader_png_crc_table_make Create a crc table */
2051 /* _gx_image_reader_png_crc_get Calculate crc value of */
2052 /* specified data */
2053 /* _gx_image_reader_png_4bytes_read Read 4 bytes and pack it to */
2054 /* INT type value */
2055 /* _gx_image_reader_png_chunk_type_read Read chunk type information */
2056 /* _gx_image_reader_png_IDAT_chunk_read Read IDAT chunk information */
2057 /* and start decoding */
2058 /* _gx_image_reader_png_IHDR_chunk_read Read IHDR chunk information */
2059 /* _gx_image_reader_png_gAMA_chunk_read Read gAMA chunk information */
2060 /* _gx_image_reader_png_PLTE_chunk_read Read PLTE chunk information */
2061 /* _gx_image_reader_png_tRNS_chunk_read Read tRNS chunk information */
2062 /* _gx_image_reader_png_unfilter Revert effect of filter */
2063 /* */
2064 /* CALLED BY */
2065 /* */
2066 /* _gx_image_reader_image_decode */
2067 /* */
2068 /* RELEASE HISTORY */
2069 /* */
2070 /* DATE NAME DESCRIPTION */
2071 /* */
2072 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
2073 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
2074 /* added data boundary check, */
2075 /* resulting in version 6.1 */
2076 /* 06-02-2021 Ting Zhu Modified comment(s), and */
2077 /* improved png decoding */
2078 /* performance, */
2079 /* resulting in version 6.1.7 */
2080 /* 10-31-2022 Ting Zhu Modified comment(s), and */
2081 /* added invalid value check, */
2082 /* resulting in version 6.2.0 */
2083 /* */
2084 /**************************************************************************/
_gx_image_reader_png_decode(GX_CONST GX_UBYTE * read_data,ULONG data_size,GX_PIXELMAP * outmap)2085 UINT _gx_image_reader_png_decode(GX_CONST GX_UBYTE *read_data, ULONG data_size, GX_PIXELMAP *outmap)
2086 {
2087 UINT status = GX_SUCCESS;
2088 GX_PNG png;
2089 INT data_len;
2090 CHAR chunk_type[4];
2091 INT checksum;
2092 GX_BOOL idat_done = GX_FALSE;
2093 INT *scratch_buffer;
2094 INT scratch_index = 0;
2095 GX_BOOL decoded_done = GX_FALSE;
2096
2097 if (data_size < 8)
2098 {
2099 return GX_INVALID_SIZE;
2100 }
2101
2102 if ((read_data[0] == 137) &&
2103 (read_data[1] == 80) &&
2104 (read_data[2] == 78) &&
2105 (read_data[3] == 71) &&
2106 (read_data[4] == 13) &&
2107 (read_data[5] == 10) &&
2108 (read_data[6] == 26) &&
2109 (read_data[7] == 10))
2110 {
2111 if (!_gx_system_memory_allocator)
2112 {
2113 return GX_SYSTEM_MEMORY_ERROR;
2114 }
2115
2116 memset(&png, 0, sizeof(GX_PNG));
2117 scratch_buffer = (INT *)_gx_system_memory_allocator(GX_PNG_SCRATCH_BUFFER_SIZE * sizeof(ULONG));
2118
2119 if (scratch_buffer == GX_NULL)
2120 {
2121 return GX_SYSTEM_MEMORY_ERROR;
2122 }
2123
2124 png.gx_png_crc_table = (UINT *)scratch_buffer;
2125 scratch_index += GX_PNG_CRC_TABLE_SIZE;
2126 png.gx_png_huffman_lit_table = scratch_buffer + scratch_index;
2127 scratch_index += GX_PNG_HUFFMAN_LIT_TABLE_SIZE;
2128 png.gx_png_huffman_lit_code_len = scratch_buffer + scratch_index;
2129 scratch_index += GX_PNG_HUFFMAN_LIT_CODE_LEN_TABLE_SIZE;
2130 png.gx_png_huffman_dist_code_len = scratch_buffer + scratch_index;
2131 scratch_index += GX_PNG_HUFFMAN_DIST_CODE_LEN_TABLE_SIZE;
2132 png.gx_png_palette_table = (GX_COLOR *)scratch_buffer + scratch_index;
2133
2134 png.gx_png_data = (GX_UBYTE *)read_data;
2135 png.gx_png_data_size = (INT)data_size;
2136 png.gx_png_data_index = 8;
2137
2138 _gx_image_reader_png_crc_table_make(&png);
2139
2140 _bit_buffer = 0;
2141 _bit_count = 0;
2142
2143 while (png.gx_png_data_index < png.gx_png_data_size - 4)
2144 {
2145 /* data_len*/
2146 _gx_image_reader_png_4bytes_read(&png, &data_len);
2147
2148 png.gx_png_trunk_crc = 0xffffffff;
2149
2150 if ((data_len < 0) ||
2151 (data_len > png.gx_png_data_size - png.gx_png_data_index - 4))
2152 {
2153 status = GX_INVALID_SIZE;
2154 break;
2155 }
2156
2157 /* Calculate checksum of the chunk data. */
2158 _gx_image_reader_png_crc_get(&png, &png.gx_png_trunk_crc, (UINT)(4 + data_len));
2159
2160 /* Read chunk type. */
2161 _gx_image_reader_png_chunk_type_read(&png, chunk_type);
2162
2163 png.gx_png_trunk_end_index = png.gx_png_data_index + data_len;
2164
2165 if ((strncmp(chunk_type, "IDAT", 4) == 0) && (!idat_done))
2166 {
2167 idat_done = GX_TRUE;
2168
2169 status = _gx_image_reader_png_IDAT_chunk_read(&png);
2170 }
2171 else if (strncmp(chunk_type, "IHDR", 4) == 0)
2172 {
2173 status = _gx_image_reader_png_IHDR_chunk_read(&png);
2174 }
2175 else if (strncmp(chunk_type, "gAMA", 4) == 0)
2176 {
2177 status = _gx_image_reader_png_gAMA_chunk_read(&png);
2178 }
2179 else if (strncmp(chunk_type, "PLTE", 4) == 0)
2180 {
2181 status = _gx_image_reader_png_PLTE_chunk_read(&png);
2182 }
2183 else if ((strncmp(chunk_type, "tRNS", 4) == 0) && (png.gx_png_trans == GX_NULL))
2184 {
2185 /* Read transparent information. */
2186 status = _gx_image_reader_png_tRNS_chunk_read(&png);
2187 }
2188 else if (strncmp(chunk_type, "IEND", 4) == GX_SUCCESS)
2189 {
2190 /* End */
2191 decoded_done = GX_TRUE;
2192 break;
2193 }
2194 else
2195 {
2196 /* Ignore chunk */
2197 png.gx_png_data_index += data_len;
2198 }
2199
2200 if (status != GX_SUCCESS)
2201 {
2202 break;
2203 }
2204
2205 _gx_image_reader_png_4bytes_read(&png, &checksum);
2206
2207 if (checksum != (INT)png.gx_png_trunk_crc)
2208 {
2209 status = GX_FAILURE;
2210 break;
2211 }
2212 }
2213
2214 if(status == GX_SUCCESS && (!decoded_done))
2215 {
2216 status = GX_FAILURE;
2217 }
2218
2219 if (status == GX_SUCCESS)
2220 {
2221 /* revert filter */
2222 status = _gx_image_reader_png_unfilter(&png);
2223 }
2224
2225 if (status == GX_SUCCESS)
2226 {
2227 outmap -> gx_pixelmap_data = png.gx_png_decoded_data;
2228 outmap -> gx_pixelmap_data_size = (ULONG)png.gx_png_decoded_data_len;
2229 outmap -> gx_pixelmap_width = (GX_VALUE)png.gx_png_width;
2230 outmap -> gx_pixelmap_height = (GX_VALUE)png.gx_png_height;
2231 outmap -> gx_pixelmap_flags = GX_PIXELMAP_RAW_FORMAT;
2232
2233 if (png.gx_png_trans_num)
2234 {
2235 outmap -> gx_pixelmap_flags |= GX_PIXELMAP_ALPHA;
2236 outmap -> gx_pixelmap_transparent_color = (ULONG)png.gx_png_trans;
2237 }
2238
2239 switch (png.gx_png_color_type)
2240 {
2241 case 6:
2242 /* Each pixel is an RGB triple, followed by an alpha sample. */
2243 if (png.gx_png_bit_depth == 8)
2244 {
2245 outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_32BPP;
2246 }
2247 else
2248 {
2249 /* Bit depth = 16. */
2250 outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_64BPP;
2251 }
2252 outmap -> gx_pixelmap_flags |= GX_PIXELMAP_ALPHA;
2253 break;
2254 case 4:
2255 /* Each pixel is a grayscale sample followed by an alpha sample. */
2256 if (png.gx_png_bit_depth == 8)
2257 {
2258 outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_16BPP_GRAY_ALPHA;
2259 }
2260 else
2261 {
2262 /* Bit depth = 16. */
2263 outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_32BPP_GRAY_ALPHA;
2264 }
2265 outmap -> gx_pixelmap_flags |= GX_PIXELMAP_ALPHA;
2266 break;
2267 case 3:
2268 /* Each pixel is a palette index */
2269 switch (png.gx_png_bit_depth)
2270 {
2271 case 1:
2272 outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_1BPP;
2273 break;
2274 case 2:
2275 outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_2BPP;
2276 break;
2277 case 4:
2278 outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_4BPP;
2279 break;
2280 default:
2281 /* Bit depth = 8. */
2282 outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_8BPP;
2283 break;
2284 }
2285
2286 /* Palette table size is no bigger than 256, aux data size will not overflow. */
2287 outmap -> gx_pixelmap_aux_data_size = (ULONG)(png.gx_png_palette_table_size) * sizeof(GX_COLOR);
2288 outmap -> gx_pixelmap_aux_data = (GX_UBYTE *)_gx_system_memory_allocator(outmap -> gx_pixelmap_aux_data_size);
2289
2290 if (!outmap -> gx_pixelmap_aux_data)
2291 {
2292 return GX_SYSTEM_MEMORY_ERROR;
2293 }
2294
2295 memcpy((GX_UBYTE *)outmap -> gx_pixelmap_aux_data, png.gx_png_palette_table, outmap -> gx_pixelmap_aux_data_size); /* Use case of memcpy is verified. */
2296 break;
2297 case 2:
2298 /* Each pixel is an RGB triple. */
2299 if (png.gx_png_bit_depth == 8)
2300 {
2301 outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_24BPP;
2302 }
2303 else
2304 {
2305 /* Bit depth = 16. */
2306 outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_48BPP;
2307 }
2308 break;
2309 default:
2310 /* Each pixel is a grayscale sample. */
2311 switch (png.gx_png_bit_depth)
2312 {
2313 case 16:
2314 outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_16BPP_GRAY;
2315 break;
2316 case 8:
2317 outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_8BPP;
2318 break;
2319 case 4:
2320 outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_4BPP;
2321 break;
2322 case 2:
2323 outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_2BPP;
2324 break;
2325 default:
2326 /* Bit depth = 1. */
2327 outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_1BPP;
2328 break;
2329 }
2330 break;
2331 }
2332 }
2333
2334 if (status != GX_SUCCESS)
2335 {
2336 if (png.gx_png_decoded_data)
2337 {
2338 _gx_system_memory_free(png.gx_png_decoded_data);
2339 }
2340
2341 if (png.gx_png_trans)
2342 {
2343 _gx_system_memory_free(png.gx_png_trans);
2344 }
2345 }
2346
2347 /* Free scratch buffer. */
2348 _gx_system_memory_free(scratch_buffer);
2349 }
2350 else
2351 {
2352 return GX_FAILURE;
2353 }
2354
2355 return status;
2356 }
2357 #endif
2358
2359