GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
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 |
/**************************************************************************/ |
||
75 |
666 |
static VOID _gx_image_reader_png_crc_table_make(GX_PNG *png) |
|
76 |
{ |
||
77 |
UINT crc; |
||
78 |
UINT n; |
||
79 |
UINT k; |
||
80 |
|||
81 |
✓✓ | 171162 |
for (n = 0; n < 256; n++) |
82 |
{ |
||
83 |
170496 |
crc = n; |
|
84 |
✓✓ | 1534464 |
for (k = 0; k < 8; k++) |
85 |
{ |
||
86 |
✓✓ | 1363968 |
if (crc & 1) |
87 |
{ |
||
88 |
681984 |
crc = 0xedb88320 ^ (crc >> 1); |
|
89 |
} |
||
90 |
else |
||
91 |
{ |
||
92 |
681984 |
crc = crc >> 1; |
|
93 |
} |
||
94 |
} |
||
95 |
170496 |
png -> gx_png_crc_table[n] = crc; |
|
96 |
} |
||
97 |
666 |
} |
|
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 |
/**************************************************************************/ |
||
142 |
4274 |
static VOID _gx_image_reader_png_crc_get(GX_PNG *png, UINT *crc, UINT len) |
|
143 |
{ |
||
144 |
UINT n; |
||
145 |
4274 |
GX_UBYTE *buf = png -> gx_png_data + png -> gx_png_data_index; |
|
146 |
4274 |
UINT crc_cal = (*crc); |
|
147 |
|||
148 |
✓✓ | 15393491 |
for (n = 0; n < len; n++) |
149 |
{ |
||
150 |
15389217 |
crc_cal = png -> gx_png_crc_table[(crc_cal ^ buf[n]) & 0xff] ^ (crc_cal >> 8); |
|
151 |
} |
||
152 |
|||
153 |
4274 |
(*crc) = crc_cal ^ 0xffffffff; |
|
154 |
4274 |
} |
|
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 |
/**************************************************************************/ |
||
199 |
9786 |
static VOID _gx_image_reader_png_4bytes_read(GX_PNG *png, INT *value) |
|
200 |
{ |
||
201 |
INT get_value; |
||
202 |
|||
203 |
9786 |
get_value = (png -> gx_png_data[png -> gx_png_data_index] << 24); |
|
204 |
9786 |
png -> gx_png_data_index++; |
|
205 |
|||
206 |
9786 |
get_value |= (png -> gx_png_data[png -> gx_png_data_index] << 16); |
|
207 |
9786 |
png -> gx_png_data_index++; |
|
208 |
|||
209 |
9786 |
get_value |= (png -> gx_png_data[png -> gx_png_data_index] << 8); |
|
210 |
9786 |
png -> gx_png_data_index++; |
|
211 |
|||
212 |
9786 |
get_value |= png -> gx_png_data[png -> gx_png_data_index]; |
|
213 |
9786 |
png -> gx_png_data_index++; |
|
214 |
|||
215 |
9786 |
(*value) = get_value; |
|
216 |
9786 |
} |
|
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 |
/**************************************************************************/ |
||
259 |
4274 |
static VOID _gx_image_reader_png_chunk_type_read(GX_PNG *png, CHAR *chunk_type) |
|
260 |
{ |
||
261 |
4274 |
chunk_type[0] = (CHAR)png -> gx_png_data[png -> gx_png_data_index++]; |
|
262 |
4274 |
chunk_type[1] = (CHAR)png -> gx_png_data[png -> gx_png_data_index++]; |
|
263 |
4274 |
chunk_type[2] = (CHAR)png -> gx_png_data[png -> gx_png_data_index++]; |
|
264 |
4274 |
chunk_type[3] = (CHAR)png -> gx_png_data[png -> gx_png_data_index++]; |
|
265 |
4274 |
} |
|
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 |
/**************************************************************************/ |
||
316 |
19950045 |
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 |
19950045 |
INT index = png -> gx_png_trunk_end_index; |
|
322 |
|||
323 |
✓✓ | 35070328 |
while (_bit_count < num_of_bits) |
324 |
{ |
||
325 |
✓✓ | 15120296 |
if (png -> gx_png_data_index >= png -> gx_png_data_size) |
326 |
{ |
||
327 |
1 |
return GX_FAILURE; |
|
328 |
} |
||
329 |
|||
330 |
15120295 |
get_byte = png -> gx_png_data[png -> gx_png_data_index++]; |
|
331 |
|||
332 |
15120295 |
_bit_buffer |= (UINT)(get_byte << (UINT)_bit_count); |
|
333 |
15120295 |
_bit_count += 8; |
|
334 |
|||
335 |
✓✓ | 15120295 |
if (png -> gx_png_data_index >= index) |
336 |
{ |
||
337 |
/* data_len*/ |
||
338 |
700 |
_gx_image_reader_png_4bytes_read(png, &checksum); |
|
339 |
|||
340 |
✓✓ | 700 |
if (png -> gx_png_trunk_crc != (UINT)checksum) |
341 |
{ |
||
342 |
12 |
return GX_FAILURE; |
|
343 |
} |
||
344 |
|||
345 |
688 |
_gx_image_reader_png_4bytes_read(png, &index); |
|
346 |
|||
347 |
688 |
png -> gx_png_trunk_crc = 0xffffffff; |
|
348 |
|||
349 |
688 |
_gx_image_reader_png_crc_get(png, &png -> gx_png_trunk_crc, (UINT)(4 + index)); |
|
350 |
|||
351 |
688 |
_gx_image_reader_png_chunk_type_read(png, chunk_type); |
|
352 |
|||
353 |
✓✓ | 688 |
if (strncmp(chunk_type, "IDAT", 4) == 0) |
354 |
{ |
||
355 |
687 |
index += png -> gx_png_data_index; |
|
356 |
687 |
png -> gx_png_trunk_end_index = index; |
|
357 |
} |
||
358 |
} |
||
359 |
} |
||
360 |
|||
361 |
19950032 |
(*return_value) = _bit_buffer; |
|
362 |
|||
363 |
19950032 |
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 |
/**************************************************************************/ |
||
408 |
43287405 |
static void _gx_image_reader_png_bits_revert(UINT *bits, UINT bits_len) |
|
409 |
{ |
||
410 |
43287405 |
UINT reverted = 0; |
|
411 |
UINT i; |
||
412 |
|||
413 |
✓✓ | 245522840 |
for (i = 0; i < bits_len; i++) |
414 |
{ |
||
415 |
202235435 |
reverted |= ((*bits) & 0x1) << (bits_len - i - 1); |
|
416 |
202235435 |
(*bits) >>= 1; |
|
417 |
} |
||
418 |
|||
419 |
43287405 |
(*bits) = reverted; |
|
420 |
43287405 |
} |
|
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 |
/**************************************************************************/ |
||
464 |
19950650 |
static VOID _gx_image_reader_png_bits_skip(UINT num_of_skip_bits) |
|
465 |
{ |
||
466 |
19950650 |
_bit_buffer >>= num_of_skip_bits; |
|
467 |
|||
468 |
19950650 |
_bit_count -= num_of_skip_bits; |
|
469 |
19950650 |
} |
|
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 |
/**************************************************************************/ |
||
515 |
661 |
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 |
✓✓ | 661 |
if (png -> gx_png_data_index + 13 > png -> gx_png_trunk_end_index) |
527 |
{ |
||
528 |
1 |
return GX_INVALID_SIZE; |
|
529 |
} |
||
530 |
|||
531 |
660 |
_gx_image_reader_png_4bytes_read(png, &png -> gx_png_width); |
|
532 |
660 |
_gx_image_reader_png_4bytes_read(png, &png -> gx_png_height); |
|
533 |
|||
534 |
/* Limited max png width to 14 bits. */ |
||
535 |
✓✓✓✓ |
660 |
if ((png -> gx_png_width < 0) || (png -> gx_png_width > GX_MAX_PIXELMAP_RESOLUTION)) |
536 |
{ |
||
537 |
2 |
return GX_INVALID_WIDTH; |
|
538 |
} |
||
539 |
|||
540 |
/* Limited max png height to 14 bits. */ |
||
541 |
✓✗✓✓ |
658 |
if ((png -> gx_png_height < 0) || (png -> gx_png_height > GX_MAX_PIXELMAP_RESOLUTION)) |
542 |
{ |
||
543 |
1 |
return GX_INVALID_HEIGHT; |
|
544 |
} |
||
545 |
|||
546 |
/* Bits per sample or per palette index, valid values are 1, 2 ,4, 8, 16. */ |
||
547 |
657 |
png -> gx_png_bit_depth = png -> gx_png_data[png -> gx_png_data_index++]; |
|
548 |
|||
549 |
✓✓ | 657 |
switch (png -> gx_png_bit_depth) |
550 |
{ |
||
551 |
656 |
case 1: |
|
552 |
case 2: |
||
553 |
case 4: |
||
554 |
case 8: |
||
555 |
case 16: |
||
556 |
656 |
break; |
|
557 |
|||
558 |
1 |
default: |
|
559 |
1 |
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 |
656 |
png -> gx_png_color_type = png -> gx_png_data[png -> gx_png_data_index++]; |
|
568 |
|||
569 |
✓✓✓✓ ✓ |
656 |
switch (png -> gx_png_color_type) |
570 |
{ |
||
571 |
147 |
case 0: |
|
572 |
/* Each pixel is agrayscale sample. */ |
||
573 |
case 3: |
||
574 |
/* Each pixel is a palette index, a PLTE chunk must appear. */ |
||
575 |
147 |
png -> gx_png_bpp = png -> gx_png_bit_depth; |
|
576 |
147 |
break; |
|
577 |
178 |
case 2: |
|
578 |
/* Each pixel is an RGB triple. */ |
||
579 |
178 |
png -> gx_png_bpp = (GX_UBYTE)(png -> gx_png_bit_depth * 3); |
|
580 |
178 |
break; |
|
581 |
|||
582 |
13 |
case 4: |
|
583 |
/* Each pixel is a grayscale sample, followed by an alpha sample. */ |
||
584 |
13 |
png -> gx_png_bpp = (GX_UBYTE)(png -> gx_png_bit_depth * 2); |
|
585 |
13 |
break; |
|
586 |
317 |
case 6: |
|
587 |
/* Each pixel is an R,G,B triple, followed by an alpha sample. */ |
||
588 |
317 |
png -> gx_png_bpp = (GX_UBYTE)(png -> gx_png_bit_depth * 4); |
|
589 |
317 |
break; |
|
590 |
|||
591 |
1 |
default: |
|
592 |
1 |
return GX_FAILURE; |
|
593 |
} |
||
594 |
|||
595 |
/* At present, only method 0 is defined. */ |
||
596 |
655 |
png -> gx_png_compression_method = png -> gx_png_data[png -> gx_png_data_index++]; |
|
597 |
|||
598 |
/* At present, only method 0 is defined. */ |
||
599 |
655 |
png -> gx_png_filter_method = png -> gx_png_data[png -> gx_png_data_index++]; |
|
600 |
|||
601 |
✓✓✓✓ |
655 |
if ((png -> gx_png_compression_method != 0) || (png -> gx_png_filter_method != 0)) |
602 |
{ |
||
603 |
/* Invalid value. */ |
||
604 |
2 |
return GX_FAILURE; |
|
605 |
} |
||
606 |
|||
607 |
/* 0 no interlace |
||
608 |
1 Adam7 interlace */ |
||
609 |
653 |
png -> gx_png_interlace_method = png -> gx_png_data[png -> gx_png_data_index++]; |
|
610 |
|||
611 |
653 |
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 |
/**************************************************************************/ |
||
660 |
14684099 |
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 |
14684099 |
UINT code_cal = 0; |
|
670 |
14684099 |
UINT code_index = 0; |
|
671 |
|||
672 |
✓✓ | 73050056 |
for (i_bit = 1; i_bit < 16; i_bit++) |
673 |
{ |
||
674 |
73050035 |
bit_count = huffman_bits_count[i_bit] - huffman_bits_count[i_bit - 1]; |
|
675 |
|||
676 |
✓✓ | 73050035 |
if (bit_count) |
677 |
{ |
||
678 |
43269969 |
code = (scan_buffer) << (32 - i_bit); |
|
679 |
43269969 |
code = (code) >> (32 - i_bit); |
|
680 |
|||
681 |
43269969 |
_gx_image_reader_png_bits_revert(&code, i_bit); |
|
682 |
|||
683 |
✓✓ | 43269969 |
if (code <= code_cal + bit_count - 1) |
684 |
{ |
||
685 |
14684078 |
*bit_len = i_bit; |
|
686 |
14684078 |
*code_value = (UINT)huffman_table[code_index + code - code_cal]; |
|
687 |
|||
688 |
14684078 |
return GX_SUCCESS; |
|
689 |
} |
||
690 |
else |
||
691 |
{ |
||
692 |
28585891 |
code_index += bit_count; |
|
693 |
28585891 |
code_cal += bit_count; |
|
694 |
} |
||
695 |
} |
||
696 |
|||
697 |
58365957 |
code_cal <<= 1; |
|
698 |
} |
||
699 |
|||
700 |
21 |
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 |
/**************************************************************************/ |
||
747 |
8151 |
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 |
✓✓ | 16781 |
for (i_bit = 7; i_bit <= 9; i_bit++) |
755 |
{ |
||
756 |
15646 |
code = scan_buffer << (32 - i_bit); |
|
757 |
15646 |
code = code >> (32 - i_bit); |
|
758 |
|||
759 |
15646 |
_gx_image_reader_png_bits_revert(&code, i_bit); |
|
760 |
|||
761 |
✓✓ | 15646 |
if (i_bit == 7) |
762 |
{ |
||
763 |
✓✓ | 8151 |
if (code <= 0x17) |
764 |
{ |
||
765 |
1791 |
*bit_len = 7; |
|
766 |
1791 |
*code_value = 256 + code; |
|
767 |
1791 |
break; |
|
768 |
} |
||
769 |
} |
||
770 |
✓✓ | 7495 |
else if (i_bit == 8) |
771 |
{ |
||
772 |
✓✓ | 6360 |
if (code <= 0xbf) |
773 |
{ |
||
774 |
/* code >= 0x30. */ |
||
775 |
5114 |
*bit_len = 8; |
|
776 |
5114 |
*code_value = code - 0x30; |
|
777 |
5114 |
break; |
|
778 |
} |
||
779 |
✓✓ | 1246 |
else if (code <= 0xc7) |
780 |
{ |
||
781 |
/* code >= 0xc0. */ |
||
782 |
111 |
*bit_len = 8; |
|
783 |
111 |
*code_value = 280 + code - 0xc0; |
|
784 |
111 |
break; |
|
785 |
} |
||
786 |
} |
||
787 |
else |
||
788 |
{ |
||
789 |
/* code >= 0x190 && code <= 0x1ff. */ |
||
790 |
1135 |
*bit_len = 9; |
|
791 |
1135 |
*code_value = 144 + code - 0x190; |
|
792 |
} |
||
793 |
} |
||
794 |
|||
795 |
8151 |
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 |
/**************************************************************************/ |
||
840 |
1018 |
static UINT _gx_image_reader_png_clen_huffman_read(GX_PNG *png, UINT hclen) |
|
841 |
{ |
||
842 |
|||
843 |
1018 |
INT code_value[19] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; |
|
844 |
1018 |
INT code_len[19] = {0}; |
|
845 |
UINT len; |
||
846 |
UINT i; |
||
847 |
INT pos[16]; |
||
848 |
|||
849 |
✓✓ | 17631 |
for (i = 0; i < hclen; i++) |
850 |
{ |
||
851 |
✓✓ | 16614 |
if (_gx_image_reader_png_bits_get(png, 3, &len) != GX_SUCCESS) |
852 |
{ |
||
853 |
1 |
return GX_FAILURE; |
|
854 |
} |
||
855 |
16613 |
_gx_image_reader_png_bits_skip(3); |
|
856 |
16613 |
len &= 0x7; |
|
857 |
|||
858 |
/* record code len for code len alphabet */ |
||
859 |
16613 |
code_len[code_value[i]] = (INT)len; |
|
860 |
|||
861 |
/* record codes number for every code len */ |
||
862 |
✓✓ | 16613 |
if (len) |
863 |
{ |
||
864 |
13493 |
png -> gx_png_huffman_clen_bits_count[len]++; |
|
865 |
} |
||
866 |
} |
||
867 |
|||
868 |
✓✓ | 16272 |
for (i = 1; i < 16; i++) |
869 |
{ |
||
870 |
15255 |
png -> gx_png_huffman_clen_bits_count[i] += png -> gx_png_huffman_clen_bits_count[i - 1]; |
|
871 |
} |
||
872 |
|||
873 |
1017 |
memset(pos, -1, 16 * sizeof(INT)); |
|
874 |
|||
875 |
✓✓ | 20340 |
for (i = 0; i < 19; i++) |
876 |
{ |
||
877 |
✓✓ | 19323 |
if (code_len[i]) |
878 |
{ |
||
879 |
✓✓ | 13492 |
if (pos[code_len[i]] == -1) |
880 |
{ |
||
881 |
4941 |
pos[code_len[i]] = png -> gx_png_huffman_clen_bits_count[code_len[i] - 1]; |
|
882 |
} |
||
883 |
13492 |
png -> gx_png_huffman_clen_table[pos[code_len[i]]++] = (INT)i; |
|
884 |
} |
||
885 |
} |
||
886 |
|||
887 |
1017 |
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 |
/**************************************************************************/ |
||
942 |
1017 |
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 |
1017 |
UINT count = 0; |
|
950 |
INT pos[16]; |
||
951 |
INT index; |
||
952 |
|||
953 |
1017 |
memset(png -> gx_png_huffman_lit_code_len, 0, sizeof(INT) * GX_PNG_HUFFMAN_LIT_CODE_LEN_TABLE_SIZE); |
|
954 |
1017 |
memset(png -> gx_png_huffman_dist_code_len, 0, sizeof(INT) * GX_PNG_HUFFMAN_DIST_CODE_LEN_TABLE_SIZE); |
|
955 |
|||
956 |
✓✓ | 238594 |
for (i = 0; i < hlit + hdist;) |
957 |
{ |
||
958 |
237583 |
count++; |
|
959 |
✓✓ | 237583 |
if (_gx_image_reader_png_bits_get(png, 16, &scan_buffer) != GX_SUCCESS) |
960 |
{ |
||
961 |
1 |
return GX_FAILURE; |
|
962 |
} |
||
963 |
|||
964 |
✓✓ | 237582 |
if (_gx_image_reader_png_dynamic_huffman_code_find(png -> gx_png_huffman_clen_table, |
965 |
237582 |
(UINT *)png -> gx_png_huffman_clen_bits_count, |
|
966 |
scan_buffer, |
||
967 |
&bit_len, |
||
968 |
&code_value) == 0) |
||
969 |
{ |
||
970 |
237578 |
_gx_image_reader_png_bits_skip(bit_len); |
|
971 |
|||
972 |
✓✓ | 237578 |
if (code_value <= 15) |
973 |
{ |
||
974 |
/* Represent code lengths of 0-15 */ |
||
975 |
✓✓ | 221291 |
if (i < hlit) |
976 |
{ |
||
977 |
202460 |
png -> gx_png_huffman_lit_code_len[i] = (INT)code_value; |
|
978 |
|||
979 |
202460 |
png -> gx_png_huffman_lit_bits_count[code_value]++; |
|
980 |
} |
||
981 |
else |
||
982 |
{ |
||
983 |
18831 |
png -> gx_png_huffman_dist_code_len[i - hlit] = (INT)code_value; |
|
984 |
18831 |
png -> gx_png_huffman_dist_bits_count[code_value]++; |
|
985 |
} |
||
986 |
|||
987 |
221291 |
i++; |
|
988 |
} |
||
989 |
else |
||
990 |
{ |
||
991 |
✓✓ | 16287 |
if (code_value == 16) |
992 |
{ |
||
993 |
/* repeat previous */ |
||
994 |
/* 2 bits repeat length*/ |
||
995 |
10127 |
_gx_image_reader_png_bits_get(png, 2, &repeat); |
|
996 |
10127 |
_gx_image_reader_png_bits_skip(2); |
|
997 |
10127 |
repeat &= 0x3; |
|
998 |
10127 |
repeat += 3; |
|
999 |
|||
1000 |
✓✓ | 10127 |
if (i < 1) |
1001 |
{ |
||
1002 |
1 |
return GX_FALSE; |
|
1003 |
} |
||
1004 |
✓✓ | 10126 |
else if ((i - 1) < hlit) |
1005 |
{ |
||
1006 |
8191 |
code_value = (UINT)png -> gx_png_huffman_lit_code_len[i - 1]; |
|
1007 |
} |
||
1008 |
else |
||
1009 |
{ |
||
1010 |
1935 |
code_value = (UINT)png -> gx_png_huffman_dist_code_len[i - 1 - hlit]; |
|
1011 |
} |
||
1012 |
|||
1013 |
✓✓ | 10126 |
if (i < hlit) |
1014 |
{ |
||
1015 |
8191 |
png -> gx_png_huffman_lit_bits_count[code_value] += (INT)repeat; |
|
1016 |
|||
1017 |
✓✓ | 41370 |
while (repeat--) |
1018 |
{ |
||
1019 |
33179 |
png -> gx_png_huffman_lit_code_len[i++] = (INT)code_value; |
|
1020 |
} |
||
1021 |
} |
||
1022 |
else |
||
1023 |
{ |
||
1024 |
1935 |
png -> gx_png_huffman_dist_bits_count[code_value] += (INT)repeat; |
|
1025 |
|||
1026 |
✓✓ | 9793 |
while (repeat--) |
1027 |
{ |
||
1028 |
7858 |
png -> gx_png_huffman_dist_code_len[i - hlit] = (INT)code_value; |
|
1029 |
7858 |
i++; |
|
1030 |
} |
||
1031 |
} |
||
1032 |
} |
||
1033 |
else |
||
1034 |
{ |
||
1035 |
✓✓ | 6160 |
if (code_value == 17) |
1036 |
{ |
||
1037 |
/* repeat 0 */ |
||
1038 |
/* 3 bits repeat length */ |
||
1039 |
5593 |
_gx_image_reader_png_bits_get(png, 3, &repeat); |
|
1040 |
5593 |
_gx_image_reader_png_bits_skip(3); |
|
1041 |
5593 |
repeat &= 0x7; |
|
1042 |
5593 |
repeat += 3; |
|
1043 |
} |
||
1044 |
else |
||
1045 |
{ |
||
1046 |
/* code_value = 18. */ |
||
1047 |
/* repeat 0*/ |
||
1048 |
/* 7 bits repeat length */ |
||
1049 |
567 |
_gx_image_reader_png_bits_get(png, 7, &repeat); |
|
1050 |
567 |
_gx_image_reader_png_bits_skip(7); |
|
1051 |
567 |
repeat &= 0x7f; |
|
1052 |
567 |
repeat += 11; |
|
1053 |
} |
||
1054 |
|||
1055 |
✓✓ | 6160 |
if (i < hlit) |
1056 |
{ |
||
1057 |
5972 |
memset(png -> gx_png_huffman_lit_code_len + i, 0, repeat * sizeof(INT)); |
|
1058 |
} |
||
1059 |
else |
||
1060 |
{ |
||
1061 |
188 |
memset(png -> gx_png_huffman_dist_code_len + i - hlit, 0, repeat * sizeof(INT)); |
|
1062 |
} |
||
1063 |
|||
1064 |
6160 |
i += repeat; |
|
1065 |
} |
||
1066 |
} |
||
1067 |
} |
||
1068 |
else |
||
1069 |
{ |
||
1070 |
/*error*/ |
||
1071 |
4 |
return GX_FAILURE; |
|
1072 |
} |
||
1073 |
} |
||
1074 |
|||
1075 |
1011 |
png -> gx_png_huffman_lit_bits_count[0] = 0; |
|
1076 |
1011 |
png -> gx_png_huffman_dist_bits_count[0] = 0; |
|
1077 |
|||
1078 |
✓✓ | 16176 |
for (i = 2; i <= 16; i++) |
1079 |
{ |
||
1080 |
15165 |
png -> gx_png_huffman_lit_bits_count[i] += png -> gx_png_huffman_lit_bits_count[i - 1]; |
|
1081 |
15165 |
png -> gx_png_huffman_dist_bits_count[i] += png -> gx_png_huffman_dist_bits_count[i - 1]; |
|
1082 |
} |
||
1083 |
|||
1084 |
1011 |
memset(pos, -1, 16 * sizeof(INT)); |
|
1085 |
|||
1086 |
✓✓ | 286378 |
for (i = 0; i < hlit; i++) |
1087 |
{ |
||
1088 |
285367 |
index = png -> gx_png_huffman_lit_code_len[i]; |
|
1089 |
✓✓ | 285367 |
if (index) |
1090 |
{ |
||
1091 |
✓✓ | 206147 |
if (pos[index] == -1) |
1092 |
{ |
||
1093 |
10074 |
pos[index] = png -> gx_png_huffman_lit_bits_count[index - 1]; |
|
1094 |
} |
||
1095 |
206147 |
png -> gx_png_huffman_lit_table[pos[index]++] = (INT)i; |
|
1096 |
} |
||
1097 |
} |
||
1098 |
|||
1099 |
1011 |
memset(pos, -1, 16 * sizeof(INT)); |
|
1100 |
|||
1101 |
✓✓ | 28582 |
for (i = 0; i < hdist; i++) |
1102 |
{ |
||
1103 |
27572 |
index = png -> gx_png_huffman_dist_code_len[i]; |
|
1104 |
✓✓ | 27572 |
if (index) |
1105 |
{ |
||
1106 |
✓✓ | 25320 |
if (pos[index] == -1) |
1107 |
{ |
||
1108 |
6642 |
pos[index] = png -> gx_png_huffman_dist_bits_count[index - 1]; |
|
1109 |
} |
||
1110 |
|||
1111 |
✓✓ | 25320 |
if (pos[index] >= GX_PNG_HUFFMAN_DIST_TABLE_SIZE) |
1112 |
{ |
||
1113 |
/* Invalid data. */ |
||
1114 |
1 |
return GX_FAILURE; |
|
1115 |
} |
||
1116 |
|||
1117 |
25319 |
png -> gx_png_huffman_dist_table[pos[index]++] = (INT)i; |
|
1118 |
} |
||
1119 |
} |
||
1120 |
|||
1121 |
1010 |
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 |
/**************************************************************************/ |
||
1176 |
1126 |
static UINT _gx_image_reader_png_huffcode_decode(GX_PNG *png, GX_BOOL dynamic, UINT decoded_data_size) |
|
1177 |
{ |
||
1178 |
UINT scan_buffer; |
||
1179 |
1126 |
UINT bit_len = 0; |
|
1180 |
1126 |
UINT code_value = 300; |
|
1181 |
UINT length; |
||
1182 |
UINT distance; |
||
1183 |
UINT extra_bits; |
||
1184 |
UINT copy_len; |
||
1185 |
|||
1186 |
while (1) |
||
1187 |
{ |
||
1188 |
✓✓ | 9600917 |
if (_gx_image_reader_png_bits_get(png, 16, &scan_buffer) != GX_SUCCESS) |
1189 |
{ |
||
1190 |
4 |
return GX_FAILURE; |
|
1191 |
} |
||
1192 |
|||
1193 |
/* Decode literal/length value from input stream */ |
||
1194 |
✓✓ | 9600913 |
if (dynamic) |
1195 |
{ |
||
1196 |
9592762 |
_gx_image_reader_png_dynamic_huffman_code_find(png -> gx_png_huffman_lit_table, |
|
1197 |
9592762 |
(UINT *)png -> gx_png_huffman_lit_bits_count, |
|
1198 |
scan_buffer, |
||
1199 |
&bit_len, |
||
1200 |
&code_value); |
||
1201 |
} |
||
1202 |
else |
||
1203 |
{ |
||
1204 |
8151 |
_gx_image_reader_png_fixed_ll_huffman_code_find(scan_buffer, &bit_len, &code_value); |
|
1205 |
} |
||
1206 |
|||
1207 |
9600913 |
_gx_image_reader_png_bits_skip(bit_len); |
|
1208 |
|||
1209 |
✓✓ | 9600913 |
if (code_value < 256) |
1210 |
{ |
||
1211 |
✓✓ | 4744250 |
if ((UINT)(png -> gx_png_decoded_data_len + 1) > decoded_data_size) |
1212 |
{ |
||
1213 |
/* Decoded data size exceed allocated buffer size. */ |
||
1214 |
1 |
return GX_FAILURE; |
|
1215 |
} |
||
1216 |
|||
1217 |
4744249 |
png -> gx_png_decoded_data[png -> gx_png_decoded_data_len++] = (GX_UBYTE)code_value; |
|
1218 |
} |
||
1219 |
✓✓ | 4856663 |
else if (code_value == 256) |
1220 |
{ |
||
1221 |
/* End of the block */ |
||
1222 |
1116 |
break; |
|
1223 |
} |
||
1224 |
else |
||
1225 |
{ |
||
1226 |
✓✓ | 4855547 |
if (code_value < 265) |
1227 |
{ |
||
1228 |
/* 0 extra bits */ |
||
1229 |
4349963 |
length = 3 + code_value - 257; |
|
1230 |
} |
||
1231 |
✓✓ | 505584 |
else if (code_value < 285) |
1232 |
{ |
||
1233 |
474693 |
extra_bits = 1 + (code_value - 265) / 4; |
|
1234 |
474693 |
_gx_image_reader_png_bits_get(png, extra_bits, &length); |
|
1235 |
474693 |
_gx_image_reader_png_bits_skip(extra_bits); |
|
1236 |
474693 |
length <<= (32 - extra_bits); |
|
1237 |
474693 |
length >>= (32 - extra_bits); |
|
1238 |
|||
1239 |
474693 |
length += 3u + (1u << (extra_bits + 2)) + ((1u << extra_bits) * ((code_value - 265) & 0x3)); |
|
1240 |
} |
||
1241 |
✓✓ | 30891 |
else if (code_value == 285) |
1242 |
{ |
||
1243 |
/* 0 extra bits */ |
||
1244 |
30889 |
length = 258; |
|
1245 |
} |
||
1246 |
else |
||
1247 |
{ |
||
1248 |
/* This should not happen. */ |
||
1249 |
2 |
return GX_FAILURE; |
|
1250 |
} |
||
1251 |
|||
1252 |
✓✓ | 4855545 |
if (dynamic) |
1253 |
{ |
||
1254 |
4853755 |
_gx_image_reader_png_bits_get(png, 16, &scan_buffer); |
|
1255 |
|||
1256 |
/*decode distance from input stream */ |
||
1257 |
4853755 |
_gx_image_reader_png_dynamic_huffman_code_find(png -> gx_png_huffman_dist_table, |
|
1258 |
4853755 |
(UINT *)png -> gx_png_huffman_dist_bits_count, |
|
1259 |
scan_buffer, |
||
1260 |
&bit_len, |
||
1261 |
&code_value); |
||
1262 |
|||
1263 |
4853755 |
_gx_image_reader_png_bits_skip(bit_len); |
|
1264 |
} |
||
1265 |
else |
||
1266 |
{ |
||
1267 |
/* Decodes 5-bits distance codes. */ |
||
1268 |
1790 |
_gx_image_reader_png_bits_get(png, 5, &scan_buffer); |
|
1269 |
1790 |
_gx_image_reader_png_bits_skip(5); |
|
1270 |
1790 |
code_value = scan_buffer & 0x1f; |
|
1271 |
1790 |
_gx_image_reader_png_bits_revert(&code_value, 5); |
|
1272 |
} |
||
1273 |
|||
1274 |
✓✓ | 4855545 |
if (code_value < 4) |
1275 |
{ |
||
1276 |
112633 |
distance = 1 + code_value; |
|
1277 |
} |
||
1278 |
✓✓ | 4742912 |
else if (code_value < 30) |
1279 |
{ |
||
1280 |
4742911 |
extra_bits = 1 + (code_value - 4) / 2; |
|
1281 |
|||
1282 |
4742911 |
_gx_image_reader_png_bits_get(png, extra_bits, &distance); |
|
1283 |
4742911 |
_gx_image_reader_png_bits_skip(extra_bits); |
|
1284 |
|||
1285 |
4742911 |
distance <<= (32 - extra_bits); |
|
1286 |
4742911 |
distance >>= (32 - extra_bits); |
|
1287 |
|||
1288 |
4742911 |
distance += 1u + (1u << (extra_bits + 1)) + (1u << extra_bits) * ((code_value - 4) & 0x1); |
|
1289 |
} |
||
1290 |
else |
||
1291 |
{ |
||
1292 |
/* This should not happen. */ |
||
1293 |
1 |
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 |
✓✓ | 14626075 |
while (length) |
1300 |
{ |
||
1301 |
✓✓ | 9770533 |
if (length > distance) |
1302 |
{ |
||
1303 |
4914989 |
copy_len = distance; |
|
1304 |
4914989 |
length -= distance; |
|
1305 |
} |
||
1306 |
else |
||
1307 |
{ |
||
1308 |
4855544 |
copy_len = length; |
|
1309 |
4855544 |
length = 0; |
|
1310 |
} |
||
1311 |
|||
1312 |
✓✓ | 9770533 |
if ((distance > (UINT)png -> gx_png_decoded_data_len) || |
1313 |
✓✓ | 9770532 |
((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 |
2 |
return GX_FAILURE; |
|
1318 |
} |
||
1319 |
|||
1320 |
9770531 |
memcpy(png -> gx_png_decoded_data + png -> gx_png_decoded_data_len, /* Use case of memcpy is verified. */ |
|
1321 |
9770531 |
png -> gx_png_decoded_data + png -> gx_png_decoded_data_len - distance, |
|
1322 |
copy_len * sizeof(GX_UBYTE)); |
||
1323 |
9770531 |
png -> gx_png_decoded_data_len += (INT)copy_len; |
|
1324 |
} |
||
1325 |
} |
||
1326 |
} |
||
1327 |
|||
1328 |
1116 |
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 |
/**************************************************************************/ |
||
1371 |
55 |
static UINT _gx_image_reader_png_tRNS_chunk_read(GX_PNG *png) |
|
1372 |
{ |
||
1373 |
INT index; |
||
1374 |
|||
1375 |
✓✓✓✓ |
55 |
if ((png -> gx_png_color_type == 4) || (png -> gx_png_color_type == 6)) |
1376 |
{ |
||
1377 |
/* tRNS is prohibited for the other color types. */ |
||
1378 |
2 |
return GX_FAILURE; |
|
1379 |
} |
||
1380 |
|||
1381 |
✓✓ | 53 |
if (png -> gx_png_color_type == 3) |
1382 |
{ |
||
1383 |
/* Contains a series of one-byte alpha values. */ |
||
1384 |
17 |
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 |
✓✓ | 17 |
if (png -> gx_png_trans_num > 256) |
1388 |
{ |
||
1389 |
1 |
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 |
36 |
png -> gx_png_trans_num = (png -> gx_png_trunk_end_index - png -> gx_png_data_index) >> 1; |
|
1397 |
|||
1398 |
✓✓ | 36 |
if (png -> gx_png_trans_num > 3) |
1399 |
{ |
||
1400 |
1 |
return GX_INVALID_VALUE; |
|
1401 |
} |
||
1402 |
} |
||
1403 |
|||
1404 |
/* Then trans num is no bigger than 256, multiplication will not overflow. */ |
||
1405 |
51 |
png -> gx_png_trans = (GX_COLOR *)_gx_system_memory_allocator((ULONG)png -> gx_png_trans_num * sizeof(GX_COLOR)); |
|
1406 |
|||
1407 |
✓✓ | 51 |
if (png -> gx_png_trans == GX_NULL) |
1408 |
{ |
||
1409 |
1 |
return GX_SYSTEM_MEMORY_ERROR; |
|
1410 |
} |
||
1411 |
|||
1412 |
✓✓ | 140 |
for (index = 0; index < png -> gx_png_trans_num; index++) |
1413 |
{ |
||
1414 |
90 |
png -> gx_png_trans[index] = png -> gx_png_data[png -> gx_png_data_index++]; |
|
1415 |
|||
1416 |
✓✓ | 90 |
if (png -> gx_png_color_type != 3) |
1417 |
{ |
||
1418 |
74 |
png -> gx_png_trans[index] <<= 8; |
|
1419 |
74 |
png -> gx_png_trans[index] |= png -> gx_png_data[png -> gx_png_data_index++]; |
|
1420 |
} |
||
1421 |
} |
||
1422 |
|||
1423 |
50 |
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 |
/**************************************************************************/ |
||
1474 |
644 |
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 |
✓✓ | 644 |
if (_gx_image_reader_png_bits_get(png, 8, &CMF) != GX_SUCCESS) |
1502 |
{ |
||
1503 |
2 |
return GX_FAILURE; |
|
1504 |
} |
||
1505 |
|||
1506 |
642 |
_gx_image_reader_png_bits_skip(8); |
|
1507 |
|||
1508 |
✓✓ | 642 |
if (_gx_image_reader_png_bits_get(png, 8, &FLG) != GX_SUCCESS) |
1509 |
{ |
||
1510 |
1 |
return GX_FAILURE; |
|
1511 |
} |
||
1512 |
|||
1513 |
641 |
_gx_image_reader_png_bits_skip(8); |
|
1514 |
|||
1515 |
641 |
compress_method = CMF & 0x0f; |
|
1516 |
641 |
window_size = 2 << (((CMF & 0xf0) >> 4) + 8); |
|
1517 |
641 |
fdict = FLG & 0x20; |
|
1518 |
|||
1519 |
✓✓✓✓ |
641 |
if ((fdict != 0) || |
1520 |
✓✓ | 639 |
(window_size > 65536) || |
1521 |
(compress_method != 8)) |
||
1522 |
{ |
||
1523 |
4 |
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 |
637 |
alloc_size = (UINT)(png -> gx_png_height * ((png -> gx_png_width * png -> gx_png_bpp + 7) / 8)); |
|
1529 |
637 |
alloc_size = alloc_size + (UINT)png -> gx_png_height; |
|
1530 |
637 |
png -> gx_png_decoded_data = (GX_UBYTE *)_gx_system_memory_allocator(alloc_size); |
|
1531 |
637 |
png -> gx_png_decoded_data_len = 0; |
|
1532 |
|||
1533 |
✓✓ | 637 |
if (png -> gx_png_decoded_data == GX_NULL) |
1534 |
{ |
||
1535 |
2 |
return GX_SYSTEM_MEMORY_ERROR; |
|
1536 |
} |
||
1537 |
|||
1538 |
do |
||
1539 |
{ |
||
1540 |
/* The header of one block */ |
||
1541 |
✓✓ | 1150 |
if (_gx_image_reader_png_bits_get(png, 8, &header) != GX_SUCCESS) |
1542 |
{ |
||
1543 |
1 |
return GX_FAILURE; |
|
1544 |
} |
||
1545 |
|||
1546 |
✓✓ | 1149 |
if ((header & 0x6) == 0x00) |
1547 |
{ |
||
1548 |
13 |
_gx_image_reader_png_bits_skip(3); |
|
1549 |
|||
1550 |
/* no compression */ |
||
1551 |
13 |
_gx_image_reader_png_bits_skip(_bit_count & 0x7); |
|
1552 |
✓✓ | 13 |
if (_bit_count) |
1553 |
{ |
||
1554 |
1 |
png -> gx_png_data_index -= (INT)(_bit_count / 8); |
|
1555 |
1 |
_gx_image_reader_png_bits_skip(_bit_count); |
|
1556 |
} |
||
1557 |
|||
1558 |
/* 4 = 2 bytes len + 2 bytes nlen. */ |
||
1559 |
✓✓ | 13 |
if (png -> gx_png_data_index + 4 > png -> gx_png_data_size) |
1560 |
{ |
||
1561 |
1 |
return GX_INVALID_SIZE; |
|
1562 |
} |
||
1563 |
|||
1564 |
/* Read "LEN". */ |
||
1565 |
12 |
len = png -> gx_png_data[png -> gx_png_data_index]; |
|
1566 |
12 |
png -> gx_png_data_index++; |
|
1567 |
12 |
len |= (png -> gx_png_data[png -> gx_png_data_index] << 8); |
|
1568 |
12 |
png -> gx_png_data_index++; |
|
1569 |
|||
1570 |
/* Read "NLEN". */ |
||
1571 |
12 |
nlen = png -> gx_png_data[png -> gx_png_data_index]; |
|
1572 |
12 |
png -> gx_png_data_index++; |
|
1573 |
12 |
nlen |= (png -> gx_png_data[png -> gx_png_data_index] << 8); |
|
1574 |
12 |
png -> gx_png_data_index++; |
|
1575 |
|||
1576 |
✓✓ | 12 |
if (len + nlen != 65535) |
1577 |
{ |
||
1578 |
/* NLEN is not one's complement of LEN. */ |
||
1579 |
4 |
return GX_FAILURE; |
|
1580 |
} |
||
1581 |
|||
1582 |
/* Read data to outbuffer directly */ |
||
1583 |
✓✓ | 8 |
if (len) |
1584 |
{ |
||
1585 |
✓✓ | 7 |
if ((UINT)(png -> gx_png_decoded_data_len + len) > alloc_size) |
1586 |
{ |
||
1587 |
/* Copied size exceed remaining buffer size. */ |
||
1588 |
1 |
return GX_FAILURE; |
|
1589 |
} |
||
1590 |
|||
1591 |
✓✓ | 6 |
if (png -> gx_png_data_index + len > png -> gx_png_data_size) |
1592 |
{ |
||
1593 |
1 |
return GX_INVALID_SIZE; |
|
1594 |
} |
||
1595 |
|||
1596 |
5 |
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 |
5 |
png -> gx_png_data_index += len; |
|
1598 |
5 |
png -> gx_png_decoded_data_len += len; |
|
1599 |
} |
||
1600 |
} |
||
1601 |
✓✓ | 1136 |
else if ((header & 0x6) == 0x2) |
1602 |
{ |
||
1603 |
115 |
_gx_image_reader_png_bits_skip(3); |
|
1604 |
|||
1605 |
/* compressed with fixed Huffman codes */ |
||
1606 |
✓✓ | 115 |
if (_gx_image_reader_png_huffcode_decode(png, GX_FALSE, alloc_size) != GX_SUCCESS) |
1607 |
{ |
||
1608 |
3 |
return GX_FAILURE; |
|
1609 |
} |
||
1610 |
} |
||
1611 |
✓✓ | 1021 |
else if ((header & 0x6) == 0x4) |
1612 |
{ |
||
1613 |
/* compressed with dynamic Huffman codes */ |
||
1614 |
1020 |
_gx_image_reader_png_bits_skip(3); |
|
1615 |
|||
1616 |
/* # of Literal/Length codes */ |
||
1617 |
1020 |
_gx_image_reader_png_bits_get(png, 5, (unsigned int *)&hlit); |
|
1618 |
|||
1619 |
1020 |
_gx_image_reader_png_bits_skip(5); |
|
1620 |
1020 |
hlit = (hlit & 0x1f) + 257; |
|
1621 |
|||
1622 |
/* # of Distance codes */ |
||
1623 |
✓✓ | 1020 |
if (_gx_image_reader_png_bits_get(png, 5, (unsigned int *)&hdist) != GX_SUCCESS) |
1624 |
{ |
||
1625 |
1 |
return GX_FAILURE; |
|
1626 |
} |
||
1627 |
1019 |
_gx_image_reader_png_bits_skip(5); |
|
1628 |
1019 |
hdist = (hdist & 0x1f) + 1; |
|
1629 |
|||
1630 |
/* # of Code Length codes */ |
||
1631 |
✓✓ | 1019 |
if (_gx_image_reader_png_bits_get(png, 4, (unsigned int *)&hclen) != GX_SUCCESS) |
1632 |
{ |
||
1633 |
1 |
return GX_FAILURE; |
|
1634 |
} |
||
1635 |
1018 |
_gx_image_reader_png_bits_skip(4); |
|
1636 |
1018 |
hclen = (hclen & 0xf) + 4; |
|
1637 |
|||
1638 |
1018 |
memset(png -> gx_png_huffman_clen_bits_count, 0, 17 * sizeof(INT)); |
|
1639 |
1018 |
memset(png -> gx_png_huffman_clen_table, 0, 20 * sizeof(INT)); |
|
1640 |
1018 |
memset(png -> gx_png_huffman_lit_bits_count, 0, 17 * sizeof(INT)); |
|
1641 |
1018 |
memset(png -> gx_png_huffman_lit_table, 0, GX_PNG_HUFFMAN_LIT_TABLE_SIZE * sizeof(int)); |
|
1642 |
1018 |
memset(png -> gx_png_huffman_dist_bits_count, 0, 17 * sizeof(INT)); |
|
1643 |
1018 |
memset(png -> gx_png_huffman_dist_table, 0, 30 * sizeof(INT)); |
|
1644 |
|||
1645 |
✓✓ | 1018 |
if (_gx_image_reader_png_clen_huffman_read(png, (UINT)hclen) != GX_SUCCESS) |
1646 |
{ |
||
1647 |
1 |
return GX_FAILURE; |
|
1648 |
} |
||
1649 |
|||
1650 |
✓✓ | 1017 |
if (_gx_image_reader_png_ll_huffman_read(png, (UINT)hlit, (UINT)hdist) != GX_SUCCESS) |
1651 |
{ |
||
1652 |
6 |
return GX_FAILURE; |
|
1653 |
} |
||
1654 |
|||
1655 |
✓✓ | 1011 |
if (_gx_image_reader_png_huffcode_decode(png, GX_TRUE, alloc_size) != GX_SUCCESS) |
1656 |
{ |
||
1657 |
6 |
return GX_FAILURE; |
|
1658 |
} |
||
1659 |
} |
||
1660 |
else |
||
1661 |
{ |
||
1662 |
/* error */ |
||
1663 |
1 |
return GX_FAILURE; |
|
1664 |
} |
||
1665 |
✓✓ | 1123 |
} while ((header & 0x1) != 0x1); |
1666 |
|||
1667 |
/* Skip checksum */ |
||
1668 |
608 |
png -> gx_png_data_index = png -> gx_png_trunk_end_index; |
|
1669 |
608 |
_gx_image_reader_png_bits_skip(_bit_count); |
|
1670 |
|||
1671 |
✓✓ | 608 |
if (alloc_size != (UINT)png -> gx_png_decoded_data_len) |
1672 |
{ |
||
1673 |
/* Decoded data size doesn't match prediction. */ |
||
1674 |
4 |
return GX_FAILURE; |
|
1675 |
} |
||
1676 |
|||
1677 |
604 |
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 |
/**************************************************************************/ |
||
1721 |
565 |
static UINT _gx_image_reader_png_gAMA_chunk_read(GX_PNG *png) |
|
1722 |
{ |
||
1723 |
✓✓ | 565 |
if (png -> gx_png_data_index + 4 > png -> gx_png_trunk_end_index) |
1724 |
{ |
||
1725 |
1 |
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 |
564 |
_gx_image_reader_png_4bytes_read(png, &png -> gx_png_gamma); |
|
1732 |
|||
1733 |
564 |
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 |
/**************************************************************************/ |
||
1775 |
66 |
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 |
66 |
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 |
✓✓ | 66 |
if (png -> gx_png_palette_table_size > 256) |
1786 |
{ |
||
1787 |
1 |
return GX_INVALID_VALUE; |
|
1788 |
} |
||
1789 |
|||
1790 |
✓✓ | 8862 |
for (index = 0; index < png -> gx_png_palette_table_size; index++) |
1791 |
{ |
||
1792 |
8797 |
red = png -> gx_png_data[png -> gx_png_data_index++]; |
|
1793 |
8797 |
green = png -> gx_png_data[png -> gx_png_data_index++]; |
|
1794 |
8797 |
blue = png -> gx_png_data[png -> gx_png_data_index++]; |
|
1795 |
|||
1796 |
8797 |
png -> gx_png_palette_table[index] = (GX_COLOR)((red << 16) | (green << 8) | blue); |
|
1797 |
} |
||
1798 |
|||
1799 |
65 |
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 |
/**************************************************************************/ |
||
1846 |
17536220 |
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 |
17536220 |
p = a + b - c; |
|
1852 |
17536220 |
pa = GX_ABS(p - a); |
|
1853 |
17536220 |
pb = GX_ABS(p - b); |
|
1854 |
17536220 |
pc = GX_ABS(p - c); |
|
1855 |
|||
1856 |
/*return nearest of a, b, c */ |
||
1857 |
|||
1858 |
✓✓✓✓ |
17536220 |
if ((pa <= pb) && (pa <= pc)) |
1859 |
{ |
||
1860 |
12176556 |
return a; |
|
1861 |
} |
||
1862 |
✓✓ | 5359664 |
else if (pb <= pc) |
1863 |
{ |
||
1864 |
4272738 |
return b; |
|
1865 |
} |
||
1866 |
else |
||
1867 |
{ |
||
1868 |
1086926 |
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 |
/**************************************************************************/ |
||
1915 |
605 |
static UINT _gx_image_reader_png_unfilter(GX_PNG *png) |
|
1916 |
{ |
||
1917 |
INT filter_type; |
||
1918 |
INT byte_width; |
||
1919 |
INT pos; |
||
1920 |
605 |
INT bpp = png -> gx_png_bpp; |
|
1921 |
INT x; |
||
1922 |
INT y; |
||
1923 |
|||
1924 |
✓✓ | 605 |
if (png -> gx_png_decoded_data == GX_NULL) |
1925 |
{ |
||
1926 |
/* This happens when IDAT chunk is missing. */ |
||
1927 |
1 |
return GX_FAILURE; |
|
1928 |
} |
||
1929 |
|||
1930 |
604 |
byte_width = (png -> gx_png_width * bpp + 7) >> 3; |
|
1931 |
604 |
bpp = (bpp + 7) >> 3; |
|
1932 |
|||
1933 |
✓✓ | 76766 |
for (y = 0; y < png -> gx_png_height; y++) |
1934 |
{ |
||
1935 |
76164 |
filter_type = png -> gx_png_decoded_data[y * byte_width + y]; |
|
1936 |
|||
1937 |
76164 |
pos = y * byte_width; |
|
1938 |
76164 |
memmove(png -> gx_png_decoded_data + pos, png -> gx_png_decoded_data + pos + y + 1, (UINT)byte_width); |
|
1939 |
|||
1940 |
✓✓✓✓ ✓✓ |
76164 |
switch (filter_type) |
1941 |
{ |
||
1942 |
2595 |
case 0: |
|
1943 |
2595 |
break; |
|
1944 |
19998 |
case 1: |
|
1945 |
/* sub(x) + raw(x-bpp)*/ |
||
1946 |
✓✓ | 15937009 |
for (x = bpp; x < byte_width; x++) |
1947 |
{ |
||
1948 |
15917011 |
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 |
19998 |
break; |
|
1951 |
26536 |
case 2: |
|
1952 |
/*up(x) + prior(x)*/ |
||
1953 |
✓✓ | 26536 |
if (y == 0) |
1954 |
{ |
||
1955 |
4 |
break; |
|
1956 |
} |
||
1957 |
|||
1958 |
✓✓ | 20764736 |
for (x = 0; x < byte_width; x++) |
1959 |
{ |
||
1960 |
20738204 |
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 |
26532 |
break; |
|
1963 |
1090 |
case 3: |
|
1964 |
/* average(x) + floor((raw(x-bpp)+prior(x))/2 */ |
||
1965 |
✓✓ | 1090 |
if (y == 0) |
1966 |
{ |
||
1967 |
✓✓ | 376 |
for (x = bpp; x < byte_width; x++) |
1968 |
{ |
||
1969 |
372 |
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 |
✓✓ | 4813 |
for (x = 0; x < bpp; x++) |
1975 |
{ |
||
1976 |
3727 |
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 |
✓✓ | 830655 |
for (x = bpp; x < byte_width; x++) |
1980 |
{ |
||
1981 |
829569 |
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 |
829569 |
png -> gx_png_decoded_data[pos + x - byte_width]) >> 1)); |
|
1983 |
} |
||
1984 |
} |
||
1985 |
1090 |
break; |
|
1986 |
25943 |
case 4: |
|
1987 |
/* paeth(x) + paethpredictor(raw(x-bpp), prior(x), prior(x-bpp)) */ |
||
1988 |
✓✓ | 25943 |
if (y == 0) |
1989 |
{ |
||
1990 |
✓✓ | 376 |
for (x = bpp; x < byte_width; x++) |
1991 |
{ |
||
1992 |
372 |
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 |
✓✓ | 128535 |
for (x = 0; x < bpp; x++) |
1998 |
{ |
||
1999 |
102596 |
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 |
✓✓ | 17562159 |
for (x = bpp; x < byte_width; x++) |
2003 |
{ |
||
2004 |
17536220 |
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 |
17536220 |
png -> gx_png_decoded_data[pos + x - byte_width], |
|
2006 |
17536220 |
png -> gx_png_decoded_data[pos + x - byte_width - bpp])); |
|
2007 |
} |
||
2008 |
} |
||
2009 |
25943 |
break; |
|
2010 |
2 |
default: |
|
2011 |
2 |
return GX_FAILURE; |
|
2012 |
} |
||
2013 |
} |
||
2014 |
|||
2015 |
602 |
png -> gx_png_decoded_data_len -= png -> gx_png_height; |
|
2016 |
|||
2017 |
602 |
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 |
/**************************************************************************/ |
||
2085 |
677 |
UINT _gx_image_reader_png_decode(GX_CONST GX_UBYTE *read_data, ULONG data_size, GX_PIXELMAP *outmap) |
|
2086 |
{ |
||
2087 |
677 |
UINT status = GX_SUCCESS; |
|
2088 |
GX_PNG png; |
||
2089 |
INT data_len; |
||
2090 |
CHAR chunk_type[4]; |
||
2091 |
INT checksum; |
||
2092 |
677 |
GX_BOOL idat_done = GX_FALSE; |
|
2093 |
INT *scratch_buffer; |
||
2094 |
677 |
INT scratch_index = 0; |
|
2095 |
677 |
GX_BOOL decoded_done = GX_FALSE; |
|
2096 |
|||
2097 |
✓✓ | 677 |
if (data_size < 8) |
2098 |
{ |
||
2099 |
1 |
return GX_INVALID_SIZE; |
|
2100 |
} |
||
2101 |
|||
2102 |
✓✓ | 676 |
if ((read_data[0] == 137) && |
2103 |
✓✓ | 675 |
(read_data[1] == 80) && |
2104 |
✓✓ | 674 |
(read_data[2] == 78) && |
2105 |
✓✓ | 673 |
(read_data[3] == 71) && |
2106 |
✓✓ | 672 |
(read_data[4] == 13) && |
2107 |
✓✓ | 671 |
(read_data[5] == 10) && |
2108 |
✓✓ | 670 |
(read_data[6] == 26) && |
2109 |
✓✓ | 669 |
(read_data[7] == 10)) |
2110 |
{ |
||
2111 |
✓✓ | 668 |
if (!_gx_system_memory_allocator) |
2112 |
{ |
||
2113 |
1 |
return GX_SYSTEM_MEMORY_ERROR; |
|
2114 |
} |
||
2115 |
|||
2116 |
667 |
memset(&png, 0, sizeof(GX_PNG)); |
|
2117 |
667 |
scratch_buffer = (INT *)_gx_system_memory_allocator(GX_PNG_SCRATCH_BUFFER_SIZE * sizeof(ULONG)); |
|
2118 |
|||
2119 |
✓✓ | 667 |
if (scratch_buffer == GX_NULL) |
2120 |
{ |
||
2121 |
1 |
return GX_SYSTEM_MEMORY_ERROR; |
|
2122 |
} |
||
2123 |
|||
2124 |
666 |
png.gx_png_crc_table = (UINT *)scratch_buffer; |
|
2125 |
666 |
scratch_index += GX_PNG_CRC_TABLE_SIZE; |
|
2126 |
666 |
png.gx_png_huffman_lit_table = scratch_buffer + scratch_index; |
|
2127 |
666 |
scratch_index += GX_PNG_HUFFMAN_LIT_TABLE_SIZE; |
|
2128 |
666 |
png.gx_png_huffman_lit_code_len = scratch_buffer + scratch_index; |
|
2129 |
666 |
scratch_index += GX_PNG_HUFFMAN_LIT_CODE_LEN_TABLE_SIZE; |
|
2130 |
666 |
png.gx_png_huffman_dist_code_len = scratch_buffer + scratch_index; |
|
2131 |
666 |
scratch_index += GX_PNG_HUFFMAN_DIST_CODE_LEN_TABLE_SIZE; |
|
2132 |
666 |
png.gx_png_palette_table = (GX_COLOR *)scratch_buffer + scratch_index; |
|
2133 |
|||
2134 |
666 |
png.gx_png_data = (GX_UBYTE *)read_data; |
|
2135 |
666 |
png.gx_png_data_size = (INT)data_size; |
|
2136 |
666 |
png.gx_png_data_index = 8; |
|
2137 |
|||
2138 |
666 |
_gx_image_reader_png_crc_table_make(&png); |
|
2139 |
|||
2140 |
666 |
_bit_buffer = 0; |
|
2141 |
666 |
_bit_count = 0; |
|
2142 |
|||
2143 |
✓✓ | 3589 |
while (png.gx_png_data_index < png.gx_png_data_size - 4) |
2144 |
{ |
||
2145 |
/* data_len*/ |
||
2146 |
3588 |
_gx_image_reader_png_4bytes_read(&png, &data_len); |
|
2147 |
|||
2148 |
3588 |
png.gx_png_trunk_crc = 0xffffffff; |
|
2149 |
|||
2150 |
✓✓ | 3588 |
if ((data_len < 0) || |
2151 |
✓✓ | 3587 |
(data_len > png.gx_png_data_size - png.gx_png_data_index - 4)) |
2152 |
{ |
||
2153 |
2 |
status = GX_INVALID_SIZE; |
|
2154 |
2 |
break; |
|
2155 |
} |
||
2156 |
|||
2157 |
/* Calculate checksum of the chunk data. */ |
||
2158 |
3586 |
_gx_image_reader_png_crc_get(&png, &png.gx_png_trunk_crc, (UINT)(4 + data_len)); |
|
2159 |
|||
2160 |
/* Read chunk type. */ |
||
2161 |
3586 |
_gx_image_reader_png_chunk_type_read(&png, chunk_type); |
|
2162 |
|||
2163 |
3586 |
png.gx_png_trunk_end_index = png.gx_png_data_index + data_len; |
|
2164 |
|||
2165 |
✓✓✓✓ |
3586 |
if ((strncmp(chunk_type, "IDAT", 4) == 0) && (!idat_done)) |
2166 |
{ |
||
2167 |
644 |
idat_done = GX_TRUE; |
|
2168 |
|||
2169 |
644 |
status = _gx_image_reader_png_IDAT_chunk_read(&png); |
|
2170 |
} |
||
2171 |
✓✓ | 2942 |
else if (strncmp(chunk_type, "IHDR", 4) == 0) |
2172 |
{ |
||
2173 |
661 |
status = _gx_image_reader_png_IHDR_chunk_read(&png); |
|
2174 |
} |
||
2175 |
✓✓ | 2281 |
else if (strncmp(chunk_type, "gAMA", 4) == 0) |
2176 |
{ |
||
2177 |
565 |
status = _gx_image_reader_png_gAMA_chunk_read(&png); |
|
2178 |
} |
||
2179 |
✓✓ | 1716 |
else if (strncmp(chunk_type, "PLTE", 4) == 0) |
2180 |
{ |
||
2181 |
66 |
status = _gx_image_reader_png_PLTE_chunk_read(&png); |
|
2182 |
} |
||
2183 |
✓✓✓✓ |
1650 |
else if ((strncmp(chunk_type, "tRNS", 4) == 0) && (png.gx_png_trans == GX_NULL)) |
2184 |
{ |
||
2185 |
/* Read transparent information. */ |
||
2186 |
55 |
status = _gx_image_reader_png_tRNS_chunk_read(&png); |
|
2187 |
} |
||
2188 |
✓✓ | 1595 |
else if (strncmp(chunk_type, "IEND", 4) == GX_SUCCESS) |
2189 |
{ |
||
2190 |
/* End */ |
||
2191 |
605 |
decoded_done = GX_TRUE; |
|
2192 |
605 |
break; |
|
2193 |
} |
||
2194 |
else |
||
2195 |
{ |
||
2196 |
/* Ignore chunk */ |
||
2197 |
990 |
png.gx_png_data_index += data_len; |
|
2198 |
} |
||
2199 |
|||
2200 |
✓✓ | 2981 |
if (status != GX_SUCCESS) |
2201 |
{ |
||
2202 |
55 |
break; |
|
2203 |
} |
||
2204 |
|||
2205 |
2926 |
_gx_image_reader_png_4bytes_read(&png, &checksum); |
|
2206 |
|||
2207 |
✓✓ | 2926 |
if (checksum != (INT)png.gx_png_trunk_crc) |
2208 |
{ |
||
2209 |
3 |
status = GX_FAILURE; |
|
2210 |
3 |
break; |
|
2211 |
} |
||
2212 |
} |
||
2213 |
|||
2214 |
✓✓✓✓ |
666 |
if(status == GX_SUCCESS && (!decoded_done)) |
2215 |
{ |
||
2216 |
1 |
status = GX_FAILURE; |
|
2217 |
} |
||
2218 |
|||
2219 |
✓✓ | 666 |
if (status == GX_SUCCESS) |
2220 |
{ |
||
2221 |
/* revert filter */ |
||
2222 |
605 |
status = _gx_image_reader_png_unfilter(&png); |
|
2223 |
} |
||
2224 |
|||
2225 |
✓✓ | 666 |
if (status == GX_SUCCESS) |
2226 |
{ |
||
2227 |
602 |
outmap -> gx_pixelmap_data = png.gx_png_decoded_data; |
|
2228 |
602 |
outmap -> gx_pixelmap_data_size = (ULONG)png.gx_png_decoded_data_len; |
|
2229 |
602 |
outmap -> gx_pixelmap_width = (GX_VALUE)png.gx_png_width; |
|
2230 |
602 |
outmap -> gx_pixelmap_height = (GX_VALUE)png.gx_png_height; |
|
2231 |
602 |
outmap -> gx_pixelmap_flags = GX_PIXELMAP_RAW_FORMAT; |
|
2232 |
|||
2233 |
✓✓ | 602 |
if (png.gx_png_trans_num) |
2234 |
{ |
||
2235 |
49 |
outmap -> gx_pixelmap_flags |= GX_PIXELMAP_ALPHA; |
|
2236 |
49 |
outmap -> gx_pixelmap_transparent_color = (ULONG)png.gx_png_trans; |
|
2237 |
} |
||
2238 |
|||
2239 |
✓✓✓✓ ✓ |
602 |
switch (png.gx_png_color_type) |
2240 |
{ |
||
2241 |
312 |
case 6: |
|
2242 |
/* Each pixel is an RGB triple, followed by an alpha sample. */ |
||
2243 |
✓✓ | 312 |
if (png.gx_png_bit_depth == 8) |
2244 |
{ |
||
2245 |
308 |
outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_32BPP; |
|
2246 |
} |
||
2247 |
else |
||
2248 |
{ |
||
2249 |
/* Bit depth = 16. */ |
||
2250 |
4 |
outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_64BPP; |
|
2251 |
} |
||
2252 |
312 |
outmap -> gx_pixelmap_flags |= GX_PIXELMAP_ALPHA; |
|
2253 |
312 |
break; |
|
2254 |
12 |
case 4: |
|
2255 |
/* Each pixel is a grayscale sample followed by an alpha sample. */ |
||
2256 |
✓✓ | 12 |
if (png.gx_png_bit_depth == 8) |
2257 |
{ |
||
2258 |
8 |
outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_16BPP_GRAY_ALPHA; |
|
2259 |
} |
||
2260 |
else |
||
2261 |
{ |
||
2262 |
/* Bit depth = 16. */ |
||
2263 |
4 |
outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_32BPP_GRAY_ALPHA; |
|
2264 |
} |
||
2265 |
12 |
outmap -> gx_pixelmap_flags |= GX_PIXELMAP_ALPHA; |
|
2266 |
12 |
break; |
|
2267 |
53 |
case 3: |
|
2268 |
/* Each pixel is a palette index */ |
||
2269 |
✓✓✓✓ |
53 |
switch (png.gx_png_bit_depth) |
2270 |
{ |
||
2271 |
6 |
case 1: |
|
2272 |
6 |
outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_1BPP; |
|
2273 |
6 |
break; |
|
2274 |
6 |
case 2: |
|
2275 |
6 |
outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_2BPP; |
|
2276 |
6 |
break; |
|
2277 |
10 |
case 4: |
|
2278 |
10 |
outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_4BPP; |
|
2279 |
10 |
break; |
|
2280 |
31 |
default: |
|
2281 |
/* Bit depth = 8. */ |
||
2282 |
31 |
outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_8BPP; |
|
2283 |
31 |
break; |
|
2284 |
} |
||
2285 |
|||
2286 |
/* Palette table size is no bigger than 256, aux data size will not overflow. */ |
||
2287 |
53 |
outmap -> gx_pixelmap_aux_data_size = (ULONG)(png.gx_png_palette_table_size) * sizeof(GX_COLOR); |
|
2288 |
53 |
outmap -> gx_pixelmap_aux_data = (GX_UBYTE *)_gx_system_memory_allocator(outmap -> gx_pixelmap_aux_data_size); |
|
2289 |
|||
2290 |
✓✓ | 53 |
if (!outmap -> gx_pixelmap_aux_data) |
2291 |
{ |
||
2292 |
1 |
return GX_SYSTEM_MEMORY_ERROR; |
|
2293 |
} |
||
2294 |
|||
2295 |
52 |
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 |
52 |
break; |
|
2297 |
172 |
case 2: |
|
2298 |
/* Each pixel is an RGB triple. */ |
||
2299 |
✓✓ | 172 |
if (png.gx_png_bit_depth == 8) |
2300 |
{ |
||
2301 |
138 |
outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_24BPP; |
|
2302 |
} |
||
2303 |
else |
||
2304 |
{ |
||
2305 |
/* Bit depth = 16. */ |
||
2306 |
34 |
outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_48BPP; |
|
2307 |
} |
||
2308 |
172 |
break; |
|
2309 |
53 |
default: |
|
2310 |
/* Each pixel is a grayscale sample. */ |
||
2311 |
✓✓✓✓ ✓ |
53 |
switch (png.gx_png_bit_depth) |
2312 |
{ |
||
2313 |
16 |
case 16: |
|
2314 |
16 |
outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_16BPP_GRAY; |
|
2315 |
16 |
break; |
|
2316 |
16 |
case 8: |
|
2317 |
16 |
outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_8BPP; |
|
2318 |
16 |
break; |
|
2319 |
8 |
case 4: |
|
2320 |
8 |
outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_4BPP; |
|
2321 |
8 |
break; |
|
2322 |
6 |
case 2: |
|
2323 |
6 |
outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_2BPP; |
|
2324 |
6 |
break; |
|
2325 |
7 |
default: |
|
2326 |
/* Bit depth = 1. */ |
||
2327 |
7 |
outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_1BPP; |
|
2328 |
7 |
break; |
|
2329 |
} |
||
2330 |
53 |
break; |
|
2331 |
} |
||
2332 |
} |
||
2333 |
|||
2334 |
✓✓ | 665 |
if (status != GX_SUCCESS) |
2335 |
{ |
||
2336 |
✓✓ | 64 |
if (png.gx_png_decoded_data) |
2337 |
{ |
||
2338 |
33 |
_gx_system_memory_free(png.gx_png_decoded_data); |
|
2339 |
} |
||
2340 |
|||
2341 |
✓✓ | 64 |
if (png.gx_png_trans) |
2342 |
{ |
||
2343 |
1 |
_gx_system_memory_free(png.gx_png_trans); |
|
2344 |
} |
||
2345 |
} |
||
2346 |
|||
2347 |
/* Free scratch buffer. */ |
||
2348 |
665 |
_gx_system_memory_free(scratch_buffer); |
|
2349 |
} |
||
2350 |
else |
||
2351 |
{ |
||
2352 |
8 |
return GX_FAILURE; |
|
2353 |
} |
||
2354 |
|||
2355 |
665 |
return status; |
|
2356 |
} |
||
2357 |
#endif |
||
2358 |
Generated by: GCOVR (Version 4.1) |