Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- zlib.inflate(this.imgData, function(err, data) {
- var byte, c, col, i, left, length, p, pa, paeth, pb, pc, pixelBytes, pixels, pos, row, scanlineLength, upper, upperLeft;
- if (err) throw err;
- pixelBytes = _this.pixelBitlength / 8;
- scanlineLength = pixelBytes * _this.width;
- pixels = new Buffer(scanlineLength * _this.height);
- length = data.length;
- row = 0;
- pos = 0;
- c = 0;
- while (pos < length) {
- switch (data[pos++]) {
- case 0:
- for (i = 0; i < scanlineLength; i += 1) {
- pixels[c++] = data[pos++];
- }
- break;
- case 1:
- for (i = 0; i < scanlineLength; i += 1) {
- byte = data[pos++];
- left = i < pixelBytes ? 0 : pixels[c - pixelBytes];
- pixels[c++] = (byte + left) % 256;
- }
- break;
- case 2:
- for (i = 0; i < scanlineLength; i += 1) {
- byte = data[pos++];
- col = (i - (i % pixelBytes)) / pixelBytes;
- upper = row && pixels[(row - 1) * scanlineLength + col * pixelBytes + (i % pixelBytes)];
- pixels[c++] = (upper + byte) % 256;
- }
- break;
- case 3:
- for (i = 0; i < scanlineLength; i += 1) {
- byte = data[pos++];
- col = (i - (i % pixelBytes)) / pixelBytes;
- left = i < pixelBytes ? 0 : pixels[c - pixelBytes];
- upper = row && pixels[(row - 1) * scanlineLength + col * pixelBytes + (i % pixelBytes)];
- pixels[c++] = (byte + Math.floor((left + upper) / 2)) % 256;
- }
- break;
- case 4:
- for (i = 0; i < scanlineLength; i += 1) {
- byte = data[pos++];
- col = (i - (i % pixelBytes)) / pixelBytes;
- left = i < pixelBytes ? 0 : pixels[c - pixelBytes];
- if (row === 0) {
- upper = upperLeft = 0;
- } else {
- upper = pixels[(row - 1) * scanlineLength + col * pixelBytes + (i % pixelBytes)];
- upperLeft = col && pixels[(row - 1) * scanlineLength + (col - 1) * pixelBytes + (i % pixelBytes)];
- }
- p = left + upper - upperLeft;
- pa = Math.abs(p - left);
- pb = Math.abs(p - upper);
- pc = Math.abs(p - upperLeft);
- if (pa <= pb && pa <= pc) {
- paeth = left;
- } else if (pb <= pc) {
- paeth = upper;
- } else {
- paeth = upperLeft;
- }
- pixels[c++] = (byte + paeth) % 256;
- }
- break;
- default:
- throw new Error("Invalid filter algorithm: " + data[pos - 1]);
- }
- row++;
- }
- callback(pixels);
- });
- unsigned png_postProcessScanlines(unsigned char* out, unsigned char* in, unsigned w, unsigned h, const void* info_png){
- unsigned err;
- /* This function converts the filtered-padded-interlaced data into pure 2D image buffer with the PNG's colortype.
- Steps:
- *) if no Adam7: 1) unfilter 2) remove padding bits (= posible extra bits per scanline if bpp < 8)
- *) if adam7: 1) 7x unfilter 2) 7x remove padding bits 3) Adam7_deinterlace
- NOTE: the in buffer will be overwritten with intermediate data! */
- //2017
- unsigned bpp = png_getBpp();//lodepng_get_bpp(&info_png->color);
- //2017 if(bpp == 0) return 31; /*error: invalid colortype*/
- if(interlace_method == 0){
- if(bpp < 8 && w * bpp != ((w * bpp + 7) / 8) * 8){
- if ((err=png_unfilter(in, in, w, h, bpp))!=0) return err;
- png_removePaddingBits(out, in, w * bpp, ((w * bpp + 7) / 8) * 8, h);
- }
- /*we can immediatly filter into the out buffer, no other steps needed*/
- else if ((err=png_unfilter(out, in, w, h, bpp))!=0) return err;
- }
- else /*interlace_method is 1 (Adam7)*/
- {
- unsigned passw[7], passh[7]; size_t filter_passstart[8], padded_passstart[8], passstart[8];
- unsigned i,j;
- png_Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp);
- for(i = 0; i < 7; i++)
- {
- if ((err=png_unfilter(&in[padded_passstart[i]], &in[filter_passstart[i]], passw[i], passh[i], bpp))!=0) return err;
- /*TODO: possible efficiency improvement: if in this reduced image the bits fit nicely in 1 scanline,
- move bytes instead of bits or move not at all*/
- if(bpp < 8)
- {
- /*remove padding bits in scanlines; after this there still may be padding
- bits between the different reduced images: each reduced image still starts nicely at a byte*/
- png_removePaddingBits(&in[passstart[i]], &in[padded_passstart[i]], passw[i] * bpp,
- ((passw[i] * bpp + 7) / 8) * 8, passh[i]);
- }
- }
- png_Adam7_deinterlace(out, in, w, h, bpp);
- }
- return 0;
- }
- int png_getBpp(){
- //return getNumColorChannels(colortype) * bitdepth;
- switch(/*colortype*/ data.png.characteristics[1]/*Байт 0x19 с файла png*/){ /* [0]=bitdepth*/
- case 0: return 1 * data.png.characteristics[0];/*Байт 0x18 с файла png*/ /*grey*/
- case 2: return 3 * data.png.characteristics[0]; /*RGB*/
- case 3: return 1 * data.png.characteristics[0]; /*palette*/
- case 4: return 2 * data.png.characteristics[0]; /*grey + alpha*/
- case 6: return 4 * data.png.characteristics[0]; /*RGBA*/
- }
- unsigned png_unfilter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp){
- /*
- For PNG filter method 0
- this function unfilters a single image (e.g. without interlacing this is called once, with Adam7 seven times)
- out must have enough bytes allocated already, in must have the scanlines + 1 filtertype byte per scanline
- w and h are image dimensions or dimensions of reduced image, bpp is bits per pixel
- in and out are allowed to be the same memory address (but aren't the same size since in has the extra filter bytes)
- */
- unsigned y;
- unsigned char* prevline = 0;
- unsigned err = 0;
- /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/
- size_t bytewidth = (bpp + 7) / 8;
- size_t linebytes = (w * bpp + 7) / 8;
- size_t i;
- for(y = 0; y < h; y++)
- {
- size_t outindex = linebytes * y;
- size_t inindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/
- unsigned char filterType = in[inindex];
- //__emit__(0xCC);
- //if ((err=png_unfilterScanline(&out[outindex], &in[inindex + 1], prevline, bytewidth, filterType, linebytes))!=0) return err;
- unsigned char* recon = out + outindex;
- const unsigned char* scanline = in + inindex + 1;
- const unsigned char* precon = prevline;
- size_t length = linebytes;
- //unsigned char* recon, const unsigned char* scanline, const unsigned char* precon, size_t bytewidth, unsigned char filterType, size_t length
- switch(filterType)
- {
- case 0: for(i = 0; i < length; i++) recon[i] = scanline[i]; break;
- case 1:
- for(i = 0; i < bytewidth; i++) recon[i] = scanline[i];
- for(i = bytewidth; i < length; i++) recon[i] = scanline[i] + recon[i - bytewidth];
- break;
- case 2:
- if(precon)
- for(i = 0; i < length; i++) recon[i] = scanline[i] + precon[i];
- else for(i = 0; i < length; i++) recon[i] = scanline[i];
- break;
- case 3:
- if(precon)
- {
- for(i = 0; i < bytewidth; i++) recon[i] = scanline[i] + precon[i] / 2;
- for(i = bytewidth; i < length; i++) recon[i] = scanline[i] + ((recon[i - bytewidth] + precon[i]) / 2);
- }
- else
- {
- for(i = 0; i < bytewidth; i++) recon[i] = scanline[i];
- for(i = bytewidth; i < length; i++) recon[i] = scanline[i] + recon[i - bytewidth] / 2;
- }
- break;
- case 4:
- if(precon)
- {
- for(i = 0; i < bytewidth; i++)
- recon[i] = (scanline[i] + precon[i]); /*paethPredictor(0, precon[i], 0) is always precon[i]*/
- for(i = bytewidth; i < length; i++)
- recon[i] = (scanline[i] + png_paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth]));
- }
- else
- {
- for(i = 0; i < bytewidth; i++)
- recon[i] = scanline[i];
- for(i = bytewidth; i < length; i++)
- /*paethPredictor(recon[i - bytewidth], 0, 0) is always recon[i - bytewidth]*/
- recon[i] = (scanline[i] + recon[i - bytewidth]);
- }
- break;
- default: return 36; /*error: unexisting filter type given*/
- }
- prevline = &out[outindex];
- }
- return 0;
- }
- unsigned png_removePaddingBits(unsigned char* out, const unsigned char* in, size_t olinebits, size_t ilinebits, unsigned h)
- {
- unsigned y;
- unsigned char bit;
- size_t diff = ilinebits - olinebits;
- size_t ibp = 0, obp = 0; /*input and output bit pointers*/
- for(y = 0; y < h; y++)
- {
- size_t x;
- for(x = 0; x < olinebits; x++){
- //bit = in[ibp >> 3 ] & (1>> (7- (ibp & 7))); //unsigned char bit = readBitFromReversedStream(&ibp, in);
- //if (bit) out[obp >> 3] |= (1>> (7- (obp & 7))); //setBitOfReversedStream(&obp, out, bit);
- if (in[ibp >> 3 ] & (1>> (7- (ibp & 7)))) out[obp >> 3] |= (1>> (7- (obp & 7)));
- ibp++; obp++;
- }
- ibp += diff;
- }
- }
- static const unsigned char ADAM7_IX[7] = {0,4,0,2,0,1,0};
- static const unsigned char ADAM7_IY[7] = {0,0,4,0,2,0,1};
- static const unsigned char ADAM7_DX[7] = {8,8,4,4,2,2,1};
- static const unsigned char ADAM7_DY[7] = {8,8,8,4,4,2,2};
- void png_Adam7_getpassvalues(unsigned passw[7], unsigned passh[7], size_t filter_passstart[8], size_t padded_passstart[8], size_t passstart[8], unsigned w, unsigned h, unsigned bpp)
- { unsigned i; /*Свернул циклы в define*/
- /*calculate width and height in pixels of each pass*/
- #define PNG_AD71L(i) if((passw[i]=(w+ (4-(i/2))*2 - ((i&1)*( (5-i)+ (i==5))) - 1 ) / ((4-(i/2))*2) )==0)passh[0]=0;
- else if((passh[i]=(h+ (i<3)?8:(8-((i+1)&6)) - (i==2)?4:((i==4)?2:(i==6)?1:0) -1 ) / ((i<3)?8:(8-((i+1)&6))))==0)passw[0]=0;
- PNG_AD71L(0); PNG_AD71L(1); PNG_AD71L(2); PNG_AD71L(3); PNG_AD71L(4); PNG_AD71L(5); PNG_AD71L(6);
- filter_passstart[0] = padded_passstart[0] = passstart[0] = 0;
- #undef PNG_ADL71L
- #define PNG_ADL71L(i) filter_passstart[i + 1] = filter_passstart[i]+ ((passw[i] && passh[i]) ? passh[i] * (1 + (passw[i] * bpp + 7) / 8) : 0);/*if passw[i] is 0, it's 0 bytes, not 1 (no filtertype-byte)*/
- padded_passstart[i + 1] = padded_passstart[i] + passh[i] * ((passw[i] * bpp + 7) / 8);/*bits padded if needed to fill full byte at end of each scanline*/
- passstart[i + 1] = passstart[i] + (passh[i] * passw[i] * bpp + 7) / 8; /*only padded at end of reduced image*/
- PNG_AD71L(0); PNG_AD71L(1); PNG_AD71L(2); PNG_AD71L(3); PNG_AD71L(4); PNG_AD71L(5); PNG_AD71L(6);
- #undef PNG_ADL71L
- }
- void png_Adam7_deinterlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp)
- {
- unsigned passw[7], passh[7];
- size_t filter_passstart[8], padded_passstart[8], passstart[8];
- unsigned i;
- png_Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp);
- if(bpp >= 8)
- {
- for(i = 0; i < 7; i++)
- {
- unsigned x, y, b;
- size_t bytewidth = bpp / 8;
- for(y = 0; y < passh[i]; y++)
- for(x = 0; x < passw[i]; x++)
- {
- size_t pixelinstart = passstart[i] + (y * passw[i] + x) * bytewidth;
- size_t pixeloutstart = ((ADAM7_IY[i] + y * ADAM7_DY[i]) * w + ADAM7_IX[i] + x * ADAM7_DX[i]) * bytewidth;
- for(b = 0; b < bytewidth; b++)
- out[pixeloutstart + b] = in[pixelinstart + b];
- }
- }
- }
- else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/
- {
- for(i = 0; i < 7; i++)
- {
- unsigned x, y, b;
- unsigned ilinebits = bpp * passw[i];
- unsigned olinebits = bpp * w;
- size_t obp, ibp; /*bit pointers (for out and in buffer)*/
- for(y = 0; y < passh[i]; y++)
- for(x = 0; x < passw[i]; x++)
- {
- ibp = (8 * passstart[i]) + (y * ilinebits + x * bpp);
- obp = (ADAM7_IY[i] + y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + x * ADAM7_DX[i]) * bpp;
- for(b = 0; b < bpp; b++)
- {
- //unsigned char bit = readBitFromReversedStream(&ibp, in);
- /*note that this function assumes the out buffer is completely 0, use setBitOfReversedStream otherwise*/
- //setBitOfReversedStream0(&obp, out, bit);
- if (in[ibp >> 3 ] & (1>> (7- (ibp & 7)))) out[obp >> 3] |= (1>> (7- (obp & 7)));
- ibp++; obp++;
- }
- }
- }
- }
- }
- unsigned char png_paethPredictor(short a, short b, short c){
- short pa = abs(b - c);
- short pb = abs(a - c);
- short pc = abs(a + b - c - c);
- if(pc < pa && pc < pb) return (unsigned char)c;
- return (pb < pa)?(unsigned char)b:(unsigned char)a;
- }
Add Comment
Please, Sign In to add comment