28 int decodePNG(std::vector<unsigned char>& out_image,
unsigned long& image_width,
unsigned long& image_height,
const unsigned char* in_png, std::size_t in_size,
bool convert_to_rgba32) {
55 static const unsigned long LENBASE[29] = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258 };
56 static const unsigned long LENEXTRA[29] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 };
57 static const unsigned long DISTBASE[30] = { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 };
58 static const unsigned long DISTEXTRA[30] = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 };
59 static const unsigned long CLCL[19] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
61 static unsigned long readBitFromStream(
size_t& bitp,
const unsigned char* bits) {
62 unsigned long result = (bits[bitp >> 3] >> (bitp & 0x7)) & 1;
66 static unsigned long readBitsFromStream(
size_t& bitp,
const unsigned char* bits,
size_t nbits) {
67 unsigned long result = 0;
68 for (
size_t i = 0; i < nbits; i++) result += (readBitFromStream(bitp, bits)) << i;
72 int makeFromLengths(
const std::vector<unsigned long>& bitlen,
unsigned long maxbitlen) {
74 unsigned long numcodes = (
unsigned long)(bitlen.size()), treepos = 0, nodefilled = 0;
75 std::vector<unsigned long> tree1d(numcodes), blcount(maxbitlen + 1, 0), nextcode(maxbitlen + 1, 0);
76 for (
unsigned long bits = 0; bits < numcodes; bits++) blcount[bitlen[bits]]++;
77 for (
unsigned long bits = 1; bits <= maxbitlen; bits++) nextcode[bits] = (nextcode[bits - 1] + blcount[bits - 1]) << 1;
78 for (
unsigned long n = 0; n < numcodes; n++)
if (bitlen[n] != 0) tree1d[n] = nextcode[bitlen[n]]++;
80 tree2d.resize(numcodes * 2, 32767);
81 for (
unsigned long n = 0; n < numcodes; n++)
82 for (
unsigned long i = 0; i < bitlen[n]; i++) {
83 unsigned long bit = (tree1d[n] >> (bitlen[n] - i - 1)) & 1;
84 if (treepos > numcodes - 2)
return 55;
85 if (tree2d[2 * treepos + bit] == 32767) {
86 if (i + 1 == bitlen[n]) {
87 tree2d[2 * treepos + bit] = n;
90 tree2d[2 * treepos + bit] = ++nodefilled + numcodes;
93 }
else treepos = tree2d[2 * treepos + bit] - numcodes;
97 int decode(
bool& decoded,
unsigned long& result,
size_t& treepos,
unsigned long bit)
const {
99 unsigned long numcodes = (
unsigned long)tree2d.size() / 2;
100 if (treepos >= numcodes)
return 11;
101 result = tree2d[2 * treepos + bit];
102 decoded = (result < numcodes);
103 treepos = decoded ? 0 : result - numcodes;
106 std::vector<unsigned long> tree2d;
110 void inflate(std::vector<unsigned char>& out,
const std::vector<unsigned char>& in,
size_t inpos = 0) {
111 size_t bp = 0, pos = 0;
113 unsigned long BFINAL = 0;
114 while (!BFINAL && !error) {
115 if (bp >> 3 >= in.size()) {
119 BFINAL = readBitFromStream(bp, &in[inpos]);
120 unsigned long BTYPE = readBitFromStream(bp, &in[inpos]);
121 BTYPE += 2 * readBitFromStream(bp, &in[inpos]);
125 }
else if (BTYPE == 0) inflateNoCompression(out, &in[inpos], bp, pos, in.size());
126 else inflateHuffmanBlock(out, &in[inpos], bp, pos, in.size(), BTYPE);
128 if (!error) out.resize(pos);
130 void generateFixedTrees(HuffmanTree& tree, HuffmanTree& treeD) {
131 std::vector<unsigned long> bitlen(288, 8), bitlenD(32, 5);;
132 for (
size_t i = 144; i <= 255; i++) bitlen[i] = 9;
133 for (
size_t i = 256; i <= 279; i++) bitlen[i] = 7;
134 tree.makeFromLengths(bitlen, 15);
135 treeD.makeFromLengths(bitlenD, 15);
137 HuffmanTree codetree, codetreeD, codelengthcodetree;
138 unsigned long huffmanDecodeSymbol(
const unsigned char* in,
size_t& bp,
const HuffmanTree& codetree,
size_t inlength) {
142 for (
size_t treepos = 0;;) {
143 if ((bp & 0x07) == 0 && (bp >> 3) > inlength) {
147 error = codetree.decode(decoded, ct, treepos, readBitFromStream(bp, in));
149 if (decoded)
return ct;
152 void getTreeInflateDynamic(HuffmanTree& tree, HuffmanTree& treeD,
const unsigned char* in,
size_t& bp,
size_t inlength) {
154 std::vector<unsigned long> bitlen(288, 0), bitlenD(32, 0);
155 if (bp >> 3 >= inlength - 2) {
159 size_t HLIT = readBitsFromStream(bp, in, 5) + 257;
160 size_t HDIST = readBitsFromStream(bp, in, 5) + 1;
161 size_t HCLEN = readBitsFromStream(bp, in, 4) + 4;
162 std::vector<unsigned long> codelengthcode(19);
163 for (
size_t i = 0; i < 19; i++) codelengthcode[CLCL[i]] = (i < HCLEN) ? readBitsFromStream(bp, in, 3) : 0;
164 error = codelengthcodetree.makeFromLengths(codelengthcode, 7);
166 size_t i = 0, replength;
167 while (i < HLIT + HDIST) {
168 unsigned long code = huffmanDecodeSymbol(in, bp, codelengthcodetree, inlength);
171 if (i < HLIT) bitlen[i++] = code;
172 else bitlenD[i++ - HLIT] = code;
173 }
else if (code == 16) {
174 if (bp >> 3 >= inlength) {
178 replength = 3 + readBitsFromStream(bp, in, 2);
180 if ((i - 1) < HLIT) value = bitlen[i - 1];
181 else value = bitlenD[i - HLIT - 1];
182 for (
size_t n = 0; n < replength; n++) {
183 if (i >= HLIT + HDIST) {
187 if (i < HLIT) bitlen[i++] = value;
188 else bitlenD[i++ - HLIT] = value;
190 }
else if (code == 17) {
191 if (bp >> 3 >= inlength) {
195 replength = 3 + readBitsFromStream(bp, in, 3);
196 for (
size_t n = 0; n < replength; n++) {
197 if (i >= HLIT + HDIST) {
201 if (i < HLIT) bitlen[i++] = 0;
202 else bitlenD[i++ - HLIT] = 0;
204 }
else if (code == 18) {
205 if (bp >> 3 >= inlength) {
209 replength = 11 + readBitsFromStream(bp, in, 7);
210 for (
size_t n = 0; n < replength; n++) {
211 if (i >= HLIT + HDIST) {
215 if (i < HLIT) bitlen[i++] = 0;
216 else bitlenD[i++ - HLIT] = 0;
223 if (bitlen[256] == 0) {
227 error = tree.makeFromLengths(bitlen, 15);
229 error = treeD.makeFromLengths(bitlenD, 15);
232 void inflateHuffmanBlock(std::vector<unsigned char>& out,
const unsigned char* in,
size_t& bp,
size_t& pos,
size_t inlength,
unsigned long btype) {
234 generateFixedTrees(codetree, codetreeD);
235 }
else if (btype == 2) {
236 getTreeInflateDynamic(codetree, codetreeD, in, bp, inlength);
240 unsigned long code = huffmanDecodeSymbol(in, bp, codetree, inlength);
242 if (code == 256)
return;
243 else if (code <= 255) {
244 if (pos >= out.size()) out.resize((pos + 1) * 2);
245 out[pos++] = (
unsigned char)(code);
246 }
else if (code >= 257 && code <= 285) {
247 size_t length = LENBASE[code - 257], numextrabits = LENEXTRA[code - 257];
248 if ((bp >> 3) >= inlength) {
252 length += readBitsFromStream(bp, in, numextrabits);
253 unsigned long codeD = huffmanDecodeSymbol(in, bp, codetreeD, inlength);
259 unsigned long dist = DISTBASE[codeD], numextrabitsD = DISTEXTRA[codeD];
260 if ((bp >> 3) >= inlength) {
264 dist += readBitsFromStream(bp, in, numextrabitsD);
265 size_t start = pos, back = start - dist;
266 if (pos + length >= out.size()) out.resize((pos + length) * 2);
267 for (
size_t i = 0; i < length; i++) {
268 out[pos++] = out[back++];
269 if (back >= start) back = start - dist;
274 void inflateNoCompression(std::vector<unsigned char>& out,
const unsigned char* in,
size_t& bp,
size_t& pos,
size_t inlength) {
275 while ((bp & 0x7) != 0) bp++;
277 if (p >= inlength - 4) {
281 unsigned long LEN = in[p] + 256 * in[p + 1], NLEN = in[p + 2] + 256 * in[p + 3];
283 if (LEN + NLEN != 65535) {
287 if (pos + LEN >= out.size()) out.resize(pos + LEN);
288 if (p + LEN > inlength) {
292 for (
unsigned long n = 0; n < LEN; n++) out[pos++] = in[p++];
296 int decompress(std::vector<unsigned char>& out,
const std::vector<unsigned char>& in) {
301 if ((in[0] * 256 + in[1]) % 31 != 0) {
304 unsigned long CM = in[0] & 15, CINFO = (in[0] >> 4) & 15, FDICT = (in[1] >> 5) & 1;
305 if (CM != 8 || CINFO > 7) {
311 inflator.inflate(out, in, 2);
312 return inflator.error;
317 unsigned long width, height, colorType, bitDepth, compressionMethod, filterMethod, interlaceMethod, key_r, key_g, key_b;
319 std::vector<unsigned char> palette;
322 void decode(std::vector<unsigned char>& out,
const unsigned char* in,
size_t size,
bool convert_to_rgba32) {
324 if (size == 0 || in == 0) {
328 readPngHeader(&in[0], size);
331 std::vector<unsigned char> idat;
333 info.key_defined =
false;
335 if (pos + 8 >= size) {
339 size_t chunkLength = read32bitInt(&in[pos]);
341 if (chunkLength > 2147483647) {
345 if (pos + chunkLength >= size) {
349 if (in[pos + 0] ==
'I' && in[pos + 1] ==
'D' && in[pos + 2] ==
'A' && in[pos + 3] ==
'T') {
350 idat.insert(idat.end(), &in[pos + 4], &in[pos + 4 + chunkLength]);
351 pos += (4 + chunkLength);
352 }
else if (in[pos + 0] ==
'I' && in[pos + 1] ==
'E' && in[pos + 2] ==
'N' && in[pos + 3] ==
'D') {
355 }
else if (in[pos + 0] ==
'P' && in[pos + 1] ==
'L' && in[pos + 2] ==
'T' && in[pos + 3] ==
'E') {
357 info.palette.resize(4 * (chunkLength / 3));
358 if (info.palette.size() > (4 * 256)) {
362 for (
size_t i = 0; i < info.palette.size(); i += 4) {
363 for (
size_t j = 0; j < 3; j++) info.palette[i + j] = in[pos++];
364 info.palette[i + 3] = 255;
366 }
else if (in[pos + 0] ==
't' && in[pos + 1] ==
'R' && in[pos + 2] ==
'N' && in[pos + 3] ==
'S') {
368 if (info.colorType == 3) {
369 if (4 * chunkLength > info.palette.size()) {
373 for (
size_t i = 0; i < chunkLength; i++) info.palette[4 * i + 3] = in[pos++];
374 }
else if (info.colorType == 0) {
375 if (chunkLength != 2) {
379 info.key_defined = 1;
380 info.key_r = info.key_g = info.key_b = 256 * in[pos] + in[pos + 1];
382 }
else if (info.colorType == 2) {
383 if (chunkLength != 6) {
387 info.key_defined = 1;
388 info.key_r = 256 * in[pos] + in[pos + 1];
390 info.key_g = 256 * in[pos] + in[pos + 1];
392 info.key_b = 256 * in[pos] + in[pos + 1];
399 if (!(in[pos + 0] & 32)) {
403 pos += (chunkLength + 4);
407 unsigned long bpp = getBpp(info);
408 std::vector<unsigned char> scanlines(((info.width * (info.height * bpp + 7)) / 8) + info.height);
410 error = zlib.decompress(scanlines, idat);
412 size_t bytewidth = (bpp + 7) / 8, outlength = (info.height * info.width * bpp + 7) / 8;
413 out.resize(outlength);
414 unsigned char* out_ = outlength ? &out[0] : 0;
415 if (info.interlaceMethod == 0) {
416 size_t linestart = 0, linelength = (info.width * bpp + 7) / 8;
418 for (
unsigned long y = 0; y < info.height; y++) {
419 unsigned long filterType = scanlines[linestart];
420 const unsigned char* prevline = (y == 0) ? 0 : &out_[(y - 1) * info.width * bytewidth];
421 unFilterScanline(&out_[linestart - y], &scanlines[linestart + 1], prevline, bytewidth, filterType, linelength);
423 linestart += (1 + linelength);
425 std::vector<unsigned char> templine((info.width * bpp + 7) >> 3);
426 for (
size_t y = 0, obp = 0; y < info.height; y++) {
427 unsigned long filterType = scanlines[linestart];
428 const unsigned char* prevline = (y == 0) ? 0 : &out_[(y - 1) * info.width * bytewidth];
429 unFilterScanline(&templine[0], &scanlines[linestart + 1], prevline, bytewidth, filterType, linelength);
431 for (
size_t bp = 0; bp < info.width * bpp;) setBitOfReversedStream(obp, out_, readBitFromReversedStream(bp, &templine[0]));
432 linestart += (1 + linelength);
436 size_t passw[7] = { (info.width + 7) / 8, (info.width + 3) / 8, (info.width + 3) / 4, (info.width + 1) / 4, (info.width + 1) / 2, (info.width + 0) / 2, (info.width + 0) / 1 };
437 size_t passh[7] = { (info.height + 7) / 8, (info.height + 7) / 8, (info.height + 3) / 8, (info.height + 3) / 4, (info.height + 1) / 4, (info.height + 1) / 2, (info.height + 0) / 2 };
438 size_t passstart[7] = { 0 };
439 size_t pattern[28] = { 0, 4, 0, 2, 0, 1, 0, 0, 0, 4, 0, 2, 0, 1, 8, 8, 4, 4, 2, 2, 1, 8, 8, 8, 4, 4, 2, 2 };
440 for (
int i = 0; i < 6; i++) passstart[i + 1] = passstart[i] + passh[i] * ((passw[i] ? 1 : 0) + (passw[i] * bpp + 7) / 8);
441 std::vector<unsigned char> scanlineo((info.width * bpp + 7) / 8), scanlinen((info.width * bpp + 7) / 8);
442 for (
int i = 0; i < 7; i++)
443 adam7Pass(&out_[0], &scanlinen[0], &scanlineo[0], &scanlines[passstart[i]], info.width, pattern[i], pattern[i + 7], pattern[i + 14], pattern[i + 21], passw[i], passh[i], bpp);
445 if (convert_to_rgba32 && (info.colorType != 6 || info.bitDepth != 8)) {
446 std::vector<unsigned char> data = out;
447 error = convert(out, &data[0], info, info.width, info.height);
450 void readPngHeader(
const unsigned char* in,
size_t inlength) {
455 if (in[0] != 137 || in[1] != 80 || in[2] != 78 || in[3] != 71 || in[4] != 13 || in[5] != 10 || in[6] != 26 || in[7] != 10) {
459 if (in[12] !=
'I' || in[13] !=
'H' || in[14] !=
'D' || in[15] !=
'R') {
463 info.width = read32bitInt(&in[16]);
464 info.height = read32bitInt(&in[20]);
465 info.bitDepth = in[24];
466 info.colorType = in[25];
467 info.compressionMethod = in[26];
472 info.filterMethod = in[27];
477 info.interlaceMethod = in[28];
482 error = checkColorValidity(info.colorType, info.bitDepth);
484 void unFilterScanline(
unsigned char* recon,
const unsigned char* scanline,
const unsigned char* precon,
size_t bytewidth,
unsigned long filterType,
size_t length) {
485 switch (filterType) {
487 for (
size_t i = 0; i < length; i++) recon[i] = scanline[i];
490 for (
size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i];
491 for (
size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + recon[i - bytewidth];
494 if (precon)
for (
size_t i = 0; i < length; i++) recon[i] = scanline[i] + precon[i];
495 else for (
size_t i = 0; i < length; i++) recon[i] = scanline[i];
499 for (
size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i] + precon[i] / 2;
500 for (
size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + ((recon[i - bytewidth] + precon[i]) / 2);
502 for (
size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i];
503 for (
size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + recon[i - bytewidth] / 2;
508 for (
size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i] + paethPredictor(0, precon[i], 0);
509 for (
size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth]);
511 for (
size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i];
512 for (
size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + paethPredictor(recon[i - bytewidth], 0, 0);
520 void adam7Pass(
unsigned char* out,
unsigned char* linen,
unsigned char* lineo,
const unsigned char* in,
unsigned long w,
size_t passleft,
size_t passtop,
size_t spacex,
size_t spacey,
size_t passw,
size_t passh,
unsigned long bpp) {
522 if (passw == 0)
return;
523 size_t bytewidth = (bpp + 7) / 8, linelength = 1 + ((bpp * passw + 7) / 8);
524 for (
unsigned long y = 0; y < passh; y++) {
525 unsigned char filterType = in[y * linelength], *prevline = (y == 0) ? 0 : lineo;
526 unFilterScanline(linen, &in[y * linelength + 1], prevline, bytewidth, filterType, (w * bpp + 7) / 8);
528 if (bpp >= 8)
for (
size_t i = 0; i < passw; i++)
for (
size_t b = 0; b < bytewidth; b++)
529 out[bytewidth * w * (passtop + spacey * y) + bytewidth * (passleft + spacex * i) + b] = linen[bytewidth * i + b];
530 else for (
size_t i = 0; i < passw; i++) {
531 size_t obp = bpp * w * (passtop + spacey * y) + bpp * (passleft + spacex * i), bp = i * bpp;
532 for (
size_t b = 0; b < bpp; b++) setBitOfReversedStream(obp, out, readBitFromReversedStream(bp, &linen[0]));
534 unsigned char* temp = linen;
539 static unsigned long readBitFromReversedStream(
size_t& bitp,
const unsigned char* bits) {
540 unsigned long result = (bits[bitp >> 3] >> (7 - (bitp & 0x7))) & 1;
544 static unsigned long readBitsFromReversedStream(
size_t& bitp,
const unsigned char* bits,
unsigned long nbits) {
545 unsigned long result = 0;
546 for (
size_t i = nbits - 1; i < nbits; i--) result += ((readBitFromReversedStream(bitp, bits)) << i);
549 void setBitOfReversedStream(
size_t& bitp,
unsigned char* bits,
unsigned long bit) {
550 bits[bitp >> 3] |= (bit << (7 - (bitp & 0x7)));
553 unsigned long read32bitInt(
const unsigned char* buffer) {
554 return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
556 int checkColorValidity(
unsigned long colorType,
unsigned long bd) {
557 if ((colorType == 2 || colorType == 4 || colorType == 6)) {
558 if (!(bd == 8 || bd == 16))
return 37;
560 }
else if (colorType == 0) {
561 if (!(bd == 1 || bd == 2 || bd == 4 || bd == 8 || bd == 16))
return 37;
563 }
else if (colorType == 3) {
564 if (!(bd == 1 || bd == 2 || bd == 4 || bd == 8))
return 37;
568 unsigned long getBpp(
const Info& info) {
569 if (info.colorType == 2)
return (3 * info.bitDepth);
570 else if (info.colorType >= 4)
return (info.colorType - 2) * info.bitDepth;
571 else return info.bitDepth;
573 int convert(std::vector<unsigned char>& out,
const unsigned char* in, Info& infoIn,
unsigned long w,
unsigned long h) {
575 size_t numpixels = w * h, bp = 0;
576 out.resize(numpixels * 4);
577 unsigned char* out_ = out.empty() ? 0 : &out[0];
578 if (infoIn.bitDepth == 8 && infoIn.colorType == 0)
579 for (
size_t i = 0; i < numpixels; i++) {
580 out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[i];
581 out_[4 * i + 3] = (infoIn.key_defined && in[i] == infoIn.key_r) ? 0 : 255;
582 }
else if (infoIn.bitDepth == 8 && infoIn.colorType == 2)
583 for (
size_t i = 0; i < numpixels; i++) {
584 for (
size_t c = 0; c < 3; c++) out_[4 * i + c] = in[3 * i + c];
585 out_[4 * i + 3] = (infoIn.key_defined == 1 && in[3 * i + 0] == infoIn.key_r && in[3 * i + 1] == infoIn.key_g && in[3 * i + 2] == infoIn.key_b) ? 0 : 255;
586 }
else if (infoIn.bitDepth == 8 && infoIn.colorType == 3)
587 for (
size_t i = 0; i < numpixels; i++) {
588 if (4U * in[i] >= infoIn.palette.size())
return 46;
589 for (
size_t c = 0; c < 4; c++) out_[4 * i + c] = infoIn.palette[4 * in[i] + c];
590 }
else if (infoIn.bitDepth == 8 && infoIn.colorType == 4)
591 for (
size_t i = 0; i < numpixels; i++) {
592 out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[2 * i + 0];
593 out_[4 * i + 3] = in[2 * i + 1];
594 }
else if (infoIn.bitDepth == 8 && infoIn.colorType == 6)
for (
size_t i = 0; i < numpixels; i++)
for (
size_t c = 0; c < 4; c++) out_[4 * i + c] = in[4 * i + c];
595 else if (infoIn.bitDepth == 16 && infoIn.colorType == 0)
596 for (
size_t i = 0; i < numpixels; i++) {
597 out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[2 * i];
598 out_[4 * i + 3] = (infoIn.key_defined && 256U * in[i] + in[i + 1] == infoIn.key_r) ? 0 : 255;
599 }
else if (infoIn.bitDepth == 16 && infoIn.colorType == 2)
600 for (
size_t i = 0; i < numpixels; i++) {
601 for (
size_t c = 0; c < 3; c++) out_[4 * i + c] = in[6 * i + 2 * c];
602 out_[4 * i + 3] = (infoIn.key_defined && 256U * in[6 * i + 0] + in[6 * i + 1] == infoIn.key_r && 256U * in[6 * i + 2] + in[6 * i + 3] == infoIn.key_g && 256U * in[6 * i + 4] + in[6 * i + 5] == infoIn.key_b) ? 0 : 255;
603 }
else if (infoIn.bitDepth == 16 && infoIn.colorType == 4)
604 for (
size_t i = 0; i < numpixels; i++) {
605 out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[4 * i];
606 out_[4 * i + 3] = in[4 * i + 2];
607 }
else if (infoIn.bitDepth == 16 && infoIn.colorType == 6)
for (
size_t i = 0; i < numpixels; i++)
for (
size_t c = 0; c < 4; c++) out_[4 * i + c] = in[8 * i + 2 * c];
608 else if (infoIn.bitDepth < 8 && infoIn.colorType == 0)
609 for (
size_t i = 0; i < numpixels; i++) {
610 unsigned long value = (readBitsFromReversedStream(bp, in, infoIn.bitDepth) * 255) / ((1 << infoIn.bitDepth) - 1);
611 out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = (
unsigned char)(value);
612 out_[4 * i + 3] = (infoIn.key_defined && value && ((1U << infoIn.bitDepth) - 1U) == infoIn.key_r && ((1U << infoIn.bitDepth) - 1U)) ? 0 : 255;
613 }
else if (infoIn.bitDepth < 8 && infoIn.colorType == 3)
614 for (
size_t i = 0; i < numpixels; i++) {
615 unsigned long value = readBitsFromReversedStream(bp, in, infoIn.bitDepth);
616 if (4 * value >= infoIn.palette.size())
return 47;
617 for (
size_t c = 0; c < 4; c++) out_[4 * i + c] = infoIn.palette[4 * value + c];
621 unsigned char paethPredictor(
short a,
short b,
short c) {
622 short p = a + b - c, pa = p > a ? (p - a) : (a - p), pb = p > b ? (p - b) : (b - p), pc = p > c ? (p - c) : (c - p);
623 return (
unsigned char)((pa <= pb && pa <= pc) ? a : pb <= pc ? b : c);
627 decoder.decode(out_image, in_png, in_size, convert_to_rgba32);
628 image_width = decoder.info.width;
629 image_height = decoder.info.height;
630 return decoder.error;