Guest User

Untitled

a guest
Jan 18th, 2018
90
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.86 KB | None | 0 0
  1. zlib.inflate(this.imgData, function(err, data) {
  2. var byte, c, col, i, left, length, p, pa, paeth, pb, pc, pixelBytes, pixels, pos, row, scanlineLength, upper, upperLeft;
  3. if (err) throw err;
  4. pixelBytes = _this.pixelBitlength / 8;
  5. scanlineLength = pixelBytes * _this.width;
  6. pixels = new Buffer(scanlineLength * _this.height);
  7. length = data.length;
  8. row = 0;
  9. pos = 0;
  10. c = 0;
  11. while (pos < length) {
  12. switch (data[pos++]) {
  13. case 0:
  14. for (i = 0; i < scanlineLength; i += 1) {
  15. pixels[c++] = data[pos++];
  16. }
  17. break;
  18.  
  19. case 1:
  20. for (i = 0; i < scanlineLength; i += 1) {
  21. byte = data[pos++];
  22. left = i < pixelBytes ? 0 : pixels[c - pixelBytes];
  23. pixels[c++] = (byte + left) % 256;
  24. }
  25. break;
  26.  
  27. case 2:
  28. for (i = 0; i < scanlineLength; i += 1) {
  29. byte = data[pos++];
  30. col = (i - (i % pixelBytes)) / pixelBytes;
  31. upper = row && pixels[(row - 1) * scanlineLength + col * pixelBytes + (i % pixelBytes)];
  32. pixels[c++] = (upper + byte) % 256;
  33. }
  34. break;
  35.  
  36. case 3:
  37. for (i = 0; i < scanlineLength; i += 1) {
  38. byte = data[pos++];
  39. col = (i - (i % pixelBytes)) / pixelBytes;
  40. left = i < pixelBytes ? 0 : pixels[c - pixelBytes];
  41. upper = row && pixels[(row - 1) * scanlineLength + col * pixelBytes + (i % pixelBytes)];
  42. pixels[c++] = (byte + Math.floor((left + upper) / 2)) % 256;
  43. }
  44. break;
  45.  
  46. case 4:
  47. for (i = 0; i < scanlineLength; i += 1) {
  48. byte = data[pos++];
  49. col = (i - (i % pixelBytes)) / pixelBytes;
  50. left = i < pixelBytes ? 0 : pixels[c - pixelBytes];
  51. if (row === 0) {
  52. upper = upperLeft = 0;
  53. } else {
  54. upper = pixels[(row - 1) * scanlineLength + col * pixelBytes + (i % pixelBytes)];
  55. upperLeft = col && pixels[(row - 1) * scanlineLength + (col - 1) * pixelBytes + (i % pixelBytes)];
  56. }
  57. p = left + upper - upperLeft;
  58. pa = Math.abs(p - left);
  59. pb = Math.abs(p - upper);
  60. pc = Math.abs(p - upperLeft);
  61. if (pa <= pb && pa <= pc) {
  62. paeth = left;
  63. } else if (pb <= pc) {
  64. paeth = upper;
  65. } else {
  66. paeth = upperLeft;
  67. }
  68. pixels[c++] = (byte + paeth) % 256;
  69. }
  70. break;
  71. default:
  72. throw new Error("Invalid filter algorithm: " + data[pos - 1]);
  73. }
  74. row++;
  75. }
  76. callback(pixels);
  77. });
  78.  
  79. unsigned png_postProcessScanlines(unsigned char* out, unsigned char* in, unsigned w, unsigned h, const void* info_png){
  80. unsigned err;
  81. /* This function converts the filtered-padded-interlaced data into pure 2D image buffer with the PNG's colortype.
  82. Steps:
  83. *) if no Adam7: 1) unfilter 2) remove padding bits (= posible extra bits per scanline if bpp < 8)
  84. *) if adam7: 1) 7x unfilter 2) 7x remove padding bits 3) Adam7_deinterlace
  85. NOTE: the in buffer will be overwritten with intermediate data! */
  86. //2017
  87. unsigned bpp = png_getBpp();//lodepng_get_bpp(&info_png->color);
  88. //2017 if(bpp == 0) return 31; /*error: invalid colortype*/
  89.  
  90. if(interlace_method == 0){
  91. if(bpp < 8 && w * bpp != ((w * bpp + 7) / 8) * 8){
  92. if ((err=png_unfilter(in, in, w, h, bpp))!=0) return err;
  93. png_removePaddingBits(out, in, w * bpp, ((w * bpp + 7) / 8) * 8, h);
  94. }
  95. /*we can immediatly filter into the out buffer, no other steps needed*/
  96. else if ((err=png_unfilter(out, in, w, h, bpp))!=0) return err;
  97. }
  98. else /*interlace_method is 1 (Adam7)*/
  99. {
  100. unsigned passw[7], passh[7]; size_t filter_passstart[8], padded_passstart[8], passstart[8];
  101. unsigned i,j;
  102. png_Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp);
  103. for(i = 0; i < 7; i++)
  104. {
  105. if ((err=png_unfilter(&in[padded_passstart[i]], &in[filter_passstart[i]], passw[i], passh[i], bpp))!=0) return err;
  106. /*TODO: possible efficiency improvement: if in this reduced image the bits fit nicely in 1 scanline,
  107. move bytes instead of bits or move not at all*/
  108. if(bpp < 8)
  109. {
  110. /*remove padding bits in scanlines; after this there still may be padding
  111. bits between the different reduced images: each reduced image still starts nicely at a byte*/
  112. png_removePaddingBits(&in[passstart[i]], &in[padded_passstart[i]], passw[i] * bpp,
  113. ((passw[i] * bpp + 7) / 8) * 8, passh[i]);
  114. }
  115. }
  116. png_Adam7_deinterlace(out, in, w, h, bpp);
  117. }
  118. return 0;
  119. }
  120.  
  121. int png_getBpp(){
  122. //return getNumColorChannels(colortype) * bitdepth;
  123. switch(/*colortype*/ data.png.characteristics[1]/*Байт 0x19 с файла png*/){ /* [0]=bitdepth*/
  124. case 0: return 1 * data.png.characteristics[0];/*Байт 0x18 с файла png*/ /*grey*/
  125. case 2: return 3 * data.png.characteristics[0]; /*RGB*/
  126. case 3: return 1 * data.png.characteristics[0]; /*palette*/
  127. case 4: return 2 * data.png.characteristics[0]; /*grey + alpha*/
  128. case 6: return 4 * data.png.characteristics[0]; /*RGBA*/
  129. }
  130.  
  131. unsigned png_unfilter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp){
  132. /*
  133. For PNG filter method 0
  134. this function unfilters a single image (e.g. without interlacing this is called once, with Adam7 seven times)
  135. out must have enough bytes allocated already, in must have the scanlines + 1 filtertype byte per scanline
  136. w and h are image dimensions or dimensions of reduced image, bpp is bits per pixel
  137. in and out are allowed to be the same memory address (but aren't the same size since in has the extra filter bytes)
  138. */
  139. unsigned y;
  140. unsigned char* prevline = 0;
  141. unsigned err = 0;
  142. /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/
  143. size_t bytewidth = (bpp + 7) / 8;
  144. size_t linebytes = (w * bpp + 7) / 8;
  145. size_t i;
  146.  
  147. for(y = 0; y < h; y++)
  148. {
  149. size_t outindex = linebytes * y;
  150. size_t inindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/
  151. unsigned char filterType = in[inindex];
  152. //__emit__(0xCC);
  153. //if ((err=png_unfilterScanline(&out[outindex], &in[inindex + 1], prevline, bytewidth, filterType, linebytes))!=0) return err;
  154. unsigned char* recon = out + outindex;
  155. const unsigned char* scanline = in + inindex + 1;
  156. const unsigned char* precon = prevline;
  157. size_t length = linebytes;
  158. //unsigned char* recon, const unsigned char* scanline, const unsigned char* precon, size_t bytewidth, unsigned char filterType, size_t length
  159.  
  160. switch(filterType)
  161. {
  162. case 0: for(i = 0; i < length; i++) recon[i] = scanline[i]; break;
  163. case 1:
  164. for(i = 0; i < bytewidth; i++) recon[i] = scanline[i];
  165. for(i = bytewidth; i < length; i++) recon[i] = scanline[i] + recon[i - bytewidth];
  166. break;
  167. case 2:
  168. if(precon)
  169. for(i = 0; i < length; i++) recon[i] = scanline[i] + precon[i];
  170. else for(i = 0; i < length; i++) recon[i] = scanline[i];
  171. break;
  172. case 3:
  173. if(precon)
  174. {
  175. for(i = 0; i < bytewidth; i++) recon[i] = scanline[i] + precon[i] / 2;
  176. for(i = bytewidth; i < length; i++) recon[i] = scanline[i] + ((recon[i - bytewidth] + precon[i]) / 2);
  177. }
  178. else
  179. {
  180. for(i = 0; i < bytewidth; i++) recon[i] = scanline[i];
  181. for(i = bytewidth; i < length; i++) recon[i] = scanline[i] + recon[i - bytewidth] / 2;
  182. }
  183. break;
  184. case 4:
  185. if(precon)
  186. {
  187. for(i = 0; i < bytewidth; i++)
  188. recon[i] = (scanline[i] + precon[i]); /*paethPredictor(0, precon[i], 0) is always precon[i]*/
  189. for(i = bytewidth; i < length; i++)
  190. recon[i] = (scanline[i] + png_paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth]));
  191. }
  192. else
  193. {
  194. for(i = 0; i < bytewidth; i++)
  195. recon[i] = scanline[i];
  196. for(i = bytewidth; i < length; i++)
  197. /*paethPredictor(recon[i - bytewidth], 0, 0) is always recon[i - bytewidth]*/
  198. recon[i] = (scanline[i] + recon[i - bytewidth]);
  199. }
  200. break;
  201. default: return 36; /*error: unexisting filter type given*/
  202. }
  203. prevline = &out[outindex];
  204. }
  205. return 0;
  206. }
  207.  
  208.  
  209. unsigned png_removePaddingBits(unsigned char* out, const unsigned char* in, size_t olinebits, size_t ilinebits, unsigned h)
  210. {
  211. unsigned y;
  212. unsigned char bit;
  213. size_t diff = ilinebits - olinebits;
  214. size_t ibp = 0, obp = 0; /*input and output bit pointers*/
  215. for(y = 0; y < h; y++)
  216. {
  217. size_t x;
  218. for(x = 0; x < olinebits; x++){
  219. //bit = in[ibp >> 3 ] & (1>> (7- (ibp & 7))); //unsigned char bit = readBitFromReversedStream(&ibp, in);
  220. //if (bit) out[obp >> 3] |= (1>> (7- (obp & 7))); //setBitOfReversedStream(&obp, out, bit);
  221. if (in[ibp >> 3 ] & (1>> (7- (ibp & 7)))) out[obp >> 3] |= (1>> (7- (obp & 7)));
  222. ibp++; obp++;
  223. }
  224. ibp += diff;
  225. }
  226. }
  227.  
  228. static const unsigned char ADAM7_IX[7] = {0,4,0,2,0,1,0};
  229. static const unsigned char ADAM7_IY[7] = {0,0,4,0,2,0,1};
  230. static const unsigned char ADAM7_DX[7] = {8,8,4,4,2,2,1};
  231. static const unsigned char ADAM7_DY[7] = {8,8,8,4,4,2,2};
  232.  
  233. 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)
  234. { unsigned i; /*Свернул циклы в define*/
  235. /*calculate width and height in pixels of each pass*/
  236. #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;
  237. 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;
  238. PNG_AD71L(0); PNG_AD71L(1); PNG_AD71L(2); PNG_AD71L(3); PNG_AD71L(4); PNG_AD71L(5); PNG_AD71L(6);
  239. filter_passstart[0] = padded_passstart[0] = passstart[0] = 0;
  240. #undef PNG_ADL71L
  241. #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)*/
  242. 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*/
  243. passstart[i + 1] = passstart[i] + (passh[i] * passw[i] * bpp + 7) / 8; /*only padded at end of reduced image*/
  244. PNG_AD71L(0); PNG_AD71L(1); PNG_AD71L(2); PNG_AD71L(3); PNG_AD71L(4); PNG_AD71L(5); PNG_AD71L(6);
  245. #undef PNG_ADL71L
  246. }
  247.  
  248. void png_Adam7_deinterlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp)
  249. {
  250. unsigned passw[7], passh[7];
  251. size_t filter_passstart[8], padded_passstart[8], passstart[8];
  252. unsigned i;
  253. png_Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp);
  254. if(bpp >= 8)
  255. {
  256. for(i = 0; i < 7; i++)
  257. {
  258. unsigned x, y, b;
  259. size_t bytewidth = bpp / 8;
  260. for(y = 0; y < passh[i]; y++)
  261. for(x = 0; x < passw[i]; x++)
  262. {
  263. size_t pixelinstart = passstart[i] + (y * passw[i] + x) * bytewidth;
  264. size_t pixeloutstart = ((ADAM7_IY[i] + y * ADAM7_DY[i]) * w + ADAM7_IX[i] + x * ADAM7_DX[i]) * bytewidth;
  265. for(b = 0; b < bytewidth; b++)
  266. out[pixeloutstart + b] = in[pixelinstart + b];
  267. }
  268. }
  269. }
  270. else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/
  271. {
  272. for(i = 0; i < 7; i++)
  273. {
  274. unsigned x, y, b;
  275. unsigned ilinebits = bpp * passw[i];
  276. unsigned olinebits = bpp * w;
  277. size_t obp, ibp; /*bit pointers (for out and in buffer)*/
  278. for(y = 0; y < passh[i]; y++)
  279. for(x = 0; x < passw[i]; x++)
  280. {
  281. ibp = (8 * passstart[i]) + (y * ilinebits + x * bpp);
  282. obp = (ADAM7_IY[i] + y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + x * ADAM7_DX[i]) * bpp;
  283. for(b = 0; b < bpp; b++)
  284. {
  285. //unsigned char bit = readBitFromReversedStream(&ibp, in);
  286. /*note that this function assumes the out buffer is completely 0, use setBitOfReversedStream otherwise*/
  287. //setBitOfReversedStream0(&obp, out, bit);
  288. if (in[ibp >> 3 ] & (1>> (7- (ibp & 7)))) out[obp >> 3] |= (1>> (7- (obp & 7)));
  289. ibp++; obp++;
  290. }
  291. }
  292. }
  293. }
  294. }
  295.  
  296. unsigned char png_paethPredictor(short a, short b, short c){
  297. short pa = abs(b - c);
  298. short pb = abs(a - c);
  299. short pc = abs(a + b - c - c);
  300. if(pc < pa && pc < pb) return (unsigned char)c;
  301. return (pb < pa)?(unsigned char)b:(unsigned char)a;
  302. }
Add Comment
Please, Sign In to add comment