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