26int decodePNG(std::vector<unsigned char>& out_image,
unsigned long& image_width,
unsigned long& image_height,
const unsigned char* in_png,
size_t in_size,
bool convert_to_rgba32)
54 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 };
55 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 };
56 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 };
57 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 };
58 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) {
unsigned long result = (bits[bitp >> 3] >> (bitp & 0x7)) & 1; bitp++;
return result; }
62 static unsigned long readBitsFromStream(
size_t& bitp,
const unsigned char* bits,
size_t nbits)
64 unsigned long result = 0;
65 for (
size_t i = 0; i < nbits; i++) result += (readBitFromStream(bitp, bits)) << i;
70 int makeFromLengths(
const std::vector<unsigned long>& bitlen,
unsigned long maxbitlen)
72 unsigned long numcodes = (
unsigned long)(bitlen.size()), treepos = 0, nodefilled = 0;
73 std::vector<unsigned long> tree1d(numcodes), blcount(maxbitlen + 1, 0), nextcode(maxbitlen + 1, 0);
74 for (
unsigned long bits = 0; bits < numcodes; bits++) blcount[bitlen[bits]]++;
75 for (
unsigned long bits = 1; bits <= maxbitlen; bits++) nextcode[bits] = (nextcode[bits - 1] + blcount[bits - 1]) << 1;
76 for (
unsigned long n = 0; n < numcodes; n++)
if (bitlen[n] != 0) tree1d[n] = nextcode[bitlen[n]]++;
77 tree2d.clear(); tree2d.resize(numcodes * 2, 32767);
78 for (
unsigned long n = 0; n < numcodes; n++)
79 for (
unsigned long i = 0; i < bitlen[n]; i++)
81 unsigned long bit = (tree1d[n] >> (bitlen[n] - i - 1)) & 1;
82 if (treepos > numcodes - 2)
return 55;
83 if (tree2d[2 * treepos + bit] == 32767)
85 if (i + 1 == bitlen[n]) { tree2d[2 * treepos + bit] = n; treepos = 0; }
86 else { tree2d[2 * treepos + bit] = ++nodefilled + numcodes; treepos = nodefilled; }
88 else treepos = tree2d[2 * treepos + bit] - numcodes;
92 int decode(
bool& decoded,
unsigned long& result,
size_t& treepos,
unsigned long bit)
const
94 unsigned long numcodes = (
unsigned long)tree2d.size() / 2;
95 if (treepos >= numcodes)
return 11;
96 result = tree2d[2 * treepos + bit];
97 decoded = (result < numcodes);
98 treepos = decoded ? 0 : result - numcodes;
101 std::vector<unsigned long> tree2d;
106 void inflate(std::vector<unsigned char>& out,
const std::vector<unsigned char>& in,
size_t inpos = 0)
108 size_t bp = 0, pos = 0;
110 unsigned long BFINAL = 0;
111 while (!BFINAL && !error)
113 if (bp >> 3 >= in.size()) { error = 52;
return; }
114 BFINAL = readBitFromStream(bp, &in[inpos]);
115 unsigned long BTYPE = readBitFromStream(bp, &in[inpos]); BTYPE += 2 * readBitFromStream(bp, &in[inpos]);
116 if (BTYPE == 3) { error = 20;
return; }
117 else if (BTYPE == 0) inflateNoCompression(out, &in[inpos], bp, pos, in.size());
118 else inflateHuffmanBlock(out, &in[inpos], bp, pos, in.size(), BTYPE);
120 if (!error) out.resize(pos);
122 void generateFixedTrees(HuffmanTree& tree, HuffmanTree& treeD)
124 std::vector<unsigned long> bitlen(288, 8), bitlenD(32, 5);;
125 for (
size_t i = 144; i <= 255; i++) bitlen[i] = 9;
126 for (
size_t i = 256; i <= 279; i++) bitlen[i] = 7;
127 tree.makeFromLengths(bitlen, 15);
128 treeD.makeFromLengths(bitlenD, 15);
130 HuffmanTree codetree, codetreeD, codelengthcodetree;
131 unsigned long huffmanDecodeSymbol(
const unsigned char* in,
size_t& bp,
const HuffmanTree& codetree,
size_t inlength)
133 bool decoded;
unsigned long ct;
134 for (
size_t treepos = 0;;)
136 if ((bp & 0x07) == 0 && (bp >> 3) > inlength) { error = 10;
return 0; }
137 error = codetree.decode(decoded, ct, treepos, readBitFromStream(bp, in));
if (error)
return 0;
138 if (decoded)
return ct;
141 void getTreeInflateDynamic(HuffmanTree& tree, HuffmanTree& treeD,
const unsigned char* in,
size_t& bp,
size_t inlength)
143 std::vector<unsigned long> bitlen(288, 0), bitlenD(32, 0);
144 if (bp >> 3 >= inlength - 2) { error = 49;
return; }
145 size_t HLIT = readBitsFromStream(bp, in, 5) + 257;
146 size_t HDIST = readBitsFromStream(bp, in, 5) + 1;
147 size_t HCLEN = readBitsFromStream(bp, in, 4) + 4;
148 std::vector<unsigned long> codelengthcode(19);
149 for (
size_t i = 0; i < 19; i++) codelengthcode[CLCL[i]] = (i < HCLEN) ? readBitsFromStream(bp, in, 3) : 0;
150 error = codelengthcodetree.makeFromLengths(codelengthcode, 7);
if (error)
return;
151 size_t i = 0, replength;
152 while (i < HLIT + HDIST)
154 unsigned long code = huffmanDecodeSymbol(in, bp, codelengthcodetree, inlength);
if (error)
return;
155 if (code <= 15) {
if (i < HLIT) bitlen[i++] = code;
else bitlenD[i++ - HLIT] = code; }
158 if (bp >> 3 >= inlength) { error = 50;
return; }
159 replength = 3 + readBitsFromStream(bp, in, 2);
161 if ((i - 1) < HLIT) value = bitlen[i - 1];
162 else value = bitlenD[i - HLIT - 1];
163 for (
size_t n = 0; n < replength; n++)
165 if (i >= HLIT + HDIST) { error = 13;
return; }
166 if (i < HLIT) bitlen[i++] = value;
else bitlenD[i++ - HLIT] = value;
171 if (bp >> 3 >= inlength) { error = 50;
return; }
172 replength = 3 + readBitsFromStream(bp, in, 3);
173 for (
size_t n = 0; n < replength; n++)
175 if (i >= HLIT + HDIST) { error = 14;
return; }
176 if (i < HLIT) bitlen[i++] = 0;
else bitlenD[i++ - HLIT] = 0;
181 if (bp >> 3 >= inlength) { error = 50;
return; }
182 replength = 11 + readBitsFromStream(bp, in, 7);
183 for (
size_t n = 0; n < replength; n++)
185 if (i >= HLIT + HDIST) { error = 15;
return; }
186 if (i < HLIT) bitlen[i++] = 0;
else bitlenD[i++ - HLIT] = 0;
189 else { error = 16;
return; }
191 if (bitlen[256] == 0) { error = 64;
return; }
192 error = tree.makeFromLengths(bitlen, 15);
if (error)
return;
193 error = treeD.makeFromLengths(bitlenD, 15);
if (error)
return;
195 void inflateHuffmanBlock(std::vector<unsigned char>& out,
const unsigned char* in,
size_t& bp,
size_t& pos,
size_t inlength,
unsigned long btype)
197 if (btype == 1) { generateFixedTrees(codetree, codetreeD); }
198 else if (btype == 2) { getTreeInflateDynamic(codetree, codetreeD, in, bp, inlength);
if (error)
return; }
201 unsigned long code = huffmanDecodeSymbol(in, bp, codetree, inlength);
if (error)
return;
202 if (code == 256)
return;
203 else if (code <= 255)
205 if (pos >= out.size()) out.resize((pos + 1) * 2);
206 out[pos++] = (
unsigned char)(code);
208 else if (code >= 257 && code <= 285)
210 size_t length = LENBASE[code - 257], numextrabits = LENEXTRA[code - 257];
211 if ((bp >> 3) >= inlength) { error = 51;
return; }
212 length += readBitsFromStream(bp, in, numextrabits);
213 unsigned long codeD = huffmanDecodeSymbol(in, bp, codetreeD, inlength);
if (error)
return;
214 if (codeD > 29) { error = 18;
return; }
215 unsigned long dist = DISTBASE[codeD], numextrabitsD = DISTEXTRA[codeD];
216 if ((bp >> 3) >= inlength) { error = 51;
return; }
217 dist += readBitsFromStream(bp, in, numextrabitsD);
218 size_t start = pos, back = start - dist;
219 if (pos + length >= out.size()) out.resize((pos + length) * 2);
220 for (
size_t i = 0; i < length; i++) { out[pos++] = out[back++];
if (back >= start) back = start - dist; }
224 void inflateNoCompression(std::vector<unsigned char>& out,
const unsigned char* in,
size_t& bp,
size_t& pos,
size_t inlength)
226 while ((bp & 0x7) != 0) bp++;
228 if (p >= inlength - 4) { error = 52;
return; }
229 unsigned long LEN = in[p] + 256 * in[p + 1], NLEN = in[p + 2] + 256 * in[p + 3]; p += 4;
230 if (LEN + NLEN != 65535) { error = 21;
return; }
231 if (pos + LEN >= out.size()) out.resize(pos + LEN);
232 if (p + LEN > inlength) { error = 23;
return; }
233 for (
unsigned long n = 0; n < LEN; n++) out[pos++] = in[p++];
237 int decompress(std::vector<unsigned char>& out,
const std::vector<unsigned char>& in)
240 if (in.size() < 2) {
return 53; }
241 if ((in[0] * 256 + in[1]) % 31 != 0) {
return 24; }
242 unsigned long CM = in[0] & 15, CINFO = (in[0] >> 4) & 15, FDICT = (in[1] >> 5) & 1;
243 if (CM != 8 || CINFO > 7) {
return 25; }
244 if (FDICT != 0) {
return 26; }
245 inflator.inflate(out, in, 2);
246 return inflator.error;
253 unsigned long width, height, colorType, bitDepth, compressionMethod, filterMethod, interlaceMethod, key_r, key_g, key_b;
255 std::vector<unsigned char> palette;
258 void decode(std::vector<unsigned char>& out,
const unsigned char* in,
size_t size,
bool convert_to_rgba32)
261 if (size == 0 || in == 0) { error = 48;
return; }
262 readPngHeader(&in[0], size);
if (error)
return;
264 std::vector<unsigned char> idat;
265 bool IEND =
false, known_type =
true;
266 info.key_defined =
false;
269 if (pos + 8 >= size) { error = 30;
return; }
270 size_t chunkLength = read32bitInt(&in[pos]); pos += 4;
271 if (chunkLength > 2147483647) { error = 63;
return; }
272 if (pos + chunkLength >= size) { error = 35;
return; }
273 if (in[pos + 0] ==
'I' && in[pos + 1] ==
'D' && in[pos + 2] ==
'A' && in[pos + 3] ==
'T')
275 idat.insert(idat.end(), &in[pos + 4], &in[pos + 4 + chunkLength]);
276 pos += (4 + chunkLength);
278 else if (in[pos + 0] ==
'I' && in[pos + 1] ==
'E' && in[pos + 2] ==
'N' && in[pos + 3] ==
'D') { pos += 4; IEND =
true; }
279 else if (in[pos + 0] ==
'P' && in[pos + 1] ==
'L' && in[pos + 2] ==
'T' && in[pos + 3] ==
'E')
282 info.palette.resize(4 * (chunkLength / 3));
283 if (info.palette.size() > (4 * 256)) { error = 38;
return; }
284 for (
size_t i = 0; i < info.palette.size(); i += 4)
286 for (
size_t j = 0; j < 3; j++) info.palette[i + j] = in[pos++];
287 info.palette[i + 3] = 255;
290 else if (in[pos + 0] ==
't' && in[pos + 1] ==
'R' && in[pos + 2] ==
'N' && in[pos + 3] ==
'S')
293 if (info.colorType == 3)
295 if (4 * chunkLength > info.palette.size()) { error = 39;
return; }
296 for (
size_t i = 0; i < chunkLength; i++) info.palette[4 * i + 3] = in[pos++];
298 else if (info.colorType == 0)
300 if (chunkLength != 2) { error = 40;
return; }
301 info.key_defined = 1; info.key_r = info.key_g = info.key_b = 256 * in[pos] + in[pos + 1]; pos += 2;
303 else if (info.colorType == 2)
305 if (chunkLength != 6) { error = 41;
return; }
306 info.key_defined = 1;
307 info.key_r = 256 * in[pos] + in[pos + 1]; pos += 2;
308 info.key_g = 256 * in[pos] + in[pos + 1]; pos += 2;
309 info.key_b = 256 * in[pos] + in[pos + 1]; pos += 2;
311 else { error = 42;
return; }
315 if (!(in[pos + 0] & 32)) { error = 69;
return; }
316 pos += (chunkLength + 4);
321 unsigned long bpp = getBpp(info);
322 std::vector<unsigned char> scanlines(((info.width * (info.height * bpp + 7)) / 8) + info.height);
324 error = zlib.decompress(scanlines, idat);
if (error)
return;
325 size_t bytewidth = (bpp + 7) / 8, outlength = (info.height * info.width * bpp + 7) / 8;
326 out.resize(outlength);
327 unsigned char* out_ = outlength ? &out[0] : 0;
328 if (info.interlaceMethod == 0)
330 size_t linestart = 0, linelength = (info.width * bpp + 7) / 8;
332 for (
unsigned long y = 0; y < info.height; y++)
334 unsigned long filterType = scanlines[linestart];
335 const unsigned char* prevline = (y == 0) ? 0 : &out_[(y - 1) * info.width * bytewidth];
336 unFilterScanline(&out_[linestart - y], &scanlines[linestart + 1], prevline, bytewidth, filterType, linelength);
if (error)
return;
337 linestart += (1 + linelength);
341 std::vector<unsigned char> templine((info.width * bpp + 7) >> 3);
342 for (
size_t y = 0, obp = 0; y < info.height; y++)
344 unsigned long filterType = scanlines[linestart];
345 const unsigned char* prevline = (y == 0) ? 0 : &out_[(y - 1) * info.width * bytewidth];
346 unFilterScanline(&templine[0], &scanlines[linestart + 1], prevline, bytewidth, filterType, linelength);
if (error)
return;
347 for (
size_t bp = 0; bp < info.width * bpp;) setBitOfReversedStream(obp, out_, readBitFromReversedStream(bp, &templine[0]));
348 linestart += (1 + linelength);
354 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 };
355 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 };
356 size_t passstart[7] = { 0 };
357 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 };
358 for (
int i = 0; i < 6; i++) passstart[i + 1] = passstart[i] + passh[i] * ((passw[i] ? 1 : 0) + (passw[i] * bpp + 7) / 8);
359 std::vector<unsigned char> scanlineo((info.width * bpp + 7) / 8), scanlinen((info.width * bpp + 7) / 8);
360 for (
int i = 0; i < 7; i++)
361 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);
363 if (convert_to_rgba32 && (info.colorType != 6 || info.bitDepth != 8))
365 std::vector<unsigned char> data = out;
366 error = convert(out, &data[0], info, info.width, info.height);
369 void readPngHeader(
const unsigned char* in,
size_t inlength)
371 if (inlength < 29) { error = 27;
return; }
372 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) { error = 28;
return; }
373 if (in[12] !=
'I' || in[13] !=
'H' || in[14] !=
'D' || in[15] !=
'R') { error = 29;
return; }
374 info.width = read32bitInt(&in[16]); info.height = read32bitInt(&in[20]);
375 info.bitDepth = in[24]; info.colorType = in[25];
376 info.compressionMethod = in[26];
if (in[26] != 0) { error = 32;
return; }
377 info.filterMethod = in[27];
if (in[27] != 0) { error = 33;
return; }
378 info.interlaceMethod = in[28];
if (in[28] > 1) { error = 34;
return; }
379 error = checkColorValidity(info.colorType, info.bitDepth);
381 void unFilterScanline(
unsigned char* recon,
const unsigned char* scanline,
const unsigned char* precon,
size_t bytewidth,
unsigned long filterType,
size_t length)
385 case 0:
for (
size_t i = 0; i < length; i++) recon[i] = scanline[i];
break;
387 for (
size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i];
388 for (
size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + recon[i - bytewidth];
391 if (precon)
for (
size_t i = 0; i < length; i++) recon[i] = scanline[i] + precon[i];
392 else for (
size_t i = 0; i < length; i++) recon[i] = scanline[i];
397 for (
size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i] + precon[i] / 2;
398 for (
size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + ((recon[i - bytewidth] + precon[i]) / 2);
402 for (
size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i];
403 for (
size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + recon[i - bytewidth] / 2;
409 for (
size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i] + paethPredictor(0, precon[i], 0);
410 for (
size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth]);
414 for (
size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i];
415 for (
size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + paethPredictor(recon[i - bytewidth], 0, 0);
418 default: error = 36;
return;
421 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)
423 if (passw == 0)
return;
424 size_t bytewidth = (bpp + 7) / 8, linelength = 1 + ((bpp * passw + 7) / 8);
425 for (
unsigned long y = 0; y < passh; y++)
427 unsigned char filterType = in[y * linelength], * prevline = (y == 0) ? 0 : lineo;
428 unFilterScanline(linen, &in[y * linelength + 1], prevline, bytewidth, filterType, (w * bpp + 7) / 8);
if (error)
return;
429 if (bpp >= 8)
for (
size_t i = 0; i < passw; i++)
for (
size_t b = 0; b < bytewidth; b++)
430 out[bytewidth * w * (passtop + spacey * y) + bytewidth * (passleft + spacex * i) + b] = linen[bytewidth * i + b];
431 else for (
size_t i = 0; i < passw; i++)
433 size_t obp = bpp * w * (passtop + spacey * y) + bpp * (passleft + spacex * i), bp = i * bpp;
434 for (
size_t b = 0; b < bpp; b++) setBitOfReversedStream(obp, out, readBitFromReversedStream(bp, &linen[0]));
436 unsigned char* temp = linen; linen = lineo; lineo = temp;
439 static unsigned long readBitFromReversedStream(
size_t& bitp,
const unsigned char* bits) {
unsigned long result = (bits[bitp >> 3] >> (7 - (bitp & 0x7))) & 1; bitp++;
return result; }
440 static unsigned long readBitsFromReversedStream(
size_t& bitp,
const unsigned char* bits,
unsigned long nbits)
442 unsigned long result = 0;
443 for (
size_t i = nbits - 1; i < nbits; i--) result += ((readBitFromReversedStream(bitp, bits)) << i);
446 void setBitOfReversedStream(
size_t& bitp,
unsigned char* bits,
unsigned long bit) { bits[bitp >> 3] |= (bit << (7 - (bitp & 0x7))); bitp++; }
447 unsigned long read32bitInt(
const unsigned char* buffer) {
return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]; }
448 int checkColorValidity(
unsigned long colorType,
unsigned long bd)
450 if ((colorType == 2 || colorType == 4 || colorType == 6)) {
if (!(bd == 8 || bd == 16))
return 37;
else return 0; }
451 else if (colorType == 0) {
if (!(bd == 1 || bd == 2 || bd == 4 || bd == 8 || bd == 16))
return 37;
else return 0; }
452 else if (colorType == 3) {
if (!(bd == 1 || bd == 2 || bd == 4 || bd == 8))
return 37;
else return 0; }
455 unsigned long getBpp(
const Info& info)
457 if (info.colorType == 2)
return (3 * info.bitDepth);
458 else if (info.colorType >= 4)
return (info.colorType - 2) * info.bitDepth;
459 else return info.bitDepth;
461 int convert(std::vector<unsigned char>& out,
const unsigned char* in, Info& infoIn,
unsigned long w,
unsigned long h)
463 size_t numpixels = w * h, bp = 0;
464 out.resize(numpixels * 4);
465 unsigned char* out_ = out.empty() ? 0 : &out[0];
466 if (infoIn.bitDepth == 8 && infoIn.colorType == 0)
467 for (
size_t i = 0; i < numpixels; i++)
469 out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[i];
470 out_[4 * i + 3] = (infoIn.key_defined && in[i] == infoIn.key_r) ? 0 : 255;
472 else if (infoIn.bitDepth == 8 && infoIn.colorType == 2)
473 for (
size_t i = 0; i < numpixels; i++)
475 for (
size_t c = 0; c < 3; c++) out_[4 * i + c] = in[3 * i + c];
476 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;
478 else if (infoIn.bitDepth == 8 && infoIn.colorType == 3)
479 for (
size_t i = 0; i < numpixels; i++)
481 if (4U * in[i] >= infoIn.palette.size())
return 46;
482 for (
size_t c = 0; c < 4; c++) out_[4 * i + c] = infoIn.palette[4 * in[i] + c];
484 else if (infoIn.bitDepth == 8 && infoIn.colorType == 4)
485 for (
size_t i = 0; i < numpixels; i++)
487 out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[2 * i + 0];
488 out_[4 * i + 3] = in[2 * i + 1];
490 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];
491 else if (infoIn.bitDepth == 16 && infoIn.colorType == 0)
492 for (
size_t i = 0; i < numpixels; i++)
494 out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[2 * i];
495 out_[4 * i + 3] = (infoIn.key_defined && 256U * in[i] + in[i + 1] == infoIn.key_r) ? 0 : 255;
497 else if (infoIn.bitDepth == 16 && infoIn.colorType == 2)
498 for (
size_t i = 0; i < numpixels; i++)
500 for (
size_t c = 0; c < 3; c++) out_[4 * i + c] = in[6 * i + 2 * c];
501 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;
503 else if (infoIn.bitDepth == 16 && infoIn.colorType == 4)
504 for (
size_t i = 0; i < numpixels; i++)
506 out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[4 * i];
507 out_[4 * i + 3] = in[4 * i + 2];
509 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];
510 else if (infoIn.bitDepth < 8 && infoIn.colorType == 0)
511 for (
size_t i = 0; i < numpixels; i++)
513 unsigned long value = (readBitsFromReversedStream(bp, in, infoIn.bitDepth) * 255) / ((1 << infoIn.bitDepth) - 1);
514 out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = (
unsigned char)(value);
515 out_[4 * i + 3] = (infoIn.key_defined && value && ((1U << infoIn.bitDepth) - 1U) == infoIn.key_r && ((1U << infoIn.bitDepth) - 1U)) ? 0 : 255;
517 else if (infoIn.bitDepth < 8 && infoIn.colorType == 3)
518 for (
size_t i = 0; i < numpixels; i++)
520 unsigned long value = readBitsFromReversedStream(bp, in, infoIn.bitDepth);
521 if (4 * value >= infoIn.palette.size())
return 47;
522 for (
size_t c = 0; c < 4; c++) out_[4 * i + c] = infoIn.palette[4 * value + c];
526 unsigned char paethPredictor(
short a,
short b,
short c)
528 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);
529 return (
unsigned char)((pa <= pb && pa <= pc) ? a : pb <= pc ? b : c);
532 PNG decoder; decoder.decode(out_image, in_png, in_size, convert_to_rgba32);
533 image_width = decoder.info.width; image_height = decoder.info.height;
534 return decoder.error;