25int 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)
53 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 };
54 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 };
55 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 };
56 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 };
57 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 };
60 static unsigned long readBitFromStream(
size_t& bitp,
const unsigned char* bits) {
unsigned long result = (bits[bitp >> 3] >> (bitp & 0x7)) & 1; bitp++;
return result; }
61 static unsigned long readBitsFromStream(
size_t& bitp,
const unsigned char* bits,
size_t nbits)
63 unsigned long result = 0;
64 for (
size_t i = 0; i < nbits; i++) result += (readBitFromStream(bitp, bits)) << i;
69 int makeFromLengths(
const std::vector<unsigned long>& bitlen,
unsigned long maxbitlen)
71 unsigned long numcodes = (
unsigned long)(bitlen.size()), treepos = 0, nodefilled = 0;
72 std::vector<unsigned long> tree1d(numcodes), blcount(maxbitlen + 1, 0), nextcode(maxbitlen + 1, 0);
73 for (
unsigned long bits = 0; bits < numcodes; bits++) blcount[bitlen[bits]]++;
74 for (
unsigned long bits = 1; bits <= maxbitlen; bits++) nextcode[bits] = (nextcode[bits - 1] + blcount[bits - 1]) << 1;
75 for (
unsigned long n = 0; n < numcodes; n++)
if (bitlen[n] != 0) tree1d[n] = nextcode[bitlen[n]]++;
76 tree2d.clear(); tree2d.resize(numcodes * 2, 32767);
77 for (
unsigned long n = 0; n < numcodes; n++)
78 for (
unsigned long i = 0; i < bitlen[n]; i++)
80 unsigned long bit = (tree1d[n] >> (bitlen[n] - i - 1)) & 1;
81 if (treepos > numcodes - 2)
return 55;
82 if (tree2d[2 * treepos + bit] == 32767)
84 if (i + 1 == bitlen[n]) { tree2d[2 * treepos + bit] = n; treepos = 0; }
85 else { tree2d[2 * treepos + bit] = ++nodefilled + numcodes; treepos = nodefilled; }
87 else treepos = tree2d[2 * treepos + bit] - numcodes;
91 int decode(
bool& decoded,
unsigned long& result,
size_t& treepos,
unsigned long bit)
const
93 unsigned long numcodes = (
unsigned long)tree2d.size() / 2;
94 if (treepos >= numcodes)
return 11;
95 result = tree2d[2 * treepos + bit];
96 decoded = (result < numcodes);
97 treepos = decoded ? 0 : result - numcodes;
100 std::vector<unsigned long> tree2d;
105 void inflate(std::vector<unsigned char>& out,
const std::vector<unsigned char>& in,
size_t inpos = 0)
107 size_t bp = 0, pos = 0;
109 unsigned long BFINAL = 0;
110 while (!BFINAL && !error)
112 if (bp >> 3 >= in.size()) { error = 52;
return; }
113 BFINAL = readBitFromStream(bp, &in[inpos]);
114 unsigned long BTYPE = readBitFromStream(bp, &in[inpos]); BTYPE += 2 * readBitFromStream(bp, &in[inpos]);
115 if (BTYPE == 3) { error = 20;
return; }
116 else if (BTYPE == 0) inflateNoCompression(out, &in[inpos], bp, pos, in.size());
117 else inflateHuffmanBlock(out, &in[inpos], bp, pos, in.size(), BTYPE);
119 if (!error) out.resize(pos);
121 void generateFixedTrees(HuffmanTree& tree, HuffmanTree& treeD)
123 std::vector<unsigned long> bitlen(288, 8), bitlenD(32, 5);;
124 for (
size_t i = 144; i <= 255; i++) bitlen[i] = 9;
125 for (
size_t i = 256; i <= 279; i++) bitlen[i] = 7;
126 tree.makeFromLengths(bitlen, 15);
127 treeD.makeFromLengths(bitlenD, 15);
129 HuffmanTree codetree, codetreeD, codelengthcodetree;
130 unsigned long huffmanDecodeSymbol(
const unsigned char* in,
size_t& bp,
const HuffmanTree& codetree,
size_t inlength)
132 bool decoded;
unsigned long ct;
133 for (
size_t treepos = 0;;)
135 if ((bp & 0x07) == 0 && (bp >> 3) > inlength) { error = 10;
return 0; }
136 error = codetree.decode(decoded, ct, treepos, readBitFromStream(bp, in));
if (error)
return 0;
137 if (decoded)
return ct;
140 void getTreeInflateDynamic(HuffmanTree& tree, HuffmanTree& treeD,
const unsigned char* in,
size_t& bp,
size_t inlength)
142 std::vector<unsigned long> bitlen(288, 0), bitlenD(32, 0);
143 if (bp >> 3 >= inlength - 2) { error = 49;
return; }
144 size_t HLIT = readBitsFromStream(bp, in, 5) + 257;
145 size_t HDIST = readBitsFromStream(bp, in, 5) + 1;
146 size_t HCLEN = readBitsFromStream(bp, in, 4) + 4;
147 std::vector<unsigned long> codelengthcode(19);
148 for (
size_t i = 0; i < 19; i++) codelengthcode[CLCL[i]] = (i < HCLEN) ? readBitsFromStream(bp, in, 3) : 0;
149 error = codelengthcodetree.makeFromLengths(codelengthcode, 7);
if (error)
return;
150 size_t i = 0, replength;
151 while (i < HLIT + HDIST)
153 unsigned long code = huffmanDecodeSymbol(in, bp, codelengthcodetree, inlength);
if (error)
return;
154 if (code <= 15) {
if (i < HLIT) bitlen[i++] = code;
else bitlenD[i++ - HLIT] = code; }
157 if (bp >> 3 >= inlength) { error = 50;
return; }
158 replength = 3 + readBitsFromStream(bp, in, 2);
160 if ((i - 1) < HLIT) value = bitlen[i - 1];
161 else value = bitlenD[i - HLIT - 1];
162 for (
size_t n = 0; n < replength; n++)
164 if (i >= HLIT + HDIST) { error = 13;
return; }
165 if (i < HLIT) bitlen[i++] = value;
else bitlenD[i++ - HLIT] = value;
170 if (bp >> 3 >= inlength) { error = 50;
return; }
171 replength = 3 + readBitsFromStream(bp, in, 3);
172 for (
size_t n = 0; n < replength; n++)
174 if (i >= HLIT + HDIST) { error = 14;
return; }
175 if (i < HLIT) bitlen[i++] = 0;
else bitlenD[i++ - HLIT] = 0;
180 if (bp >> 3 >= inlength) { error = 50;
return; }
181 replength = 11 + readBitsFromStream(bp, in, 7);
182 for (
size_t n = 0; n < replength; n++)
184 if (i >= HLIT + HDIST) { error = 15;
return; }
185 if (i < HLIT) bitlen[i++] = 0;
else bitlenD[i++ - HLIT] = 0;
188 else { error = 16;
return; }
190 if (bitlen[256] == 0) { error = 64;
return; }
191 error = tree.makeFromLengths(bitlen, 15);
if (error)
return;
192 error = treeD.makeFromLengths(bitlenD, 15);
if (error)
return;
194 void inflateHuffmanBlock(std::vector<unsigned char>& out,
const unsigned char* in,
size_t& bp,
size_t& pos,
size_t inlength,
unsigned long btype)
196 if (btype == 1) { generateFixedTrees(codetree, codetreeD); }
197 else if (btype == 2) { getTreeInflateDynamic(codetree, codetreeD, in, bp, inlength);
if (error)
return; }
200 unsigned long code = huffmanDecodeSymbol(in, bp, codetree, inlength);
if (error)
return;
201 if (code == 256)
return;
202 else if (code <= 255)
204 if (pos >= out.size()) out.resize((pos + 1) * 2);
205 out[pos++] = (
unsigned char)(code);
207 else if (code >= 257 && code <= 285)
209 size_t length = LENBASE[code - 257], numextrabits = LENEXTRA[code - 257];
210 if ((bp >> 3) >= inlength) { error = 51;
return; }
211 length += readBitsFromStream(bp, in, numextrabits);
212 unsigned long codeD = huffmanDecodeSymbol(in, bp, codetreeD, inlength);
if (error)
return;
213 if (codeD > 29) { error = 18;
return; }
214 unsigned long dist = DISTBASE[codeD], numextrabitsD = DISTEXTRA[codeD];
215 if ((bp >> 3) >= inlength) { error = 51;
return; }
216 dist += readBitsFromStream(bp, in, numextrabitsD);
217 size_t start = pos, back = start - dist;
218 if (pos + length >= out.size()) out.resize((pos + length) * 2);
219 for (
size_t i = 0; i < length; i++) { out[pos++] = out[back++];
if (back >= start) back = start - dist; }
223 void inflateNoCompression(std::vector<unsigned char>& out,
const unsigned char* in,
size_t& bp,
size_t& pos,
size_t inlength)
225 while ((bp & 0x7) != 0) bp++;
227 if (p >= inlength - 4) { error = 52;
return; }
228 unsigned long LEN = in[p] + 256 * in[p + 1], NLEN = in[p + 2] + 256 * in[p + 3]; p += 4;
229 if (LEN + NLEN != 65535) { error = 21;
return; }
230 if (pos + LEN >= out.size()) out.resize(pos + LEN);
231 if (p + LEN > inlength) { error = 23;
return; }
232 for (
unsigned long n = 0; n < LEN; n++) out[pos++] = in[p++];
236 int decompress(std::vector<unsigned char>& out,
const std::vector<unsigned char>& in)
239 if (in.size() < 2) {
return 53; }
240 if ((in[0] * 256 + in[1]) % 31 != 0) {
return 24; }
241 unsigned long CM = in[0] & 15, CINFO = (in[0] >> 4) & 15, FDICT = (in[1] >> 5) & 1;
242 if (CM != 8 || CINFO > 7) {
return 25; }
243 if (FDICT != 0) {
return 26; }
244 inflator.inflate(out, in, 2);
245 return inflator.error;
252 unsigned long width, height, colorType, bitDepth, compressionMethod, filterMethod, interlaceMethod, key_r, key_g, key_b;
254 std::vector<unsigned char> palette;
257 void decode(std::vector<unsigned char>& out,
const unsigned char* in,
size_t size,
bool convert_to_rgba32)
260 if (size == 0 || in == 0) { error = 48;
return; }
261 readPngHeader(&in[0], size);
if (error)
return;
263 std::vector<unsigned char> idat;
264 bool IEND =
false, known_type =
true;
265 info.key_defined =
false;
268 if (pos + 8 >= size) { error = 30;
return; }
269 size_t chunkLength = read32bitInt(&in[pos]); pos += 4;
270 if (chunkLength > 2147483647) { error = 63;
return; }
271 if (pos + chunkLength >= size) { error = 35;
return; }
272 if (in[pos + 0] ==
'I' && in[pos + 1] ==
'D' && in[pos + 2] ==
'A' && in[pos + 3] ==
'T')
274 idat.insert(idat.end(), &in[pos + 4], &in[pos + 4 + chunkLength]);
275 pos += (4 + chunkLength);
277 else if (in[pos + 0] ==
'I' && in[pos + 1] ==
'E' && in[pos + 2] ==
'N' && in[pos + 3] ==
'D') { pos += 4; IEND =
true; }
278 else if (in[pos + 0] ==
'P' && in[pos + 1] ==
'L' && in[pos + 2] ==
'T' && in[pos + 3] ==
'E')
281 info.palette.resize(4 * (chunkLength / 3));
282 if (info.palette.size() > (4 * 256)) { error = 38;
return; }
283 for (
size_t i = 0; i < info.palette.size(); i += 4)
285 for (
size_t j = 0; j < 3; j++) info.palette[i + j] = in[pos++];
286 info.palette[i + 3] = 255;
289 else if (in[pos + 0] ==
't' && in[pos + 1] ==
'R' && in[pos + 2] ==
'N' && in[pos + 3] ==
'S')
292 if (info.colorType == 3)
294 if (4 * chunkLength > info.palette.size()) { error = 39;
return; }
295 for (
size_t i = 0; i < chunkLength; i++) info.palette[4 * i + 3] = in[pos++];
297 else if (info.colorType == 0)
299 if (chunkLength != 2) { error = 40;
return; }
300 info.key_defined = 1; info.key_r = info.key_g = info.key_b = 256 * in[pos] + in[pos + 1]; pos += 2;
302 else if (info.colorType == 2)
304 if (chunkLength != 6) { error = 41;
return; }
305 info.key_defined = 1;
306 info.key_r = 256 * in[pos] + in[pos + 1]; pos += 2;
307 info.key_g = 256 * in[pos] + in[pos + 1]; pos += 2;
308 info.key_b = 256 * in[pos] + in[pos + 1]; pos += 2;
310 else { error = 42;
return; }
314 if (!(in[pos + 0] & 32)) { error = 69;
return; }
315 pos += (chunkLength + 4);
320 unsigned long bpp = getBpp(info);
321 std::vector<unsigned char> scanlines(((info.width * (info.height * bpp + 7)) / 8) + info.height);
323 error = zlib.decompress(scanlines, idat);
if (error)
return;
324 size_t bytewidth = (bpp + 7) / 8, outlength = (info.height * info.width * bpp + 7) / 8;
325 out.resize(outlength);
326 unsigned char* out_ = outlength ? &out[0] : 0;
327 if (info.interlaceMethod == 0)
329 size_t linestart = 0, linelength = (info.width * bpp + 7) / 8;
331 for (
unsigned long y = 0; y < info.height; y++)
333 unsigned long filterType = scanlines[linestart];
334 const unsigned char* prevline = (y == 0) ? 0 : &out_[(y - 1) * info.width * bytewidth];
335 unFilterScanline(&out_[linestart - y], &scanlines[linestart + 1], prevline, bytewidth, filterType, linelength);
if (error)
return;
336 linestart += (1 + linelength);
340 std::vector<unsigned char> templine((info.width * bpp + 7) >> 3);
341 for (
size_t y = 0, obp = 0; y < info.height; y++)
343 unsigned long filterType = scanlines[linestart];
344 const unsigned char* prevline = (y == 0) ? 0 : &out_[(y - 1) * info.width * bytewidth];
345 unFilterScanline(&templine[0], &scanlines[linestart + 1], prevline, bytewidth, filterType, linelength);
if (error)
return;
346 for (
size_t bp = 0; bp < info.width * bpp;) setBitOfReversedStream(obp, out_, readBitFromReversedStream(bp, &templine[0]));
347 linestart += (1 + linelength);
353 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 };
354 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 };
355 size_t passstart[7] = { 0 };
356 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 };
357 for (
int i = 0; i < 6; i++) passstart[i + 1] = passstart[i] + passh[i] * ((passw[i] ? 1 : 0) + (passw[i] * bpp + 7) / 8);
358 std::vector<unsigned char> scanlineo((info.width * bpp + 7) / 8), scanlinen((info.width * bpp + 7) / 8);
359 for (
int i = 0; i < 7; i++)
360 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);
362 if (convert_to_rgba32 && (info.colorType != 6 || info.bitDepth != 8))
364 std::vector<unsigned char> data = out;
365 error = convert(out, &data[0], info, info.width, info.height);
368 void readPngHeader(
const unsigned char* in,
size_t inlength)
370 if (inlength < 29) { error = 27;
return; }
371 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; }
372 if (in[12] !=
'I' || in[13] !=
'H' || in[14] !=
'D' || in[15] !=
'R') { error = 29;
return; }
373 info.width = read32bitInt(&in[16]); info.height = read32bitInt(&in[20]);
374 info.bitDepth = in[24]; info.colorType = in[25];
375 info.compressionMethod = in[26];
if (in[26] != 0) { error = 32;
return; }
376 info.filterMethod = in[27];
if (in[27] != 0) { error = 33;
return; }
377 info.interlaceMethod = in[28];
if (in[28] > 1) { error = 34;
return; }
378 error = checkColorValidity(info.colorType, info.bitDepth);
380 void unFilterScanline(
unsigned char* recon,
const unsigned char* scanline,
const unsigned char* precon,
size_t bytewidth,
unsigned long filterType,
size_t length)
384 case 0:
for (
size_t i = 0; i < length; i++) recon[i] = scanline[i];
break;
386 for (
size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i];
387 for (
size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + recon[i - bytewidth];
390 if (precon)
for (
size_t i = 0; i < length; i++) recon[i] = scanline[i] + precon[i];
391 else for (
size_t i = 0; i < length; i++) recon[i] = scanline[i];
396 for (
size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i] + precon[i] / 2;
397 for (
size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + ((recon[i - bytewidth] + precon[i]) / 2);
401 for (
size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i];
402 for (
size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + recon[i - bytewidth] / 2;
408 for (
size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i] + paethPredictor(0, precon[i], 0);
409 for (
size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth]);
413 for (
size_t i = 0; i < bytewidth; i++) recon[i] = scanline[i];
414 for (
size_t i = bytewidth; i < length; i++) recon[i] = scanline[i] + paethPredictor(recon[i - bytewidth], 0, 0);
417 default: error = 36;
return;
420 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)
422 if (passw == 0)
return;
423 size_t bytewidth = (bpp + 7) / 8, linelength = 1 + ((bpp * passw + 7) / 8);
424 for (
unsigned long y = 0; y < passh; y++)
426 unsigned char filterType = in[y * linelength], * prevline = (y == 0) ? 0 : lineo;
427 unFilterScanline(linen, &in[y * linelength + 1], prevline, bytewidth, filterType, (w * bpp + 7) / 8);
if (error)
return;
428 if (bpp >= 8)
for (
size_t i = 0; i < passw; i++)
for (
size_t b = 0; b < bytewidth; b++)
429 out[bytewidth * w * (passtop + spacey * y) + bytewidth * (passleft + spacex * i) + b] = linen[bytewidth * i + b];
430 else for (
size_t i = 0; i < passw; i++)
432 size_t obp = bpp * w * (passtop + spacey * y) + bpp * (passleft + spacex * i), bp = i * bpp;
433 for (
size_t b = 0; b < bpp; b++) setBitOfReversedStream(obp, out, readBitFromReversedStream(bp, &linen[0]));
435 unsigned char* temp = linen; linen = lineo; lineo = temp;
438 static unsigned long readBitFromReversedStream(
size_t& bitp,
const unsigned char* bits) {
unsigned long result = (bits[bitp >> 3] >> (7 - (bitp & 0x7))) & 1; bitp++;
return result; }
439 static unsigned long readBitsFromReversedStream(
size_t& bitp,
const unsigned char* bits,
unsigned long nbits)
441 unsigned long result = 0;
442 for (
size_t i = nbits - 1; i < nbits; i--) result += ((readBitFromReversedStream(bitp, bits)) << i);
445 void setBitOfReversedStream(
size_t& bitp,
unsigned char* bits,
unsigned long bit) { bits[bitp >> 3] |= (bit << (7 - (bitp & 0x7))); bitp++; }
446 unsigned long read32bitInt(
const unsigned char* buffer) {
return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]; }
447 int checkColorValidity(
unsigned long colorType,
unsigned long bd)
449 if ((colorType == 2 || colorType == 4 || colorType == 6)) {
if (!(bd == 8 || bd == 16))
return 37;
else return 0; }
450 else if (colorType == 0) {
if (!(bd == 1 || bd == 2 || bd == 4 || bd == 8 || bd == 16))
return 37;
else return 0; }
451 else if (colorType == 3) {
if (!(bd == 1 || bd == 2 || bd == 4 || bd == 8))
return 37;
else return 0; }
454 unsigned long getBpp(
const Info& info)
456 if (info.colorType == 2)
return (3 * info.bitDepth);
457 else if (info.colorType >= 4)
return (info.colorType - 2) * info.bitDepth;
458 else return info.bitDepth;
460 int convert(std::vector<unsigned char>& out,
const unsigned char* in, Info& infoIn,
unsigned long w,
unsigned long h)
462 size_t numpixels = w * h, bp = 0;
463 out.resize(numpixels * 4);
464 unsigned char* out_ = out.empty() ? 0 : &out[0];
465 if (infoIn.bitDepth == 8 && infoIn.colorType == 0)
466 for (
size_t i = 0; i < numpixels; i++)
468 out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[i];
469 out_[4 * i + 3] = (infoIn.key_defined && in[i] == infoIn.key_r) ? 0 : 255;
471 else if (infoIn.bitDepth == 8 && infoIn.colorType == 2)
472 for (
size_t i = 0; i < numpixels; i++)
474 for (
size_t c = 0; c < 3; c++) out_[4 * i + c] = in[3 * i + c];
475 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;
477 else if (infoIn.bitDepth == 8 && infoIn.colorType == 3)
478 for (
size_t i = 0; i < numpixels; i++)
480 if (4U * in[i] >= infoIn.palette.size())
return 46;
481 for (
size_t c = 0; c < 4; c++) out_[4 * i + c] = infoIn.palette[4 * in[i] + c];
483 else if (infoIn.bitDepth == 8 && infoIn.colorType == 4)
484 for (
size_t i = 0; i < numpixels; i++)
486 out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[2 * i + 0];
487 out_[4 * i + 3] = in[2 * i + 1];
489 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];
490 else if (infoIn.bitDepth == 16 && infoIn.colorType == 0)
491 for (
size_t i = 0; i < numpixels; i++)
493 out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[2 * i];
494 out_[4 * i + 3] = (infoIn.key_defined && 256U * in[i] + in[i + 1] == infoIn.key_r) ? 0 : 255;
496 else if (infoIn.bitDepth == 16 && infoIn.colorType == 2)
497 for (
size_t i = 0; i < numpixels; i++)
499 for (
size_t c = 0; c < 3; c++) out_[4 * i + c] = in[6 * i + 2 * c];
500 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;
502 else if (infoIn.bitDepth == 16 && infoIn.colorType == 4)
503 for (
size_t i = 0; i < numpixels; i++)
505 out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = in[4 * i];
506 out_[4 * i + 3] = in[4 * i + 2];
508 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];
509 else if (infoIn.bitDepth < 8 && infoIn.colorType == 0)
510 for (
size_t i = 0; i < numpixels; i++)
512 unsigned long value = (readBitsFromReversedStream(bp, in, infoIn.bitDepth) * 255) / ((1 << infoIn.bitDepth) - 1);
513 out_[4 * i + 0] = out_[4 * i + 1] = out_[4 * i + 2] = (
unsigned char)(value);
514 out_[4 * i + 3] = (infoIn.key_defined && value && ((1U << infoIn.bitDepth) - 1U) == infoIn.key_r && ((1U << infoIn.bitDepth) - 1U)) ? 0 : 255;
516 else if (infoIn.bitDepth < 8 && infoIn.colorType == 3)
517 for (
size_t i = 0; i < numpixels; i++)
519 unsigned long value = readBitsFromReversedStream(bp, in, infoIn.bitDepth);
520 if (4 * value >= infoIn.palette.size())
return 47;
521 for (
size_t c = 0; c < 4; c++) out_[4 * i + c] = infoIn.palette[4 * value + c];
525 unsigned char paethPredictor(
short a,
short b,
short c)
527 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);
528 return (
unsigned char)((pa <= pb && pa <= pc) ? a : pb <= pc ? b : c);
531 PNG decoder; decoder.decode(out_image, in_png, in_size, convert_to_rgba32);
532 image_width = decoder.info.width; image_height = decoder.info.height;
533 return decoder.error;