Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/basis_universal/encoder/pvpngreader.cpp
9902 views
1
// pngreader.cpp - Public Domain - see unlicense at bottom of file.
2
//
3
// Notes:
4
// This is ancient code from ~1995 ported to C++. It was originally written for a
5
// DOS app with very limited memory. It's not as fast as it should be, but it works.
6
// The low-level PNG reader class was written assuming the PNG file could not fit
7
// entirely into memory, which dictated how it was written/structured.
8
// It has been modified to use either zlib or miniz.
9
// It supports all PNG color types/bit depths/interlacing, however 16-bit/component
10
// images are converted to 8-bit.
11
// TRNS chunks are converted to alpha as needed.
12
// GAMA chunk is read, but not applied.
13
14
#include "../transcoder/basisu.h"
15
16
#define MINIZ_HEADER_FILE_ONLY
17
#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES
18
#include "basisu_miniz.h"
19
20
#include "pvpngreader.h"
21
22
#include <stdlib.h>
23
#include <stdio.h>
24
#include <math.h>
25
#include <string.h>
26
#include <vector>
27
#include <assert.h>
28
29
#define PVPNG_IDAT_CRC_CHECKING (1)
30
#define PVPNG_ADLER32_CHECKING (1)
31
32
namespace pv_png
33
{
34
35
const uint32_t MIN_PNG_SIZE = 8 + 13 + 8 + 1 + 4 + 12;
36
37
template <typename S> inline S maximum(S a, S b) { return (a > b) ? a : b; }
38
template <typename S> inline S minimum(S a, S b) { return (a < b) ? a : b; }
39
40
template <typename T> inline void clear_obj(T& obj) { memset(&obj, 0, sizeof(obj)); }
41
42
#define MAX_SUPPORTED_RES (32768)
43
#define FALSE (0)
44
#define TRUE (1)
45
#define PNG_MAX_ALLOC_BLOCKS (16)
46
47
enum
48
{
49
PNG_DECERROR = -3,
50
PNG_ALLDONE = -5,
51
PNG_READPASTEOF = -11,
52
PNG_UNKNOWNTYPE = -16,
53
PNG_FILEREADERROR = -17,
54
PNG_NOTENOUGHMEM = -108,
55
PNG_BAD_CHUNK_CRC32 = -13000,
56
PNG_NO_IHDR = -13001,
57
PNG_BAD_WIDTH = -13002,
58
PNG_BAD_HEIGHT = -13003,
59
PNG_UNS_COMPRESSION = -13004,
60
PNG_UNS_FILTER = -13005,
61
PNG_UNS_ILACE = -13006,
62
PNG_UNS_COLOR_TYPE = -13007,
63
PNG_BAD_BIT_DEPTH = -13008,
64
PNG_BAD_CHUNK_SIZE = -13009,
65
PNG_UNS_CRITICAL_CHUNK = -13010,
66
PNG_BAD_TRNS_CHUNK = -13011,
67
PNG_BAD_PLTE_CHUNK = -13012,
68
PNG_UNS_RESOLUTION = -13013,
69
PNG_INVALID_DATA_STREAM = -13014,
70
PNG_MISSING_PALETTE = -13015,
71
PNG_UNS_PREDICTOR = -13016,
72
PNG_INCOMPLETE_IMAGE = -13017,
73
PNG_TOO_MUCH_DATA = -13018
74
};
75
76
#define PNG_COLOR_TYPE_PAL_MASK (1)
77
#define PNG_COLOR_TYPE_COL_MASK (2)
78
#define PNG_COLOR_TYPE_ALP_MASK (4)
79
80
#define PNG_INFLATE_SRC_BUF_SIZE (4096)
81
82
struct ihdr_struct
83
{
84
uint32_t m_width;
85
uint32_t m_height;
86
uint8_t m_bit_depth;
87
uint8_t m_color_type;
88
uint8_t m_comp_type;
89
uint8_t m_filter_type;
90
uint8_t m_ilace_type;
91
};
92
93
class png_file
94
{
95
public:
96
png_file() { }
97
virtual ~png_file() { }
98
99
virtual bool resize(uint64_t new_size) = 0;
100
virtual uint64_t get_size() = 0;
101
virtual uint64_t tell() = 0;
102
virtual bool seek(uint64_t ofs) = 0;
103
virtual size_t write(const void* pBuf, size_t len) = 0;
104
virtual size_t read(void* pBuf, size_t len) = 0;
105
};
106
107
class png_memory_file : public png_file
108
{
109
public:
110
std::vector<uint8_t> m_buf;
111
uint64_t m_ofs;
112
113
png_memory_file() :
114
png_file(),
115
m_ofs(0)
116
{
117
}
118
119
virtual ~png_memory_file()
120
{
121
}
122
123
std::vector<uint8_t>& get_buf() { return m_buf; }
124
const std::vector<uint8_t>& get_buf() const { return m_buf; }
125
126
void init()
127
{
128
m_ofs = 0;
129
m_buf.resize(0);
130
}
131
132
virtual bool resize(uint64_t new_size)
133
{
134
if ((sizeof(size_t) == sizeof(uint32_t)) && (new_size >= 0x7FFFFFFF))
135
return false;
136
137
m_buf.resize((size_t)new_size);
138
m_ofs = m_buf.size();
139
140
return true;
141
}
142
143
virtual uint64_t get_size()
144
{
145
return m_buf.size();
146
}
147
148
virtual uint64_t tell()
149
{
150
return m_ofs;
151
}
152
153
virtual bool seek(uint64_t ofs)
154
{
155
m_ofs = ofs;
156
return true;
157
}
158
159
virtual size_t write(const void* pBuf, size_t len)
160
{
161
uint64_t new_size = m_ofs + len;
162
if (new_size > m_buf.size())
163
{
164
if ((sizeof(size_t) == sizeof(uint32_t)) && (new_size > 0x7FFFFFFFUL))
165
return 0;
166
m_buf.resize((size_t)new_size);
167
}
168
169
memcpy(&m_buf[(size_t)m_ofs], pBuf, len);
170
m_ofs += len;
171
172
return len;
173
}
174
175
virtual size_t read(void* pBuf, size_t len)
176
{
177
if (m_ofs >= m_buf.size())
178
return 0;
179
180
uint64_t max_bytes = minimum<uint64_t>(len, m_buf.size() - m_ofs);
181
memcpy(pBuf, &m_buf[(size_t)m_ofs], (size_t)max_bytes);
182
183
m_ofs += max_bytes;
184
185
return (size_t)max_bytes;
186
}
187
};
188
189
class png_readonly_memory_file : public png_file
190
{
191
public:
192
const uint8_t* m_pBuf;
193
size_t m_buf_size;
194
uint64_t m_ofs;
195
196
png_readonly_memory_file() :
197
png_file(),
198
m_pBuf(nullptr),
199
m_buf_size(0),
200
m_ofs(0)
201
{
202
}
203
204
virtual ~png_readonly_memory_file()
205
{
206
}
207
208
void init(const void *pBuf, size_t buf_size)
209
{
210
m_pBuf = static_cast<const uint8_t*>(pBuf);
211
m_buf_size = buf_size;
212
m_ofs = 0;
213
}
214
215
virtual bool resize(uint64_t new_size)
216
{
217
(void)new_size;
218
assert(0);
219
return false;
220
}
221
222
virtual uint64_t get_size()
223
{
224
return m_buf_size;
225
}
226
227
virtual uint64_t tell()
228
{
229
return m_ofs;
230
}
231
232
virtual bool seek(uint64_t ofs)
233
{
234
m_ofs = ofs;
235
return true;
236
}
237
238
virtual size_t write(const void* pBuf, size_t len)
239
{
240
(void)pBuf;
241
(void)len;
242
assert(0);
243
return 0;
244
}
245
246
virtual size_t read(void* pBuf, size_t len)
247
{
248
if (m_ofs >= m_buf_size)
249
return 0;
250
251
uint64_t max_bytes = minimum<uint64_t>(len, m_buf_size - m_ofs);
252
memcpy(pBuf, &m_pBuf[(size_t)m_ofs], (size_t)max_bytes);
253
254
m_ofs += max_bytes;
255
256
return (size_t)max_bytes;
257
}
258
};
259
260
#ifdef _MSC_VER
261
#define ftell64 _ftelli64
262
#define fseek64 _fseeki64
263
#else
264
#define ftell64 ftello
265
#define fseek64 fseeko
266
#endif
267
268
class png_cfile : public png_file
269
{
270
public:
271
FILE* m_pFile;
272
273
png_cfile() :
274
png_file(),
275
m_pFile(nullptr)
276
{
277
}
278
279
virtual ~png_cfile()
280
{
281
close();
282
}
283
284
bool init(const char *pFilename, const char *pMode)
285
{
286
close();
287
288
m_pFile = nullptr;
289
290
#ifdef _MSC_VER
291
fopen_s(&m_pFile, pFilename, pMode);
292
#else
293
m_pFile = fopen(pFilename, pMode);
294
#endif
295
296
return m_pFile != nullptr;
297
}
298
299
bool close()
300
{
301
bool status = true;
302
if (m_pFile)
303
{
304
if (fclose(m_pFile) == EOF)
305
status = false;
306
m_pFile = nullptr;
307
}
308
return status;
309
}
310
311
virtual bool resize(uint64_t new_size)
312
{
313
if (new_size)
314
{
315
if (!seek(new_size - 1))
316
return false;
317
318
int v = 0;
319
if (write(&v, 1) != 1)
320
return false;
321
}
322
else
323
{
324
if (!seek(0))
325
return false;
326
}
327
328
return true;
329
}
330
331
virtual uint64_t get_size()
332
{
333
int64_t cur_ofs = ftell64(m_pFile);
334
if (cur_ofs < 0)
335
return 0;
336
337
if (fseek64(m_pFile, 0, SEEK_END) != 0)
338
return 0;
339
340
const int64_t cur_size = ftell64(m_pFile);
341
if (cur_size < 0)
342
return 0;
343
344
if (fseek64(m_pFile, cur_ofs, SEEK_SET) != 0)
345
return 0;
346
347
return cur_size;
348
}
349
350
virtual uint64_t tell()
351
{
352
int64_t cur_ofs = ftell64(m_pFile);
353
if (cur_ofs < 0)
354
return 0;
355
356
return cur_ofs;
357
}
358
359
virtual bool seek(uint64_t ofs)
360
{
361
return fseek64(m_pFile, ofs, SEEK_SET) == 0;
362
}
363
364
virtual size_t write(const void* pBuf, size_t len)
365
{
366
return (size_t)fwrite(pBuf, 1, len, m_pFile);
367
}
368
369
virtual size_t read(void* pBuf, size_t len)
370
{
371
return (size_t)fread(pBuf, 1, len, m_pFile);
372
}
373
};
374
375
// This low-level helper class handles the actual decoding of PNG files.
376
class png_decoder
377
{
378
public:
379
png_decoder();
380
~png_decoder();
381
382
// Scans the PNG file, but doesn't decode the IDAT data.
383
// Returns 0 on success, or an error code.
384
// If the returned status is non-zero, or m_img_supported_flag==FALSE the image either the image is corrupted/not PNG or is unsupported in some way.
385
int png_scan(png_file *pFile);
386
387
// Decodes a single scanline of PNG image data.
388
// Returns a pointer to the scanline's pixel data and its size in bytes.
389
// This data is only minimally processed from the internal PNG pixel data.
390
// The caller must use the ihdr, trns_flag and values, and the palette to actually decode the pixel data.
391
//
392
// Possible returned pixel formats is somewhat complex due to the history of this code:
393
// 8-bit RGBA, always 4 bytes/pixel - 24bpp PNG's are converted to 32bpp and TRNS processing is done automatically (8/16bpp RGB or RGBA PNG files)
394
// 1/2/4/8-bit grayscale, 1 byte per pixel - must convert to [0,255] using the palette or some other means, must optionally use the TRNS chunk for alpha (1/2/4/8 Grayscale PNG files - not 16bpp though!)
395
// 1/2/4/8-bit palettized, 1 byte per pixel - must convert to RGB using the 24bpp palette and optionally the TRNS chunk for alpha (1/2/4/8bpp palettized PNG files)
396
// 8-bit grayscale with alpha, 2 bytes per pixel - TRNS processing will be done for you on 16bpp images (there's a special case here for 16bpp Grey files) (8/16bpp Gray-Alpha *or 16bpp Grayscale* PNG files)
397
//
398
// Returns 0 on success, a non-zero error code, or PNG_ALLDONE.
399
int png_decode(void** ppImg_ptr, uint32_t* pImg_len);
400
401
// Starts decoding. Returns 0 on success, otherwise an error code.
402
int png_decode_start();
403
404
// Deinitializes the decoder, freeing all allocations.
405
void png_decode_end();
406
407
png_file* m_pFile;
408
409
// Image's 24bpp palette - 3 bytes per entry
410
uint8_t m_plte_flag;
411
uint8_t m_img_pal[768];
412
413
int m_img_supported_flag;
414
415
ihdr_struct m_ihdr;
416
417
uint8_t m_chunk_flag;
418
uint32_t m_chunk_size;
419
uint32_t m_chunk_left;
420
uint32_t m_chunk_crc32;
421
uint8_t m_chunk_name[4];
422
423
uint8_t m_end_of_idat_chunks;
424
425
void* m_pMalloc_blocks[PNG_MAX_ALLOC_BLOCKS];
426
427
uint32_t m_dec_bytes_per_pixel; // bytes per pixel decoded from the PNG file (minimum 1 for 1/2/4 bpp), factors in the PNG 8/16 bit/component bit depth, may be up to 8 bytes (2*4)
428
uint32_t m_dst_bytes_per_pixel; // bytes per pixel returned to the caller (1-4), always has alpha if the PNG has alpha, 16-bit components always converted to 8-bits/component
429
430
uint32_t m_dec_bytes_per_line; // bytes per line decoded from the PNG file (before 1/2/4 expansion), +1 for the filter byte
431
uint32_t m_src_bytes_per_line; // decoded PNG bytes per line, before 1/2/4 bpp expansion, not counting the filter byte, updated during adam7 deinterlacing
432
uint32_t m_dst_bytes_per_line; // bytes per line returned to the caller (1-4 times width)
433
434
int (*m_pProcess_func)(uint8_t* src, uint8_t* dst, int pixels, png_decoder* pwi);
435
436
uint8_t* m_pPre_line_buf;
437
uint8_t* m_pCur_line_buf;
438
uint8_t* m_pPro_line_buf;
439
440
uint8_t m_bkgd_flag;
441
uint32_t m_bkgd_value[3];
442
443
uint8_t m_gama_flag;
444
uint32_t m_gama_value;
445
446
uint8_t m_trns_flag;
447
uint32_t m_trns_value[256];
448
449
buminiz::mz_stream m_inflator;
450
451
uint8_t inflate_src_buf[PNG_INFLATE_SRC_BUF_SIZE];
452
453
uint32_t m_inflate_src_buf_ofs;
454
uint32_t m_inflate_src_buf_size;
455
uint32_t m_inflate_dst_buf_ofs;
456
457
int m_inflate_eof_flag;
458
459
uint8_t m_gamma_table[256];
460
461
int m_pass_x_size;
462
int m_pass_y_left;
463
464
int m_adam7_pass_num;
465
int m_adam7_pass_y;
466
int m_adam7_pass_size_x[7];
467
int m_adam7_pass_size_y[7];
468
469
std::vector<uint8_t> m_adam7_image_buf;
470
471
int m_adam7_decoded_flag;
472
473
bool m_scanned_flag;
474
475
int m_terminate_status;
476
477
#define TEMP_BUF_SIZE (384)
478
uint8_t m_temp_buf[TEMP_BUF_SIZE * 4];
479
480
void clear();
481
void uninitialize();
482
int terminate(int status);
483
void* png_malloc(uint32_t i);
484
void* png_calloc(uint32_t i);
485
int block_read(void* buf, uint32_t len);
486
int64_t block_read_dword();
487
int fetch_next_chunk_data(uint8_t* buf, int bytes);
488
int fetch_next_chunk_byte();
489
int fetch_next_chunk_word();
490
int64_t fetch_next_chunk_dword();
491
int fetch_next_chunk_init();
492
int unchunk_data(uint8_t* buf, uint32_t bytes, uint32_t* ptr_bytes_read);
493
inline void adam7_write_pixel_8(int x, int y, int c);
494
inline void adam7_write_pixel_16(int x, int y, int r, int g);
495
inline void adam7_write_pixel_24(int x, int y, int r, int g, int b);
496
inline void adam7_write_pixel_32(int x, int y, int r, int g, int b, int a);
497
void unpredict_sub(uint8_t* lst, uint8_t* cur, uint32_t bytes, int bpp);
498
void unpredict_up(uint8_t* lst, uint8_t* cur, uint32_t bytes, int bpp);
499
void unpredict_average(uint8_t* lst, uint8_t* cur, uint32_t bytes, int bpp);
500
inline uint8_t paeth_predictor(int a, int b, int c);
501
void unpredict_paeth(uint8_t* lst, uint8_t* cur, uint32_t bytes, int bpp);
502
int adam7_pass_size(int size, int start, int step);
503
int decompress_line(uint32_t* bytes_decoded);
504
int find_iend_chunk();
505
void calc_gamma_table();
506
void create_grey_palette();
507
int read_signature();
508
int read_ihdr_chunk();
509
int read_bkgd_chunk();
510
int read_gama_chunk();
511
int read_trns_chunk();
512
int read_plte_chunk();
513
int find_idat_chunk();
514
};
515
516
void png_decoder::uninitialize()
517
{
518
m_pFile = nullptr;
519
520
for (int i = 0; i < PNG_MAX_ALLOC_BLOCKS; i++)
521
{
522
free(m_pMalloc_blocks[i]);
523
m_pMalloc_blocks[i] = nullptr;
524
}
525
526
mz_inflateEnd(&m_inflator);
527
}
528
529
int png_decoder::terminate(int status)
530
{
531
if (m_terminate_status == 0)
532
m_terminate_status = status;
533
534
uninitialize();
535
return status;
536
}
537
538
void* png_decoder::png_malloc(uint32_t len)
539
{
540
if (!len)
541
len++;
542
543
void* p = malloc(len);
544
545
if (!p)
546
return nullptr;
547
548
int j;
549
for (j = 0; j < PNG_MAX_ALLOC_BLOCKS; j++)
550
if (!m_pMalloc_blocks[j])
551
break;
552
553
if (j == PNG_MAX_ALLOC_BLOCKS)
554
return nullptr;
555
556
m_pMalloc_blocks[j] = p;
557
558
return p;
559
}
560
561
void* png_decoder::png_calloc(uint32_t len)
562
{
563
void* p = png_malloc(len);
564
if (!p)
565
return nullptr;
566
567
if (p)
568
memset(p, 0, len);
569
570
return p;
571
}
572
573
int png_decoder::block_read(void* buf, uint32_t len)
574
{
575
size_t bytes_read = m_pFile->read(buf, len);
576
if (bytes_read != len)
577
return terminate(PNG_READPASTEOF);
578
return 0;
579
}
580
581
int64_t png_decoder::block_read_dword()
582
{
583
uint8_t buf[4];
584
585
int status = block_read(buf, 4);
586
if (status != 0)
587
return status;
588
589
uint32_t v = buf[3] + ((uint32_t)buf[2] << 8) + ((uint32_t)buf[1] << 16) + ((uint32_t)buf[0] << 24);
590
return (int64_t)v;
591
}
592
593
int png_decoder::fetch_next_chunk_data(uint8_t* buf, int bytes)
594
{
595
if (!m_chunk_flag)
596
return 0;
597
598
bytes = minimum<int>(bytes, m_chunk_left);
599
600
int status = block_read(buf, bytes);
601
if (status != 0)
602
return status;
603
604
#if PVPNG_IDAT_CRC_CHECKING
605
bool check_crc32 = true;
606
#else
607
const bool is_idat = (m_chunk_name[0] == 'I') && (m_chunk_name[1] == 'D') && (m_chunk_name[2] == 'A') && (m_chunk_name[3] == 'T');
608
bool check_crc32 = !is_idat;
609
#endif
610
611
if (check_crc32)
612
m_chunk_crc32 = buminiz::mz_crc32(m_chunk_crc32, buf, bytes);
613
614
if ((m_chunk_left -= bytes) == 0)
615
{
616
int64_t res = block_read_dword();
617
if (res < 0)
618
return (int)res;
619
620
if (check_crc32)
621
{
622
if (m_chunk_crc32 != (uint32_t)res)
623
return terminate(PNG_BAD_CHUNK_CRC32);
624
}
625
626
m_chunk_flag = FALSE;
627
}
628
629
return bytes;
630
}
631
632
int png_decoder::fetch_next_chunk_byte()
633
{
634
uint8_t buf[1];
635
636
int status = fetch_next_chunk_data(buf, 1);
637
if (status < 0)
638
return status;
639
640
if (status != 1)
641
return terminate(PNG_BAD_CHUNK_SIZE);
642
643
return buf[0];
644
}
645
646
int png_decoder::fetch_next_chunk_word()
647
{
648
uint8_t buf[2];
649
650
int status = fetch_next_chunk_data(buf, 2);
651
if (status < 0)
652
return status;
653
654
if (status != 2)
655
return terminate(PNG_BAD_CHUNK_SIZE);
656
657
return buf[1] + ((uint32_t)buf[0] << 8);
658
}
659
660
int64_t png_decoder::fetch_next_chunk_dword()
661
{
662
uint8_t buf[4];
663
664
int status = fetch_next_chunk_data(buf, 4);
665
if (status < 0)
666
return status;
667
668
if (status != 4)
669
terminate(PNG_BAD_CHUNK_SIZE);
670
671
uint32_t v = buf[3] + ((uint32_t)buf[2] << 8) + ((uint32_t)buf[1] << 16) + ((uint32_t)buf[0] << 24);
672
return (int64_t)v;
673
}
674
675
int png_decoder::fetch_next_chunk_init()
676
{
677
while (m_chunk_flag)
678
{
679
int status = fetch_next_chunk_data(m_temp_buf, TEMP_BUF_SIZE * 4);
680
if (status != 0)
681
return status;
682
}
683
684
int64_t n = block_read_dword();
685
if (n < 0)
686
return (int)n;
687
688
m_chunk_size = (uint32_t)n;
689
690
m_chunk_flag = TRUE;
691
m_chunk_left = m_chunk_size + 4;
692
m_chunk_crc32 = 0;
693
694
int status = fetch_next_chunk_data(m_chunk_name, 4);
695
if (status < 0)
696
return status;
697
698
return 0;
699
}
700
701
int png_decoder::unchunk_data(uint8_t* buf, uint32_t bytes, uint32_t* ptr_bytes_read)
702
{
703
uint32_t bytes_read = 0;
704
705
if ((!bytes) || (m_end_of_idat_chunks))
706
{
707
*ptr_bytes_read = 0;
708
return TRUE;
709
}
710
711
while (bytes_read != bytes)
712
{
713
if (!m_chunk_flag)
714
{
715
int res = fetch_next_chunk_init();
716
if (res < 0)
717
return res;
718
719
if ((m_chunk_name[0] != 'I') ||
720
(m_chunk_name[1] != 'D') ||
721
(m_chunk_name[2] != 'A') ||
722
(m_chunk_name[3] != 'T'))
723
{
724
*ptr_bytes_read = bytes_read;
725
m_end_of_idat_chunks = TRUE;
726
return TRUE;
727
}
728
}
729
730
int res = fetch_next_chunk_data(buf + bytes_read, bytes - bytes_read);
731
if (res < 0)
732
return res;
733
734
bytes_read += (uint32_t)res;
735
}
736
737
*ptr_bytes_read = bytes_read;
738
739
return FALSE;
740
}
741
742
inline void png_decoder::adam7_write_pixel_8(int x, int y, int c)
743
{
744
m_adam7_image_buf[x + y * m_dst_bytes_per_line] = (uint8_t)c;
745
}
746
747
inline void png_decoder::adam7_write_pixel_16(int x, int y, int r, int g)
748
{
749
uint32_t ofs = x * 2 + y * m_dst_bytes_per_line;
750
m_adam7_image_buf[ofs + 0] = (uint8_t)r;
751
m_adam7_image_buf[ofs + 1] = (uint8_t)g;
752
}
753
754
inline void png_decoder::adam7_write_pixel_24(int x, int y, int r, int g, int b)
755
{
756
uint32_t ofs = x * 3 + y * m_dst_bytes_per_line;
757
m_adam7_image_buf[ofs + 0] = (uint8_t)r;
758
m_adam7_image_buf[ofs + 1] = (uint8_t)g;
759
m_adam7_image_buf[ofs + 2] = (uint8_t)b;
760
}
761
762
inline void png_decoder::adam7_write_pixel_32(int x, int y, int r, int g, int b, int a)
763
{
764
uint32_t ofs = x * 4 + y * m_dst_bytes_per_line;
765
m_adam7_image_buf[ofs + 0] = (uint8_t)r;
766
m_adam7_image_buf[ofs + 1] = (uint8_t)g;
767
m_adam7_image_buf[ofs + 2] = (uint8_t)b;
768
m_adam7_image_buf[ofs + 3] = (uint8_t)a;
769
}
770
771
static void PixelDePack2(void* src, void* dst, int numbytes)
772
{
773
uint8_t* src8 = (uint8_t*)src;
774
uint8_t* dst8 = (uint8_t*)dst;
775
776
while (numbytes)
777
{
778
uint8_t v = *src8++;
779
780
for (uint32_t i = 0; i < 8; i++)
781
dst8[7 - i] = (v >> i) & 1;
782
783
dst8 += 8;
784
numbytes--;
785
}
786
}
787
788
static void PixelDePack16(void* src, void* dst, int numbytes)
789
{
790
uint8_t* src8 = (uint8_t*)src;
791
uint8_t* dst8 = (uint8_t*)dst;
792
793
while (numbytes)
794
{
795
uint8_t v = *src8++;
796
797
dst8[0] = (uint8_t)v >> 4;
798
dst8[1] = (uint8_t)v & 0xF;
799
dst8 += 2;
800
801
numbytes--;
802
}
803
}
804
805
static int unpack_grey_1(uint8_t* src, uint8_t* dst, int pixels, png_decoder *pwi)
806
{
807
(void)pwi;
808
PixelDePack2(src, dst, pixels >> 3);
809
810
dst += (pixels & 0xFFF8);
811
812
if ((pixels & 7) != 0)
813
{
814
uint8_t c = src[pixels >> 3];
815
816
pixels &= 7;
817
818
while (pixels--)
819
{
820
*dst++ = ((c & 128) >> 7);
821
822
c <<= 1;
823
}
824
}
825
826
return TRUE;
827
}
828
829
static int unpack_grey_2(uint8_t* src, uint8_t* dst, int pixels, png_decoder* pwi)
830
{
831
(void)pwi;
832
int i = pixels;
833
uint8_t c;
834
835
while (i >= 4)
836
{
837
c = *src++;
838
839
*dst++ = (c >> 6);
840
*dst++ = (c >> 4) & 3;
841
*dst++ = (c >> 2) & 3;
842
*dst++ = (c) & 3;
843
844
i -= 4;
845
}
846
847
if (i)
848
{
849
c = *src;
850
851
while (i--)
852
{
853
*dst++ = (c >> 6);
854
855
c <<= 2;
856
}
857
}
858
859
return TRUE;
860
}
861
862
static int unpack_grey_4(uint8_t* src, uint8_t* dst, int pixels, png_decoder* pwi)
863
{
864
(void)pwi;
865
866
PixelDePack16(src, dst, pixels >> 1);
867
868
if (pixels & 1)
869
dst[pixels & 0xFFFE] = (src[pixels >> 1] >> 4);
870
871
return TRUE;
872
}
873
874
static int unpack_grey_8(uint8_t* src, uint8_t* dst, int pixels, png_decoder* pwi)
875
{
876
(void)src;
877
(void)dst;
878
(void)pixels;
879
(void)pwi;
880
return FALSE;
881
}
882
883
static int unpack_grey_16(uint8_t* src, uint8_t* dst, int pixels, png_decoder* pwi)
884
{
885
(void)pwi;
886
while (pixels--)
887
{
888
*dst++ = *src++;
889
890
src++;
891
}
892
893
return TRUE;
894
}
895
896
static int unpack_grey_16_2(uint8_t* src, uint8_t* dst, int pixels, png_decoder* pwi)
897
{
898
if (pwi->m_trns_flag)
899
{
900
while (pixels--)
901
{
902
uint32_t v = (src[0] << 8) + src[1];
903
src += 2;
904
905
*dst++ = (uint8_t)(v >> 8);
906
*dst++ = (v == pwi->m_trns_value[0]) ? 0 : 255;
907
}
908
}
909
else
910
{
911
while (pixels--)
912
{
913
*dst++ = *src++;
914
*dst++ = 0xFF;
915
916
src++;
917
}
918
}
919
920
return TRUE;
921
}
922
923
static int unpack_true_8(uint8_t* src, uint8_t* dst, int pixels, png_decoder* pwi)
924
{
925
if (pwi->m_trns_flag)
926
{
927
const uint32_t tr = pwi->m_trns_value[0];
928
const uint32_t tg = pwi->m_trns_value[1];
929
const uint32_t tb = pwi->m_trns_value[2];
930
931
for (int i = 0; i < pixels; i++)
932
{
933
uint8_t r = src[i * 3 + 0];
934
uint8_t g = src[i * 3 + 1];
935
uint8_t b = src[i * 3 + 2];
936
937
dst[i * 4 + 0] = r;
938
dst[i * 4 + 1] = g;
939
dst[i * 4 + 2] = b;
940
dst[i * 4 + 3] = ((r == tr) && (g == tg) && (b == tb)) ? 0 : 255;
941
}
942
}
943
else
944
{
945
for (int i = 0; i < pixels; i++)
946
{
947
dst[i * 4 + 0] = src[i * 3 + 0];
948
dst[i * 4 + 1] = src[i * 3 + 1];
949
dst[i * 4 + 2] = src[i * 3 + 2];
950
dst[i * 4 + 3] = 255;
951
}
952
}
953
954
return TRUE;
955
}
956
957
static int unpack_true_16(uint8_t* src, uint8_t* dst, int pixels, png_decoder* pwi)
958
{
959
if (pwi->m_trns_flag)
960
{
961
const uint32_t tr = pwi->m_trns_value[0];
962
const uint32_t tg = pwi->m_trns_value[1];
963
const uint32_t tb = pwi->m_trns_value[2];
964
965
for (int i = 0; i < pixels; i++)
966
{
967
uint32_t r = (src[i * 6 + 0] << 8) + src[i * 6 + 1];
968
uint32_t g = (src[i * 6 + 2] << 8) + src[i * 6 + 3];
969
uint32_t b = (src[i * 6 + 4] << 8) + src[i * 6 + 5];
970
971
dst[i * 4 + 0] = (uint8_t)(r >> 8);
972
dst[i * 4 + 1] = (uint8_t)(g >> 8);
973
dst[i * 4 + 2] = (uint8_t)(b >> 8);
974
dst[i * 4 + 3] = ((r == tr) && (g == tg) && (b == tb)) ? 0 : 255;
975
}
976
}
977
else
978
{
979
while (pixels--)
980
{
981
dst[0] = src[0];
982
dst[1] = src[2];
983
dst[2] = src[4];
984
dst[3] = 255;
985
986
dst += 4;
987
src += 6;
988
}
989
}
990
991
return TRUE;
992
}
993
994
static int unpack_grey_alpha_8(uint8_t* src, uint8_t* dst, int pixels, png_decoder* pwi)
995
{
996
(void)pwi;
997
while (pixels--)
998
{
999
dst[0] = src[0];
1000
dst[1] = src[1];
1001
dst += 2;
1002
src += 2;
1003
}
1004
1005
return TRUE;
1006
}
1007
1008
static int unpack_grey_alpha_16(uint8_t* src, uint8_t* dst, int pixels, png_decoder* pwi)
1009
{
1010
(void)pwi;
1011
while (pixels--)
1012
{
1013
dst[0] = src[0];
1014
dst[1] = src[2];
1015
dst += 2;
1016
src += 4;
1017
}
1018
1019
return TRUE;
1020
}
1021
1022
static int unpack_true_alpha_8(uint8_t* src, uint8_t* dst, int pixels, png_decoder* pwi)
1023
{
1024
(void)src;
1025
(void)dst;
1026
(void)pixels;
1027
(void)pwi;
1028
return FALSE;
1029
}
1030
1031
static int unpack_true_alpha_16(uint8_t* src, uint8_t* dst, int pixels, png_decoder* pwi)
1032
{
1033
(void)pwi;
1034
while (pixels--)
1035
{
1036
dst[0] = src[0];
1037
dst[1] = src[2];
1038
dst[2] = src[4];
1039
dst[3] = src[6];
1040
dst += 4;
1041
src += 8;
1042
}
1043
1044
return TRUE;
1045
}
1046
1047
void png_decoder::unpredict_sub(uint8_t* lst, uint8_t* cur, uint32_t bytes, int bpp)
1048
{
1049
(void)lst;
1050
if (bytes == (uint32_t)bpp)
1051
return;
1052
1053
cur += bpp;
1054
bytes -= bpp;
1055
1056
while (bytes--)
1057
{
1058
*cur += *(cur - bpp);
1059
cur++;
1060
}
1061
}
1062
1063
void png_decoder::unpredict_up(uint8_t* lst, uint8_t* cur, uint32_t bytes, int bpp)
1064
{
1065
(void)bpp;
1066
while (bytes--)
1067
*cur++ += *lst++;
1068
}
1069
1070
void png_decoder::unpredict_average(uint8_t* lst, uint8_t* cur, uint32_t bytes, int bpp)
1071
{
1072
int i;
1073
1074
for (i = 0; i < bpp; i++)
1075
*cur++ += (*lst++ >> 1);
1076
1077
if (bytes == (uint32_t)bpp)
1078
return;
1079
1080
bytes -= bpp;
1081
1082
while (bytes--)
1083
{
1084
*cur += ((*lst++ + *(cur - bpp)) >> 1);
1085
cur++;
1086
}
1087
}
1088
1089
inline uint8_t png_decoder::paeth_predictor(int a, int b, int c)
1090
{
1091
int p, pa, pb, pc;
1092
1093
/* a = left, b = above, c = upper left */
1094
1095
p = a + b - c;
1096
1097
pa = abs(p - a);
1098
pb = abs(p - b);
1099
pc = abs(p - c);
1100
1101
if ((pa <= pb) && (pa <= pc))
1102
return (uint8_t)a;
1103
else if (pb <= pc)
1104
return (uint8_t)b;
1105
else
1106
return (uint8_t)c;
1107
}
1108
1109
void png_decoder::unpredict_paeth(uint8_t* lst, uint8_t* cur, uint32_t bytes, int bpp)
1110
{
1111
int i;
1112
1113
for (i = 0; i < bpp; i++)
1114
*cur++ += paeth_predictor(0, *lst++, 0);
1115
1116
if (bytes == (uint32_t)bpp)
1117
return;
1118
1119
bytes -= bpp;
1120
1121
while (bytes--)
1122
{
1123
int p, a, b, c, pa, pb, pc;
1124
1125
a = *(cur - bpp);
1126
b = *lst;
1127
c = *(lst - bpp);
1128
1129
p = a + b - c;
1130
1131
pa = abs(p - a);
1132
pb = abs(p - b);
1133
pc = abs(p - c);
1134
1135
if ((pa <= pb) && (pa <= pc))
1136
*cur++ += (uint8_t)a;
1137
else if (pb <= pc)
1138
*cur++ += (uint8_t)b;
1139
else
1140
*cur++ += (uint8_t)c;
1141
1142
lst++;
1143
}
1144
}
1145
1146
int png_decoder::adam7_pass_size(int size, int start, int step)
1147
{
1148
if (size > start)
1149
return 1 + ((size - 1) - start) / step;
1150
else
1151
return 0;
1152
}
1153
1154
// TRUE if no more data, negative on error, FALSE if OK
1155
int png_decoder::decompress_line(uint32_t* bytes_decoded)
1156
{
1157
int status;
1158
uint32_t temp, src_bytes_left, dst_bytes_left;
1159
1160
m_inflate_dst_buf_ofs = 0;
1161
1162
for (; ; )
1163
{
1164
if (m_inflate_src_buf_ofs == PNG_INFLATE_SRC_BUF_SIZE)
1165
{
1166
int res = unchunk_data(inflate_src_buf, PNG_INFLATE_SRC_BUF_SIZE, &temp);
1167
if (res < 0)
1168
return res;
1169
m_inflate_eof_flag = res;
1170
1171
m_inflate_src_buf_size = temp;
1172
1173
m_inflate_src_buf_ofs = 0;
1174
}
1175
1176
for (; ; )
1177
{
1178
src_bytes_left = m_inflate_src_buf_size - m_inflate_src_buf_ofs;
1179
dst_bytes_left = m_dec_bytes_per_line - m_inflate_dst_buf_ofs;
1180
1181
m_inflator.next_in = inflate_src_buf + m_inflate_src_buf_ofs;
1182
m_inflator.avail_in = src_bytes_left;
1183
1184
m_inflator.next_out = m_pCur_line_buf + m_inflate_dst_buf_ofs;
1185
m_inflator.avail_out = dst_bytes_left;
1186
1187
status = buminiz::mz_inflate2(&m_inflator, buminiz::MZ_NO_FLUSH, PVPNG_ADLER32_CHECKING);
1188
1189
const uint32_t src_bytes_consumed = src_bytes_left - m_inflator.avail_in;
1190
const uint32_t dst_bytes_written = dst_bytes_left - m_inflator.avail_out;
1191
1192
m_inflate_src_buf_ofs += src_bytes_consumed;
1193
m_inflate_dst_buf_ofs += dst_bytes_written;
1194
1195
if (status != buminiz::MZ_OK)
1196
{
1197
if (status != buminiz::MZ_STREAM_END)
1198
return terminate(PNG_INVALID_DATA_STREAM);
1199
1200
if (bytes_decoded)
1201
*bytes_decoded = m_inflate_dst_buf_ofs;
1202
1203
return TRUE;
1204
}
1205
1206
if (m_inflate_dst_buf_ofs == m_dec_bytes_per_line)
1207
{
1208
if (bytes_decoded)
1209
*bytes_decoded = m_inflate_dst_buf_ofs;
1210
1211
return FALSE;
1212
}
1213
1214
if ((m_inflate_src_buf_ofs == m_inflate_src_buf_size) &&
1215
(m_inflate_eof_flag == FALSE))
1216
break;
1217
}
1218
}
1219
}
1220
1221
int png_decoder::find_iend_chunk()
1222
{
1223
uint32_t dummy;
1224
1225
while (!m_end_of_idat_chunks)
1226
{
1227
int res = unchunk_data(m_temp_buf, TEMP_BUF_SIZE * 4, &dummy);
1228
if (res < 0)
1229
return res;
1230
}
1231
1232
for (; ; )
1233
{
1234
if ((m_chunk_name[0] == 'I') &&
1235
(m_chunk_name[1] == 'E') &&
1236
(m_chunk_name[2] == 'N') &&
1237
(m_chunk_name[3] == 'D'))
1238
break;
1239
1240
int res = fetch_next_chunk_init();
1241
if (res < 0)
1242
return res;
1243
}
1244
1245
return 0;
1246
}
1247
1248
int png_decoder::png_decode(void** ppImg_ptr, uint32_t* pImg_len)
1249
{
1250
int status;
1251
uint8_t* decoded_line;
1252
uint32_t bytes_decoded;
1253
1254
if (m_adam7_decoded_flag)
1255
{
1256
if (m_pass_y_left == 0)
1257
return PNG_ALLDONE;
1258
1259
*ppImg_ptr = &m_adam7_image_buf[(m_ihdr.m_height - m_pass_y_left) * m_dst_bytes_per_line];
1260
*pImg_len = m_dst_bytes_per_line;
1261
1262
m_pass_y_left--;
1263
1264
return 0;
1265
}
1266
1267
if (m_pass_y_left == 0)
1268
{
1269
if (m_ihdr.m_ilace_type == 0)
1270
{
1271
status = find_iend_chunk();
1272
if (status < 0)
1273
return status;
1274
1275
return PNG_ALLDONE;
1276
}
1277
1278
for (; ; )
1279
{
1280
if (++m_adam7_pass_num == 7)
1281
{
1282
status = find_iend_chunk();
1283
if (status < 0)
1284
return status;
1285
1286
return PNG_ALLDONE;
1287
}
1288
1289
if (((m_pass_y_left = m_adam7_pass_size_y[m_adam7_pass_num]) != 0) &&
1290
((m_pass_x_size = m_adam7_pass_size_x[m_adam7_pass_num]) != 0))
1291
break;
1292
}
1293
1294
switch (m_adam7_pass_num)
1295
{
1296
case 0:
1297
case 1:
1298
case 3:
1299
case 5:
1300
m_adam7_pass_y = 0;
1301
break;
1302
case 2:
1303
m_adam7_pass_y = 4;
1304
break;
1305
case 4:
1306
m_adam7_pass_y = 2;
1307
break;
1308
case 6:
1309
m_adam7_pass_y = 1;
1310
break;
1311
}
1312
1313
switch (m_ihdr.m_color_type)
1314
{
1315
case PNG_COLOR_TYPE_GREYSCALE:
1316
case PNG_COLOR_TYPE_PALETTIZED:
1317
{
1318
m_src_bytes_per_line = (((uint32_t)m_pass_x_size * m_ihdr.m_bit_depth) + 7) / 8;
1319
break;
1320
}
1321
case PNG_COLOR_TYPE_TRUECOLOR:
1322
{
1323
m_src_bytes_per_line = ((uint32_t)m_pass_x_size * m_dec_bytes_per_pixel);
1324
break;
1325
}
1326
case PNG_COLOR_TYPE_GREYSCALE_ALPHA:
1327
{
1328
m_src_bytes_per_line = ((uint32_t)m_pass_x_size * m_dec_bytes_per_pixel);
1329
break;
1330
}
1331
case PNG_COLOR_TYPE_TRUECOLOR_ALPHA:
1332
{
1333
m_src_bytes_per_line = ((uint32_t)m_pass_x_size * m_dec_bytes_per_pixel);
1334
break;
1335
}
1336
}
1337
1338
m_dec_bytes_per_line = m_src_bytes_per_line + 1;
1339
1340
memset(m_pPre_line_buf, 0, m_src_bytes_per_line);
1341
}
1342
1343
int res = decompress_line(&bytes_decoded);
1344
if (res < 0)
1345
return terminate(res);
1346
1347
if (res)
1348
{
1349
if (m_ihdr.m_ilace_type == 0)
1350
{
1351
if (m_pass_y_left != 1)
1352
return terminate(PNG_INCOMPLETE_IMAGE);
1353
}
1354
else
1355
{
1356
if ((m_pass_y_left != 1) && (m_adam7_pass_num != 6))
1357
return terminate(PNG_INCOMPLETE_IMAGE);
1358
}
1359
}
1360
1361
if (bytes_decoded != m_dec_bytes_per_line)
1362
return terminate(PNG_INCOMPLETE_IMAGE);
1363
1364
decoded_line = &m_pCur_line_buf[1];
1365
1366
switch (m_pCur_line_buf[0])
1367
{
1368
case 0:
1369
break;
1370
case 1:
1371
{
1372
unpredict_sub(m_pPre_line_buf, m_pCur_line_buf + 1, m_src_bytes_per_line, m_dec_bytes_per_pixel);
1373
break;
1374
}
1375
case 2:
1376
{
1377
unpredict_up(m_pPre_line_buf, m_pCur_line_buf + 1, m_src_bytes_per_line, m_dec_bytes_per_pixel);
1378
break;
1379
}
1380
case 3:
1381
{
1382
unpredict_average(m_pPre_line_buf, m_pCur_line_buf + 1, m_src_bytes_per_line, m_dec_bytes_per_pixel);
1383
break;
1384
}
1385
case 4:
1386
{
1387
unpredict_paeth(m_pPre_line_buf, m_pCur_line_buf + 1, m_src_bytes_per_line, m_dec_bytes_per_pixel);
1388
break;
1389
}
1390
default:
1391
return terminate(PNG_UNS_PREDICTOR);
1392
}
1393
1394
memmove(m_pPre_line_buf, m_pCur_line_buf + 1, m_src_bytes_per_line);
1395
1396
if (m_pProcess_func)
1397
{
1398
if ((*m_pProcess_func)(m_pCur_line_buf + 1, m_pPro_line_buf, m_pass_x_size, this))
1399
decoded_line = m_pPro_line_buf;
1400
}
1401
1402
if (m_ihdr.m_ilace_type == 0)
1403
{
1404
*ppImg_ptr = decoded_line;
1405
*pImg_len = m_dst_bytes_per_line;
1406
1407
if (--m_pass_y_left == 0)
1408
{
1409
res = decompress_line(&bytes_decoded);
1410
if (res < 0)
1411
return terminate(res);
1412
1413
if (res == FALSE)
1414
return terminate(PNG_TOO_MUCH_DATA);
1415
1416
if (bytes_decoded)
1417
return terminate(PNG_TOO_MUCH_DATA);
1418
}
1419
}
1420
else
1421
{
1422
int i, x_ofs = 0, y_ofs = 0, x_stp = 0;
1423
uint8_t* p = decoded_line;
1424
1425
switch (m_adam7_pass_num)
1426
{
1427
case 0: { x_ofs = 0; x_stp = 8; break; }
1428
case 1: { x_ofs = 4; x_stp = 8; break; }
1429
case 2: { x_ofs = 0; x_stp = 4; break; }
1430
case 3: { x_ofs = 2; x_stp = 4; break; }
1431
case 4: { x_ofs = 0; x_stp = 2; break; }
1432
case 5: { x_ofs = 1; x_stp = 2; break; }
1433
case 6: { x_ofs = 0; x_stp = 1; break; }
1434
}
1435
1436
y_ofs = m_adam7_pass_y;
1437
1438
assert(x_ofs < (int)m_ihdr.m_width);
1439
assert(y_ofs < (int)m_ihdr.m_height);
1440
1441
if (m_dst_bytes_per_pixel == 1)
1442
{
1443
for (i = m_pass_x_size; i > 0; i--, x_ofs += x_stp)
1444
adam7_write_pixel_8(x_ofs, y_ofs, *p++);
1445
}
1446
else if (m_dst_bytes_per_pixel == 2)
1447
{
1448
for (i = m_pass_x_size; i > 0; i--, x_ofs += x_stp, p += 2)
1449
adam7_write_pixel_16(x_ofs, y_ofs, p[0], p[1]);
1450
}
1451
else if (m_dst_bytes_per_pixel == 3)
1452
{
1453
for (i = m_pass_x_size; i > 0; i--, x_ofs += x_stp, p += 3)
1454
adam7_write_pixel_24(x_ofs, y_ofs, p[0], p[1], p[2]);
1455
}
1456
else if (m_dst_bytes_per_pixel == 4)
1457
{
1458
for (i = m_pass_x_size; i > 0; i--, x_ofs += x_stp, p += 4)
1459
adam7_write_pixel_32(x_ofs, y_ofs, p[0], p[1], p[2], p[3]);
1460
}
1461
else
1462
{
1463
assert(0);
1464
}
1465
1466
switch (m_adam7_pass_num)
1467
{
1468
case 0:
1469
case 1:
1470
case 2: { m_adam7_pass_y += 8; break; }
1471
case 3:
1472
case 4: { m_adam7_pass_y += 4; break; }
1473
case 5:
1474
case 6: { m_adam7_pass_y += 2; break; }
1475
}
1476
1477
if ((--m_pass_y_left == 0) && (m_adam7_pass_num == 6))
1478
{
1479
res = decompress_line(&bytes_decoded);
1480
if (res < 0)
1481
return terminate(res);
1482
1483
if (res == FALSE)
1484
return terminate(PNG_TOO_MUCH_DATA);
1485
1486
if (bytes_decoded)
1487
return terminate(PNG_TOO_MUCH_DATA);
1488
}
1489
}
1490
1491
return 0;
1492
}
1493
1494
void png_decoder::png_decode_end()
1495
{
1496
uninitialize();
1497
}
1498
1499
int png_decoder::png_decode_start()
1500
{
1501
int status;
1502
1503
if (m_img_supported_flag != TRUE)
1504
return terminate(m_img_supported_flag);
1505
1506
switch (m_ihdr.m_color_type)
1507
{
1508
case PNG_COLOR_TYPE_GREYSCALE:
1509
{
1510
if (m_ihdr.m_bit_depth == 16)
1511
{
1512
// This is a special case. We can't pass back 8-bit samples and let the caller decide on transparency because the PNG is 16-bits.
1513
// So we expand to 8-bit Gray-Alpha and handle transparency during decoding.
1514
// We don't do this with all grayscale cases because that would require more code to deal with 1/2/4bpp expansion.
1515
m_dec_bytes_per_pixel = (m_ihdr.m_bit_depth + 7) / 8;
1516
m_dst_bytes_per_pixel = 2;
1517
1518
m_src_bytes_per_line = (((uint32_t)m_ihdr.m_width * m_ihdr.m_bit_depth) + 7) / 8;
1519
m_dst_bytes_per_line = 2 * m_ihdr.m_width;
1520
1521
m_pProcess_func = unpack_grey_16_2;
1522
}
1523
else
1524
{
1525
m_dec_bytes_per_pixel = (m_ihdr.m_bit_depth + 7) / 8;
1526
m_dst_bytes_per_pixel = 1;
1527
1528
m_src_bytes_per_line = (((uint32_t)m_ihdr.m_width * m_ihdr.m_bit_depth) + 7) / 8;
1529
m_dst_bytes_per_line = m_ihdr.m_width;
1530
1531
if (m_ihdr.m_bit_depth == 1)
1532
m_pProcess_func = unpack_grey_1;
1533
else if (m_ihdr.m_bit_depth == 2)
1534
m_pProcess_func = unpack_grey_2;
1535
else if (m_ihdr.m_bit_depth == 4)
1536
m_pProcess_func = unpack_grey_4;
1537
else
1538
m_pProcess_func = unpack_grey_8;
1539
}
1540
1541
break;
1542
}
1543
case PNG_COLOR_TYPE_PALETTIZED:
1544
{
1545
m_dec_bytes_per_pixel = (m_ihdr.m_bit_depth + 7) / 8;
1546
m_dst_bytes_per_pixel = 1;
1547
1548
m_src_bytes_per_line = (((uint32_t)m_ihdr.m_width * m_ihdr.m_bit_depth) + 7) / 8;
1549
m_dst_bytes_per_line = m_ihdr.m_width;
1550
1551
if (m_ihdr.m_bit_depth == 1)
1552
m_pProcess_func = unpack_grey_1;
1553
else if (m_ihdr.m_bit_depth == 2)
1554
m_pProcess_func = unpack_grey_2;
1555
else if (m_ihdr.m_bit_depth == 4)
1556
m_pProcess_func = unpack_grey_4;
1557
else if (m_ihdr.m_bit_depth == 8)
1558
m_pProcess_func = unpack_grey_8;
1559
else if (m_ihdr.m_bit_depth == 16)
1560
m_pProcess_func = unpack_grey_16;
1561
1562
break;
1563
}
1564
case PNG_COLOR_TYPE_TRUECOLOR:
1565
{
1566
// We always pass back alpha with transparency handling.
1567
m_dec_bytes_per_pixel = 3 * (m_ihdr.m_bit_depth / 8);
1568
m_dst_bytes_per_pixel = 4;
1569
1570
m_src_bytes_per_line = ((uint32_t)m_ihdr.m_width * m_dec_bytes_per_pixel);
1571
m_dst_bytes_per_line = 4 * m_ihdr.m_width;
1572
1573
if (m_ihdr.m_bit_depth == 8)
1574
m_pProcess_func = unpack_true_8;
1575
else if (m_ihdr.m_bit_depth == 16)
1576
m_pProcess_func = unpack_true_16;
1577
1578
break;
1579
}
1580
case PNG_COLOR_TYPE_GREYSCALE_ALPHA:
1581
{
1582
m_dec_bytes_per_pixel = 2 * (m_ihdr.m_bit_depth / 8);
1583
m_dst_bytes_per_pixel = 2;
1584
1585
m_src_bytes_per_line = ((uint32_t)m_ihdr.m_width * m_dec_bytes_per_pixel);
1586
m_dst_bytes_per_line = m_ihdr.m_width * 2;
1587
1588
if (m_ihdr.m_bit_depth == 8)
1589
m_pProcess_func = unpack_grey_alpha_8;
1590
else if (m_ihdr.m_bit_depth == 16)
1591
m_pProcess_func = unpack_grey_alpha_16;
1592
1593
break;
1594
}
1595
case PNG_COLOR_TYPE_TRUECOLOR_ALPHA:
1596
{
1597
m_dec_bytes_per_pixel = 4 * (m_ihdr.m_bit_depth / 8);
1598
m_dst_bytes_per_pixel = 4;
1599
1600
m_src_bytes_per_line = ((uint32_t)m_ihdr.m_width * m_dec_bytes_per_pixel);
1601
m_dst_bytes_per_line = 4 * m_ihdr.m_width;
1602
1603
if (m_ihdr.m_bit_depth == 8)
1604
m_pProcess_func = unpack_true_alpha_8;
1605
else
1606
m_pProcess_func = unpack_true_alpha_16;
1607
1608
break;
1609
}
1610
}
1611
1612
m_dec_bytes_per_line = m_src_bytes_per_line + 1;
1613
1614
m_pPre_line_buf = (uint8_t*)png_calloc(m_src_bytes_per_line);
1615
m_pCur_line_buf = (uint8_t*)png_calloc(m_dec_bytes_per_line);
1616
m_pPro_line_buf = (uint8_t*)png_calloc(m_dst_bytes_per_line);
1617
1618
if (!m_pPre_line_buf || !m_pCur_line_buf || !m_pPro_line_buf)
1619
return terminate(PNG_NOTENOUGHMEM);
1620
1621
m_inflate_src_buf_ofs = PNG_INFLATE_SRC_BUF_SIZE;
1622
1623
int res = mz_inflateInit(&m_inflator);
1624
if (res != 0)
1625
return terminate(PNG_DECERROR);
1626
1627
if (m_ihdr.m_ilace_type == 1)
1628
{
1629
//int i;
1630
//uint32_t total_lines, lines_processed;
1631
1632
m_adam7_pass_size_x[0] = adam7_pass_size(m_ihdr.m_width, 0, 8);
1633
m_adam7_pass_size_x[1] = adam7_pass_size(m_ihdr.m_width, 4, 8);
1634
m_adam7_pass_size_x[2] = adam7_pass_size(m_ihdr.m_width, 0, 4);
1635
m_adam7_pass_size_x[3] = adam7_pass_size(m_ihdr.m_width, 2, 4);
1636
m_adam7_pass_size_x[4] = adam7_pass_size(m_ihdr.m_width, 0, 2);
1637
m_adam7_pass_size_x[5] = adam7_pass_size(m_ihdr.m_width, 1, 2);
1638
m_adam7_pass_size_x[6] = adam7_pass_size(m_ihdr.m_width, 0, 1);
1639
1640
m_adam7_pass_size_y[0] = adam7_pass_size(m_ihdr.m_height, 0, 8);
1641
m_adam7_pass_size_y[1] = adam7_pass_size(m_ihdr.m_height, 0, 8);
1642
m_adam7_pass_size_y[2] = adam7_pass_size(m_ihdr.m_height, 4, 8);
1643
m_adam7_pass_size_y[3] = adam7_pass_size(m_ihdr.m_height, 0, 4);
1644
m_adam7_pass_size_y[4] = adam7_pass_size(m_ihdr.m_height, 2, 4);
1645
m_adam7_pass_size_y[5] = adam7_pass_size(m_ihdr.m_height, 0, 2);
1646
m_adam7_pass_size_y[6] = adam7_pass_size(m_ihdr.m_height, 1, 2);
1647
1648
m_adam7_image_buf.resize(m_dst_bytes_per_line * m_ihdr.m_height);
1649
1650
m_adam7_pass_num = -1;
1651
1652
m_pass_y_left = 0;
1653
1654
#if 0
1655
total_lines = lines_processed = 0;
1656
1657
for (i = 0; i < 7; i++)
1658
total_lines += m_adam7_pass_size_y[i];
1659
#endif
1660
1661
for (; ; )
1662
{
1663
void* dummy_ptr = nullptr;
1664
uint32_t dummy_len = 0;
1665
1666
status = png_decode(&dummy_ptr, &dummy_len);
1667
1668
if (status)
1669
{
1670
if (status == PNG_ALLDONE)
1671
break;
1672
else
1673
{
1674
uninitialize();
1675
1676
return status;
1677
}
1678
}
1679
1680
//lines_processed++;
1681
}
1682
1683
m_adam7_decoded_flag = TRUE;
1684
m_pass_y_left = m_ihdr.m_height;
1685
}
1686
else
1687
{
1688
m_pass_x_size = m_ihdr.m_width;
1689
m_pass_y_left = m_ihdr.m_height;
1690
}
1691
1692
return 0;
1693
}
1694
1695
void png_decoder::calc_gamma_table()
1696
{
1697
if (m_gama_value == 45000)
1698
{
1699
for (int i = 0; i < 256; i++)
1700
m_gamma_table[i] = (uint8_t)i;
1701
return;
1702
}
1703
1704
float gamma = (float)(m_gama_value) / 100000.0f;
1705
1706
gamma = 1.0f / (gamma * 2.2f);
1707
1708
for (int i = 0; i < 256; i++)
1709
{
1710
float temp = powf((float)(i) / 255.0f, gamma) * 255.0f;
1711
1712
int j = (int)(temp + .5f);
1713
1714
if (j < 0)
1715
j = 0;
1716
else if (j > 255)
1717
j = 255;
1718
1719
m_gamma_table[i] = (uint8_t)j;
1720
}
1721
}
1722
1723
void png_decoder::create_grey_palette()
1724
{
1725
int i, j;
1726
uint8_t* p = m_img_pal;
1727
1728
const int img_colors = minimum(256, 1 << m_ihdr.m_bit_depth);
1729
for (i = 0; i < img_colors; i++)
1730
{
1731
j = ((uint32_t)255 * (uint32_t)i) / (img_colors - 1);
1732
1733
*p++ = (uint8_t)j;
1734
*p++ = (uint8_t)j;
1735
*p++ = (uint8_t)j;
1736
}
1737
}
1738
1739
int png_decoder::read_signature()
1740
{
1741
if (m_pFile->read(m_temp_buf, 8) != 8)
1742
return terminate(PNG_UNKNOWNTYPE);
1743
1744
if ((m_temp_buf[0] != 137) ||
1745
(m_temp_buf[1] != 80) ||
1746
(m_temp_buf[2] != 78) ||
1747
(m_temp_buf[3] != 71) ||
1748
(m_temp_buf[4] != 13) ||
1749
(m_temp_buf[5] != 10) ||
1750
(m_temp_buf[6] != 26) ||
1751
(m_temp_buf[7] != 10))
1752
{
1753
return terminate(PNG_UNKNOWNTYPE);
1754
}
1755
1756
return 0;
1757
}
1758
1759
int png_decoder::read_ihdr_chunk()
1760
{
1761
int res = fetch_next_chunk_init();
1762
if (res < 0)
1763
return res;
1764
1765
if ((m_chunk_name[0] != 'I') || (m_chunk_name[1] != 'H') || (m_chunk_name[2] != 'D') || (m_chunk_name[3] != 'R') || (m_chunk_size != 13))
1766
return terminate(PNG_NO_IHDR);
1767
1768
int64_t v64 = fetch_next_chunk_dword();
1769
if (v64 < 0)
1770
return (int)v64;
1771
m_ihdr.m_width = (uint32_t)v64;
1772
1773
v64 = fetch_next_chunk_dword();
1774
if (v64 < 0)
1775
return (int)v64;
1776
m_ihdr.m_height = (uint32_t)v64;
1777
1778
if ((m_ihdr.m_width == 0) || (m_ihdr.m_width > MAX_SUPPORTED_RES))
1779
return terminate(PNG_BAD_WIDTH);
1780
1781
if ((m_ihdr.m_height == 0) || (m_ihdr.m_height > MAX_SUPPORTED_RES))
1782
return terminate(PNG_BAD_HEIGHT);
1783
1784
int v = fetch_next_chunk_byte();
1785
if (v < 0)
1786
return v;
1787
m_ihdr.m_bit_depth = (uint8_t)v;
1788
1789
v = fetch_next_chunk_byte();
1790
if (v < 0)
1791
return v;
1792
m_ihdr.m_color_type = (uint8_t)v;
1793
1794
v = fetch_next_chunk_byte();
1795
if (v < 0)
1796
return v;
1797
m_ihdr.m_comp_type = (uint8_t)v;
1798
1799
v = fetch_next_chunk_byte();
1800
if (v < 0)
1801
return v;
1802
m_ihdr.m_filter_type = (uint8_t)v;
1803
1804
v = fetch_next_chunk_byte();
1805
if (v < 0)
1806
return v;
1807
m_ihdr.m_ilace_type = (uint8_t)v;
1808
1809
if (m_ihdr.m_comp_type != 0)
1810
m_img_supported_flag = PNG_UNS_COMPRESSION;
1811
1812
if (m_ihdr.m_filter_type != 0)
1813
m_img_supported_flag = PNG_UNS_FILTER;
1814
1815
if (m_ihdr.m_ilace_type > 1)
1816
m_img_supported_flag = PNG_UNS_ILACE;
1817
1818
switch (m_ihdr.m_color_type)
1819
{
1820
case PNG_COLOR_TYPE_GREYSCALE:
1821
{
1822
switch (m_ihdr.m_bit_depth)
1823
{
1824
case 1:
1825
case 2:
1826
case 4:
1827
case 8:
1828
case 16:
1829
{
1830
break;
1831
}
1832
default:
1833
return terminate(PNG_BAD_BIT_DEPTH);
1834
}
1835
1836
break;
1837
}
1838
case PNG_COLOR_TYPE_PALETTIZED:
1839
{
1840
switch (m_ihdr.m_bit_depth)
1841
{
1842
case 1:
1843
case 2:
1844
case 4:
1845
case 8:
1846
{
1847
break;
1848
}
1849
default:
1850
return terminate(PNG_BAD_BIT_DEPTH);
1851
}
1852
1853
break;
1854
}
1855
case PNG_COLOR_TYPE_TRUECOLOR:
1856
case PNG_COLOR_TYPE_GREYSCALE_ALPHA:
1857
case PNG_COLOR_TYPE_TRUECOLOR_ALPHA:
1858
{
1859
switch (m_ihdr.m_bit_depth)
1860
{
1861
case 8:
1862
case 16:
1863
{
1864
break;
1865
}
1866
default:
1867
return terminate(PNG_BAD_BIT_DEPTH);
1868
}
1869
1870
break;
1871
}
1872
default:
1873
return terminate(PNG_UNS_COLOR_TYPE);
1874
}
1875
1876
return 0;
1877
}
1878
1879
int png_decoder::read_bkgd_chunk()
1880
{
1881
m_bkgd_flag = TRUE;
1882
1883
if (m_ihdr.m_color_type == PNG_COLOR_TYPE_PALETTIZED)
1884
{
1885
int v = fetch_next_chunk_byte();
1886
if (v < 0)
1887
return v;
1888
m_bkgd_value[0] = v;
1889
}
1890
else if ((m_ihdr.m_color_type == PNG_COLOR_TYPE_GREYSCALE) || (m_ihdr.m_color_type == PNG_COLOR_TYPE_GREYSCALE_ALPHA))
1891
{
1892
int v = fetch_next_chunk_word();
1893
if (v < 0)
1894
return v;
1895
m_bkgd_value[0] = v;
1896
}
1897
else if ((m_ihdr.m_color_type == PNG_COLOR_TYPE_TRUECOLOR) || (m_ihdr.m_color_type == PNG_COLOR_TYPE_TRUECOLOR_ALPHA))
1898
{
1899
int v = fetch_next_chunk_word();
1900
if (v < 0)
1901
return v;
1902
m_bkgd_value[0] = v;
1903
1904
v = fetch_next_chunk_word();
1905
if (v < 0)
1906
return v;
1907
m_bkgd_value[1] = v;
1908
1909
v = fetch_next_chunk_word();
1910
if (v < 0)
1911
return v;
1912
m_bkgd_value[2] = v;
1913
}
1914
1915
return 0;
1916
}
1917
1918
int png_decoder::read_gama_chunk()
1919
{
1920
m_gama_flag = TRUE;
1921
1922
int64_t v = fetch_next_chunk_dword();
1923
if (v < 0)
1924
return (int)v;
1925
1926
m_gama_value = (uint32_t)v;
1927
1928
return 0;
1929
}
1930
1931
int png_decoder::read_trns_chunk()
1932
{
1933
int i;
1934
1935
m_trns_flag = TRUE;
1936
1937
if (m_ihdr.m_color_type == PNG_COLOR_TYPE_PALETTIZED)
1938
{
1939
for (i = 0; i < 256; i++)
1940
m_trns_value[i] = 255;
1941
1942
const uint32_t img_colors = 1 << m_ihdr.m_bit_depth;
1943
if (m_chunk_size > (uint32_t)img_colors)
1944
return terminate(PNG_BAD_TRNS_CHUNK);
1945
1946
for (i = 0; i < (int)m_chunk_size; i++)
1947
{
1948
int v = fetch_next_chunk_byte();
1949
if (v < 0)
1950
return v;
1951
m_trns_value[i] = v;
1952
}
1953
}
1954
else if (m_ihdr.m_color_type == PNG_COLOR_TYPE_GREYSCALE)
1955
{
1956
int v = fetch_next_chunk_word();
1957
if (v < 0)
1958
return v;
1959
m_trns_value[0] = v;
1960
}
1961
else if (m_ihdr.m_color_type == PNG_COLOR_TYPE_TRUECOLOR)
1962
{
1963
int v = fetch_next_chunk_word();
1964
if (v < 0)
1965
return v;
1966
m_trns_value[0] = v;
1967
1968
v = fetch_next_chunk_word();
1969
if (v < 0)
1970
return v;
1971
m_trns_value[1] = v;
1972
1973
v = fetch_next_chunk_word();
1974
if (v < 0)
1975
return v;
1976
m_trns_value[2] = v;
1977
}
1978
else
1979
{
1980
return terminate(PNG_BAD_TRNS_CHUNK);
1981
}
1982
return 0;
1983
}
1984
1985
int png_decoder::read_plte_chunk()
1986
{
1987
int i, j;
1988
uint8_t* p;
1989
1990
if (m_plte_flag)
1991
return terminate(PNG_BAD_PLTE_CHUNK);
1992
1993
m_plte_flag = TRUE;
1994
1995
memset(m_img_pal, 0, 768);
1996
1997
if (m_chunk_size % 3)
1998
return terminate(PNG_BAD_PLTE_CHUNK);
1999
2000
j = m_chunk_size / 3;
2001
2002
const int img_colors = minimum(256, 1 << m_ihdr.m_bit_depth);
2003
if (j > img_colors)
2004
return terminate(PNG_BAD_PLTE_CHUNK);
2005
2006
if ((m_ihdr.m_color_type == PNG_COLOR_TYPE_GREYSCALE) ||
2007
(m_ihdr.m_color_type == PNG_COLOR_TYPE_GREYSCALE_ALPHA))
2008
return terminate(PNG_BAD_PLTE_CHUNK);
2009
2010
p = m_img_pal;
2011
2012
for (i = 0; i < j; i++)
2013
{
2014
int v = fetch_next_chunk_byte();
2015
if (v < 0)
2016
return v;
2017
*p++ = (uint8_t)v;
2018
2019
v = fetch_next_chunk_byte();
2020
if (v < 0)
2021
return v;
2022
*p++ = (uint8_t)v;
2023
2024
v = fetch_next_chunk_byte();
2025
if (v < 0)
2026
return v;
2027
*p++ = (uint8_t)v;
2028
}
2029
2030
return 0;
2031
}
2032
2033
int png_decoder::find_idat_chunk()
2034
{
2035
for (; ; )
2036
{
2037
int res = fetch_next_chunk_init();
2038
if (res < 0)
2039
return res;
2040
2041
if (m_chunk_name[0] & 32) /* ancillary? */
2042
{
2043
if ((m_chunk_name[0] == 'b') && (m_chunk_name[1] == 'K') && (m_chunk_name[2] == 'G') && (m_chunk_name[3] == 'D'))
2044
{
2045
res = read_bkgd_chunk();
2046
if (res < 0)
2047
return res;
2048
}
2049
else if ((m_chunk_name[0] == 'g') && (m_chunk_name[1] == 'A') && (m_chunk_name[2] == 'M') && (m_chunk_name[3] == 'A'))
2050
{
2051
res = read_gama_chunk();
2052
if (res < 0)
2053
return res;
2054
}
2055
else if ((m_chunk_name[0] == 't') && (m_chunk_name[1] == 'R') && (m_chunk_name[2] == 'N') && (m_chunk_name[3] == 'S'))
2056
{
2057
res = read_trns_chunk();
2058
if (res < 0)
2059
return res;
2060
}
2061
}
2062
else
2063
{
2064
if ((m_chunk_name[0] == 'P') && (m_chunk_name[1] == 'L') && (m_chunk_name[2] == 'T') && (m_chunk_name[3] == 'E'))
2065
{
2066
res = read_plte_chunk();
2067
if (res < 0)
2068
return res;
2069
}
2070
else if ((m_chunk_name[0] == 'I') && (m_chunk_name[1] == 'D') && (m_chunk_name[2] == 'A') && (m_chunk_name[3] == 'T'))
2071
{
2072
break;
2073
}
2074
else
2075
{
2076
m_img_supported_flag = PNG_UNS_CRITICAL_CHUNK;
2077
}
2078
}
2079
}
2080
2081
return 0;
2082
}
2083
2084
png_decoder::png_decoder()
2085
{
2086
clear();
2087
}
2088
2089
png_decoder::~png_decoder()
2090
{
2091
uninitialize();
2092
}
2093
2094
void png_decoder::clear()
2095
{
2096
clear_obj(m_pMalloc_blocks);
2097
2098
m_pFile = nullptr;
2099
2100
clear_obj(m_img_pal);
2101
2102
m_img_supported_flag = FALSE;
2103
2104
m_adam7_image_buf.clear();
2105
2106
clear_obj(m_ihdr);
2107
2108
m_chunk_flag = FALSE;
2109
m_chunk_size = 0;
2110
m_chunk_left = 0;
2111
m_chunk_crc32 = 0;
2112
clear_obj(m_chunk_name);
2113
2114
m_end_of_idat_chunks = 0;
2115
2116
m_dec_bytes_per_pixel = 0;
2117
m_dst_bytes_per_pixel = 0;
2118
2119
m_dec_bytes_per_line = 0;
2120
m_src_bytes_per_line = 0;
2121
m_dst_bytes_per_line = 0;
2122
2123
m_pProcess_func = nullptr;
2124
2125
m_pPre_line_buf = nullptr;
2126
m_pCur_line_buf = nullptr;
2127
m_pPro_line_buf = nullptr;
2128
2129
m_bkgd_flag = FALSE;
2130
clear_obj(m_bkgd_value);
2131
2132
m_gama_flag = FALSE;
2133
m_gama_value = 0;
2134
2135
m_plte_flag = FALSE;
2136
2137
m_trns_flag = FALSE;
2138
clear_obj(m_trns_value);
2139
2140
clear_obj(m_inflator);
2141
2142
m_inflate_src_buf_ofs = 0;
2143
m_inflate_src_buf_size = 0;
2144
m_inflate_dst_buf_ofs = 0;
2145
2146
m_inflate_eof_flag = FALSE;
2147
2148
clear_obj(m_trns_value);
2149
2150
m_pass_x_size = 0;
2151
m_pass_y_left = 0;
2152
2153
m_adam7_pass_num = 0;
2154
m_adam7_pass_y = 0;
2155
clear_obj(m_adam7_pass_size_x);
2156
clear_obj(m_adam7_pass_size_y);
2157
2158
m_adam7_decoded_flag = FALSE;
2159
2160
m_scanned_flag = false;
2161
2162
m_terminate_status = 0;
2163
}
2164
2165
int png_decoder::png_scan(png_file *pFile)
2166
{
2167
m_pFile = pFile;
2168
2169
m_img_supported_flag = TRUE;
2170
m_terminate_status = 0;
2171
2172
int res = read_signature();
2173
if (res != 0)
2174
return res;
2175
2176
res = read_ihdr_chunk();
2177
if (res != 0)
2178
return res;
2179
2180
res = find_idat_chunk();
2181
if (res != 0)
2182
return res;
2183
2184
if (m_gama_flag)
2185
calc_gamma_table();
2186
2187
if (m_ihdr.m_color_type == PNG_COLOR_TYPE_PALETTIZED)
2188
{
2189
if (!m_plte_flag)
2190
return terminate(PNG_MISSING_PALETTE);
2191
}
2192
else if ((m_ihdr.m_color_type == PNG_COLOR_TYPE_GREYSCALE) || (m_ihdr.m_color_type == PNG_COLOR_TYPE_GREYSCALE_ALPHA))
2193
{
2194
create_grey_palette();
2195
}
2196
2197
m_scanned_flag = true;
2198
2199
return 0;
2200
}
2201
2202
static inline uint8_t get_709_luma(uint32_t r, uint32_t g, uint32_t b)
2203
{
2204
return (uint8_t)((13938U * r + 46869U * g + 4729U * b + 32768U) >> 16U);
2205
}
2206
2207
bool get_png_info(const void* pImage_buf, size_t buf_size, png_info &info)
2208
{
2209
memset(&info, 0, sizeof(info));
2210
2211
if ((!pImage_buf) || (buf_size < MIN_PNG_SIZE))
2212
return false;
2213
2214
png_readonly_memory_file mf;
2215
mf.init(pImage_buf, buf_size);
2216
2217
png_decoder dec;
2218
2219
int status = dec.png_scan(&mf);
2220
if ((status != 0) || (dec.m_img_supported_flag != TRUE))
2221
return false;
2222
2223
info.m_width = dec.m_ihdr.m_width;
2224
info.m_height = dec.m_ihdr.m_height;
2225
info.m_bit_depth = dec.m_ihdr.m_bit_depth;
2226
info.m_color_type = dec.m_ihdr.m_color_type;
2227
info.m_has_gamma = dec.m_gama_flag != 0;
2228
info.m_gamma_value = dec.m_gama_value;
2229
info.m_has_trns = dec.m_trns_flag != 0;
2230
2231
switch (dec.m_ihdr.m_color_type)
2232
{
2233
case PNG_COLOR_TYPE_GREYSCALE:
2234
info.m_num_chans = dec.m_trns_flag ? 2 : 1;
2235
break;
2236
case PNG_COLOR_TYPE_GREYSCALE_ALPHA:
2237
info.m_num_chans = 2;
2238
break;
2239
case PNG_COLOR_TYPE_PALETTIZED:
2240
case PNG_COLOR_TYPE_TRUECOLOR:
2241
info.m_num_chans = dec.m_trns_flag ? 4 : 3;
2242
break;
2243
case PNG_COLOR_TYPE_TRUECOLOR_ALPHA:
2244
info.m_num_chans = 4;
2245
break;
2246
default:
2247
assert(0);
2248
break;
2249
}
2250
2251
return true;
2252
}
2253
2254
void* load_png(const void* pImage_buf, size_t buf_size, uint32_t desired_chans, uint32_t& width, uint32_t& height, uint32_t& num_chans)
2255
{
2256
width = 0;
2257
height = 0;
2258
num_chans = 0;
2259
2260
if ((!pImage_buf) || (buf_size < MIN_PNG_SIZE))
2261
{
2262
assert(0);
2263
return nullptr;
2264
}
2265
2266
if (desired_chans > 4)
2267
{
2268
assert(0);
2269
return nullptr;
2270
}
2271
2272
png_readonly_memory_file mf;
2273
mf.init(pImage_buf, buf_size);
2274
2275
png_decoder dec;
2276
2277
int status = dec.png_scan(&mf);
2278
if ((status != 0) || (dec.m_img_supported_flag != TRUE))
2279
return nullptr;
2280
2281
uint32_t colortype = dec.m_ihdr.m_color_type;
2282
switch (colortype)
2283
{
2284
case PNG_COLOR_TYPE_GREYSCALE:
2285
num_chans = dec.m_trns_flag ? 2 : 1;
2286
break;
2287
case PNG_COLOR_TYPE_GREYSCALE_ALPHA:
2288
num_chans = 2;
2289
break;
2290
case PNG_COLOR_TYPE_PALETTIZED:
2291
case PNG_COLOR_TYPE_TRUECOLOR:
2292
num_chans = dec.m_trns_flag ? 4 : 3;
2293
break;
2294
case PNG_COLOR_TYPE_TRUECOLOR_ALPHA:
2295
num_chans = 4;
2296
break;
2297
default:
2298
assert(0);
2299
break;
2300
}
2301
2302
if (!desired_chans)
2303
desired_chans = num_chans;
2304
2305
#if 0
2306
printf("lode_png: %ux%u bitdepth: %u colortype: %u trns: %u ilace: %u\n",
2307
dec.m_ihdr.m_width,
2308
dec.m_ihdr.m_height,
2309
dec.m_ihdr.m_bit_depth,
2310
dec.m_ihdr.m_color_type,
2311
dec.m_trns_flag,
2312
dec.m_ihdr.m_ilace_type);
2313
#endif
2314
2315
width = dec.m_ihdr.m_width;
2316
height = dec.m_ihdr.m_height;
2317
uint32_t bitdepth = dec.m_ihdr.m_bit_depth;
2318
uint32_t pitch = width * desired_chans;
2319
2320
uint64_t total_size = (uint64_t)pitch * height;
2321
if (total_size > 0x7FFFFFFFULL)
2322
return nullptr;
2323
2324
uint8_t* pBuf = (uint8_t*)malloc((size_t)total_size);
2325
if (!pBuf)
2326
return nullptr;
2327
2328
if (dec.png_decode_start() != 0)
2329
{
2330
free(pBuf);
2331
return nullptr;
2332
}
2333
2334
uint8_t* pDst = pBuf;
2335
2336
for (uint32_t y = 0; y < height; y++, pDst += pitch)
2337
{
2338
uint8_t* pLine;
2339
uint32_t line_bytes;
2340
if (dec.png_decode((void**)&pLine, &line_bytes) != 0)
2341
{
2342
free(pBuf);
2343
return nullptr;
2344
}
2345
2346
// This conversion matrix handles converting RGB->Luma, converting grayscale samples to 8-bit samples, converting palettized images, and PNG transparency.
2347
switch (colortype)
2348
{
2349
case PNG_COLOR_TYPE_GREYSCALE:
2350
{
2351
uint32_t trans_value = dec.m_trns_value[0];
2352
2353
switch (desired_chans)
2354
{
2355
case 1:
2356
if (bitdepth == 16)
2357
{
2358
assert(line_bytes == width * 2);
2359
2360
for (uint32_t i = 0; i < width; i++)
2361
pDst[i] = dec.m_img_pal[pLine[i * 2 + 0] * 3];
2362
}
2363
else if (bitdepth == 8)
2364
{
2365
assert(line_bytes == width);
2366
memcpy(pDst, pLine, pitch);
2367
}
2368
else
2369
{
2370
assert(line_bytes == width);
2371
for (uint32_t i = 0; i < width; i++)
2372
pDst[i] = dec.m_img_pal[pLine[i] * 3];
2373
}
2374
break;
2375
case 2:
2376
if (bitdepth == 16)
2377
{
2378
assert(line_bytes == width * 2);
2379
for (uint32_t i = 0; i < width; i++)
2380
{
2381
pDst[i * 2 + 0] = dec.m_img_pal[pLine[i * 2 + 0] * 3];
2382
pDst[i * 2 + 1] = pLine[i * 2 + 1];
2383
}
2384
}
2385
else if (dec.m_trns_flag)
2386
{
2387
assert(line_bytes == width);
2388
for (uint32_t i = 0; i < width; i++)
2389
{
2390
pDst[i * 2 + 0] = dec.m_img_pal[pLine[i] * 3];
2391
pDst[i * 2 + 1] = (pLine[i] == trans_value) ? 0 : 255;
2392
}
2393
}
2394
else
2395
{
2396
assert(line_bytes == width);
2397
for (uint32_t i = 0; i < width; i++)
2398
{
2399
pDst[i * 2 + 0] = dec.m_img_pal[pLine[i] * 3];
2400
pDst[i * 2 + 1] = 255;
2401
}
2402
}
2403
break;
2404
case 3:
2405
if (bitdepth == 16)
2406
{
2407
assert(line_bytes == width * 2);
2408
for (uint32_t i = 0; i < width; i++)
2409
{
2410
uint8_t c = dec.m_img_pal[pLine[i * 2 + 0] * 3];
2411
pDst[i * 3 + 0] = c;
2412
pDst[i * 3 + 1] = c;
2413
pDst[i * 3 + 2] = c;
2414
}
2415
}
2416
else
2417
{
2418
assert(line_bytes == width);
2419
for (uint32_t i = 0; i < width; i++)
2420
{
2421
uint8_t c = dec.m_img_pal[pLine[i] * 3];
2422
pDst[i * 3 + 0] = c;
2423
pDst[i * 3 + 1] = c;
2424
pDst[i * 3 + 2] = c;
2425
}
2426
}
2427
break;
2428
case 4:
2429
if (bitdepth == 16)
2430
{
2431
assert(line_bytes == width * 2);
2432
for (uint32_t i = 0; i < width; i++)
2433
{
2434
uint8_t c = dec.m_img_pal[pLine[i * 2 + 0] * 3];
2435
pDst[i * 4 + 0] = c;
2436
pDst[i * 4 + 1] = c;
2437
pDst[i * 4 + 2] = c;
2438
pDst[i * 4 + 3] = pLine[i * 2 + 1];
2439
}
2440
}
2441
else if (dec.m_trns_flag)
2442
{
2443
assert(line_bytes == width);
2444
for (uint32_t i = 0; i < width; i++)
2445
{
2446
uint8_t c = dec.m_img_pal[pLine[i] * 3];
2447
pDst[i * 4 + 0] = c;
2448
pDst[i * 4 + 1] = c;
2449
pDst[i * 4 + 2] = c;
2450
pDst[i * 4 + 3] = (pLine[i] == trans_value) ? 0 : 255;
2451
}
2452
}
2453
else
2454
{
2455
assert(line_bytes == width);
2456
for (uint32_t i = 0; i < width; i++)
2457
{
2458
uint8_t c = dec.m_img_pal[pLine[i] * 3];
2459
pDst[i * 4 + 0] = c;
2460
pDst[i * 4 + 1] = c;
2461
pDst[i * 4 + 2] = c;
2462
pDst[i * 4 + 3] = 255;
2463
}
2464
}
2465
break;
2466
}
2467
2468
break;
2469
}
2470
case PNG_COLOR_TYPE_GREYSCALE_ALPHA:
2471
{
2472
assert(line_bytes == width * 2);
2473
2474
switch (desired_chans)
2475
{
2476
case 1:
2477
for (uint32_t i = 0; i < width; i++)
2478
pDst[i] = dec.m_img_pal[pLine[i * 2 + 0] * 3];
2479
break;
2480
case 2:
2481
assert(line_bytes == pitch);
2482
if (bitdepth >= 8)
2483
memcpy(pDst, pLine, pitch);
2484
else
2485
{
2486
for (uint32_t i = 0; i < width; i++)
2487
{
2488
pDst[i * 2 + 0] = dec.m_img_pal[pLine[i * 2 + 0] * 3];
2489
pDst[i * 2 + 1] = pLine[i * 2 + 1];
2490
}
2491
}
2492
break;
2493
case 3:
2494
for (uint32_t i = 0; i < width; i++)
2495
{
2496
uint8_t c = dec.m_img_pal[pLine[i * 2 + 0] * 3];
2497
pDst[i * 3 + 0] = c;
2498
pDst[i * 3 + 1] = c;
2499
pDst[i * 3 + 2] = c;
2500
}
2501
break;
2502
case 4:
2503
for (uint32_t i = 0; i < width; i++)
2504
{
2505
uint8_t c = dec.m_img_pal[pLine[i * 2 + 0] * 3];
2506
pDst[i * 4 + 0] = c;
2507
pDst[i * 4 + 1] = c;
2508
pDst[i * 4 + 2] = c;
2509
pDst[i * 4 + 3] = pLine[i * 2 + 1];
2510
}
2511
break;
2512
}
2513
2514
break;
2515
}
2516
case PNG_COLOR_TYPE_PALETTIZED:
2517
{
2518
assert(line_bytes == width);
2519
2520
switch (desired_chans)
2521
{
2522
case 1:
2523
for (uint32_t i = 0; i < width; i++)
2524
{
2525
const uint8_t* p = &dec.m_img_pal[pLine[i] * 3];
2526
pDst[i] = get_709_luma(p[0], p[1], p[2]);
2527
}
2528
break;
2529
case 2:
2530
if (dec.m_trns_flag)
2531
{
2532
for (uint32_t i = 0; i < width; i++)
2533
{
2534
const uint8_t* p = &dec.m_img_pal[pLine[i] * 3];
2535
pDst[i * 2 + 0] = get_709_luma(p[0], p[1], p[2]);
2536
pDst[i * 2 + 1] = (uint8_t)dec.m_trns_value[pLine[i]];
2537
}
2538
}
2539
else
2540
{
2541
for (uint32_t i = 0; i < width; i++)
2542
{
2543
const uint8_t* p = &dec.m_img_pal[pLine[i] * 3];
2544
pDst[i * 2 + 0] = get_709_luma(p[0], p[1], p[2]);
2545
pDst[i * 2 + 1] = 255;
2546
}
2547
}
2548
break;
2549
case 3:
2550
for (uint32_t i = 0; i < width; i++)
2551
{
2552
const uint8_t* p = &dec.m_img_pal[pLine[i] * 3];
2553
pDst[i * 3 + 0] = p[0];
2554
pDst[i * 3 + 1] = p[1];
2555
pDst[i * 3 + 2] = p[2];
2556
}
2557
break;
2558
case 4:
2559
if (dec.m_trns_flag)
2560
{
2561
for (uint32_t i = 0; i < width; i++)
2562
{
2563
const uint8_t* p = &dec.m_img_pal[pLine[i] * 3];
2564
pDst[i * 4 + 0] = p[0];
2565
pDst[i * 4 + 1] = p[1];
2566
pDst[i * 4 + 2] = p[2];
2567
pDst[i * 4 + 3] = (uint8_t)dec.m_trns_value[pLine[i]];
2568
}
2569
}
2570
else
2571
{
2572
for (uint32_t i = 0; i < width; i++)
2573
{
2574
const uint8_t* p = &dec.m_img_pal[pLine[i] * 3];
2575
pDst[i * 4 + 0] = p[0];
2576
pDst[i * 4 + 1] = p[1];
2577
pDst[i * 4 + 2] = p[2];
2578
pDst[i * 4 + 3] = 255;
2579
}
2580
}
2581
break;
2582
}
2583
2584
break;
2585
}
2586
case PNG_COLOR_TYPE_TRUECOLOR:
2587
case PNG_COLOR_TYPE_TRUECOLOR_ALPHA:
2588
{
2589
assert(line_bytes == width * 4);
2590
2591
switch (desired_chans)
2592
{
2593
case 1:
2594
for (uint32_t i = 0; i < width; i++)
2595
{
2596
const uint8_t* p = &pLine[i * 4];
2597
pDst[i] = get_709_luma(p[0], p[1], p[2]);
2598
}
2599
break;
2600
case 2:
2601
for (uint32_t i = 0; i < width; i++)
2602
{
2603
const uint8_t* p = &pLine[i * 4];
2604
pDst[i * 2 + 0] = get_709_luma(p[0], p[1], p[2]);
2605
pDst[i * 2 + 1] = p[3];
2606
}
2607
break;
2608
case 3:
2609
for (uint32_t i = 0; i < width; i++)
2610
{
2611
const uint8_t* p = &pLine[i * 4];
2612
pDst[i * 3 + 0] = p[0];
2613
pDst[i * 3 + 1] = p[1];
2614
pDst[i * 3 + 2] = p[2];
2615
}
2616
break;
2617
case 4:
2618
memcpy(pDst, pLine, pitch);
2619
break;
2620
}
2621
2622
break;
2623
}
2624
default:
2625
assert(0);
2626
break;
2627
}
2628
2629
} // y
2630
2631
return pBuf;
2632
}
2633
2634
} // namespace pv_png
2635
2636
/*
2637
This is free and unencumbered software released into the public domain.
2638
2639
Anyone is free to copy, modify, publish, use, compile, sell, or
2640
distribute this software, either in source code form or as a compiled
2641
binary, for any purpose, commercial or non-commercial, and by any
2642
means.
2643
2644
In jurisdictions that recognize copyright laws, the author or authors
2645
of this software dedicate any and all copyright interest in the
2646
software to the public domain. We make this dedication for the benefit
2647
of the public at large and to the detriment of our heirs and
2648
successors. We intend this dedication to be an overt act of
2649
relinquishment in perpetuity of all present and future rights to this
2650
software under copyright law.
2651
2652
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
2653
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2654
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
2655
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
2656
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
2657
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2658
OTHER DEALINGS IN THE SOFTWARE.
2659
2660
For more information, please refer to <http://unlicense.org/>
2661
2662
Richard Geldreich, Jr.
2663
1/20/2022
2664
*/
2665
2666