pixel-match.js 66 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673
  1. 'use strict';
  2. var fs = require('fs');
  3. var util = require('util');
  4. var Stream = require('stream');
  5. var zlib = require('zlib');
  6. var require$$0 = require('assert');
  7. var require$$1 = require('buffer');
  8. function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
  9. var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
  10. var util__default = /*#__PURE__*/_interopDefaultLegacy(util);
  11. var Stream__default = /*#__PURE__*/_interopDefaultLegacy(Stream);
  12. var zlib__default = /*#__PURE__*/_interopDefaultLegacy(zlib);
  13. var require$$0__default = /*#__PURE__*/_interopDefaultLegacy(require$$0);
  14. var require$$1__default = /*#__PURE__*/_interopDefaultLegacy(require$$1);
  15. var pixelmatch_1 = pixelmatch;
  16. function pixelmatch(img1, img2, output, width, height, options) {
  17. if (!options) options = {};
  18. var threshold = options.threshold === undefined ? 0.1 : options.threshold;
  19. // maximum acceptable square distance between two colors;
  20. // 35215 is the maximum possible value for the YIQ difference metric
  21. var maxDelta = 35215 * threshold * threshold,
  22. diff = 0;
  23. // compare each pixel of one image against the other one
  24. for (var y = 0; y < height; y++) {
  25. for (var x = 0; x < width; x++) {
  26. var pos = (y * width + x) * 4;
  27. // squared YUV distance between colors at this pixel position
  28. var delta = colorDelta(img1, img2, pos, pos);
  29. // the color difference is above the threshold
  30. if (delta > maxDelta) {
  31. // check it's a real rendering difference or just anti-aliasing
  32. if (!options.includeAA && (antialiased(img1, x, y, width, height, img2) ||
  33. antialiased(img2, x, y, width, height, img1))) {
  34. // one of the pixels is anti-aliasing; draw as yellow and do not count as difference
  35. if (output) drawPixel(output, pos, 255, 255, 0);
  36. } else {
  37. // found substantial difference not caused by anti-aliasing; draw it as red
  38. if (output) drawPixel(output, pos, 255, 0, 0);
  39. diff++;
  40. }
  41. } else if (output) {
  42. // pixels are similar; draw background as grayscale image blended with white
  43. var val = blend(grayPixel(img1, pos), 0.1);
  44. drawPixel(output, pos, val, val, val);
  45. }
  46. }
  47. }
  48. // return the number of different pixels
  49. return diff;
  50. }
  51. // check if a pixel is likely a part of anti-aliasing;
  52. // based on "Anti-aliased Pixel and Intensity Slope Detector" paper by V. Vysniauskas, 2009
  53. function antialiased(img, x1, y1, width, height, img2) {
  54. var x0 = Math.max(x1 - 1, 0),
  55. y0 = Math.max(y1 - 1, 0),
  56. x2 = Math.min(x1 + 1, width - 1),
  57. y2 = Math.min(y1 + 1, height - 1),
  58. pos = (y1 * width + x1) * 4,
  59. zeroes = 0,
  60. positives = 0,
  61. negatives = 0,
  62. min = 0,
  63. max = 0,
  64. minX, minY, maxX, maxY;
  65. // go through 8 adjacent pixels
  66. for (var x = x0; x <= x2; x++) {
  67. for (var y = y0; y <= y2; y++) {
  68. if (x === x1 && y === y1) continue;
  69. // brightness delta between the center pixel and adjacent one
  70. var delta = colorDelta(img, img, pos, (y * width + x) * 4, true);
  71. // count the number of equal, darker and brighter adjacent pixels
  72. if (delta === 0) zeroes++;
  73. else if (delta < 0) negatives++;
  74. else if (delta > 0) positives++;
  75. // if found more than 2 equal siblings, it's definitely not anti-aliasing
  76. if (zeroes > 2) return false;
  77. if (!img2) continue;
  78. // remember the darkest pixel
  79. if (delta < min) {
  80. min = delta;
  81. minX = x;
  82. minY = y;
  83. }
  84. // remember the brightest pixel
  85. if (delta > max) {
  86. max = delta;
  87. maxX = x;
  88. maxY = y;
  89. }
  90. }
  91. }
  92. if (!img2) return true;
  93. // if there are no both darker and brighter pixels among siblings, it's not anti-aliasing
  94. if (negatives === 0 || positives === 0) return false;
  95. // if either the darkest or the brightest pixel has more than 2 equal siblings in both images
  96. // (definitely not anti-aliased), this pixel is anti-aliased
  97. return (!antialiased(img, minX, minY, width, height) && !antialiased(img2, minX, minY, width, height)) ||
  98. (!antialiased(img, maxX, maxY, width, height) && !antialiased(img2, maxX, maxY, width, height));
  99. }
  100. // calculate color difference according to the paper "Measuring perceived color difference
  101. // using YIQ NTSC transmission color space in mobile applications" by Y. Kotsarenko and F. Ramos
  102. function colorDelta(img1, img2, k, m, yOnly) {
  103. var a1 = img1[k + 3] / 255,
  104. a2 = img2[m + 3] / 255,
  105. r1 = blend(img1[k + 0], a1),
  106. g1 = blend(img1[k + 1], a1),
  107. b1 = blend(img1[k + 2], a1),
  108. r2 = blend(img2[m + 0], a2),
  109. g2 = blend(img2[m + 1], a2),
  110. b2 = blend(img2[m + 2], a2),
  111. y = rgb2y(r1, g1, b1) - rgb2y(r2, g2, b2);
  112. if (yOnly) return y; // brightness difference only
  113. var i = rgb2i(r1, g1, b1) - rgb2i(r2, g2, b2),
  114. q = rgb2q(r1, g1, b1) - rgb2q(r2, g2, b2);
  115. return 0.5053 * y * y + 0.299 * i * i + 0.1957 * q * q;
  116. }
  117. function rgb2y(r, g, b) { return r * 0.29889531 + g * 0.58662247 + b * 0.11448223; }
  118. function rgb2i(r, g, b) { return r * 0.59597799 - g * 0.27417610 - b * 0.32180189; }
  119. function rgb2q(r, g, b) { return r * 0.21147017 - g * 0.52261711 + b * 0.31114694; }
  120. // blend semi-transparent color with white
  121. function blend(c, a) {
  122. return 255 + (c - 255) * a;
  123. }
  124. function drawPixel(output, pos, r, g, b) {
  125. output[pos + 0] = r;
  126. output[pos + 1] = g;
  127. output[pos + 2] = b;
  128. output[pos + 3] = 255;
  129. }
  130. function grayPixel(img, i) {
  131. var a = img[i + 3] / 255,
  132. r = blend(img[i + 0], a),
  133. g = blend(img[i + 1], a),
  134. b = blend(img[i + 2], a);
  135. return rgb2y(r, g, b);
  136. }
  137. function createCommonjsModule(fn, basedir, module) {
  138. return module = {
  139. path: basedir,
  140. exports: {},
  141. require: function (path, base) {
  142. return commonjsRequire(path, (base === undefined || base === null) ? module.path : base);
  143. }
  144. }, fn(module, module.exports), module.exports;
  145. }
  146. function commonjsRequire () {
  147. throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs');
  148. }
  149. var chunkstream = createCommonjsModule(function (module) {
  150. var ChunkStream = module.exports = function() {
  151. Stream__default['default'].call(this);
  152. this._buffers = [];
  153. this._buffered = 0;
  154. this._reads = [];
  155. this._paused = false;
  156. this._encoding = 'utf8';
  157. this.writable = true;
  158. };
  159. util__default['default'].inherits(ChunkStream, Stream__default['default']);
  160. ChunkStream.prototype.read = function(length, callback) {
  161. this._reads.push({
  162. length: Math.abs(length), // if length < 0 then at most this length
  163. allowLess: length < 0,
  164. func: callback
  165. });
  166. process.nextTick(function() {
  167. this._process();
  168. // its paused and there is not enought data then ask for more
  169. if (this._paused && this._reads.length > 0) {
  170. this._paused = false;
  171. this.emit('drain');
  172. }
  173. }.bind(this));
  174. };
  175. ChunkStream.prototype.write = function(data, encoding) {
  176. if (!this.writable) {
  177. this.emit('error', new Error('Stream not writable'));
  178. return false;
  179. }
  180. var dataBuffer;
  181. if (Buffer.isBuffer(data)) {
  182. dataBuffer = data;
  183. }
  184. else {
  185. dataBuffer = new Buffer(data, encoding || this._encoding);
  186. }
  187. this._buffers.push(dataBuffer);
  188. this._buffered += dataBuffer.length;
  189. this._process();
  190. // ok if there are no more read requests
  191. if (this._reads && this._reads.length === 0) {
  192. this._paused = true;
  193. }
  194. return this.writable && !this._paused;
  195. };
  196. ChunkStream.prototype.end = function(data, encoding) {
  197. if (data) {
  198. this.write(data, encoding);
  199. }
  200. this.writable = false;
  201. // already destroyed
  202. if (!this._buffers) {
  203. return;
  204. }
  205. // enqueue or handle end
  206. if (this._buffers.length === 0) {
  207. this._end();
  208. }
  209. else {
  210. this._buffers.push(null);
  211. this._process();
  212. }
  213. };
  214. ChunkStream.prototype.destroySoon = ChunkStream.prototype.end;
  215. ChunkStream.prototype._end = function() {
  216. if (this._reads.length > 0) {
  217. this.emit('error',
  218. new Error('Unexpected end of input')
  219. );
  220. }
  221. this.destroy();
  222. };
  223. ChunkStream.prototype.destroy = function() {
  224. if (!this._buffers) {
  225. return;
  226. }
  227. this.writable = false;
  228. this._reads = null;
  229. this._buffers = null;
  230. this.emit('close');
  231. };
  232. ChunkStream.prototype._processReadAllowingLess = function(read) {
  233. // ok there is any data so that we can satisfy this request
  234. this._reads.shift(); // == read
  235. // first we need to peek into first buffer
  236. var smallerBuf = this._buffers[0];
  237. // ok there is more data than we need
  238. if (smallerBuf.length > read.length) {
  239. this._buffered -= read.length;
  240. this._buffers[0] = smallerBuf.slice(read.length);
  241. read.func.call(this, smallerBuf.slice(0, read.length));
  242. }
  243. else {
  244. // ok this is less than maximum length so use it all
  245. this._buffered -= smallerBuf.length;
  246. this._buffers.shift(); // == smallerBuf
  247. read.func.call(this, smallerBuf);
  248. }
  249. };
  250. ChunkStream.prototype._processRead = function(read) {
  251. this._reads.shift(); // == read
  252. var pos = 0;
  253. var count = 0;
  254. var data = new Buffer(read.length);
  255. // create buffer for all data
  256. while (pos < read.length) {
  257. var buf = this._buffers[count++];
  258. var len = Math.min(buf.length, read.length - pos);
  259. buf.copy(data, pos, 0, len);
  260. pos += len;
  261. // last buffer wasn't used all so just slice it and leave
  262. if (len !== buf.length) {
  263. this._buffers[--count] = buf.slice(len);
  264. }
  265. }
  266. // remove all used buffers
  267. if (count > 0) {
  268. this._buffers.splice(0, count);
  269. }
  270. this._buffered -= read.length;
  271. read.func.call(this, data);
  272. };
  273. ChunkStream.prototype._process = function() {
  274. try {
  275. // as long as there is any data and read requests
  276. while (this._buffered > 0 && this._reads && this._reads.length > 0) {
  277. var read = this._reads[0];
  278. // read any data (but no more than length)
  279. if (read.allowLess) {
  280. this._processReadAllowingLess(read);
  281. }
  282. else if (this._buffered >= read.length) {
  283. // ok we can meet some expectations
  284. this._processRead(read);
  285. }
  286. else {
  287. // not enought data to satisfy first request in queue
  288. // so we need to wait for more
  289. break;
  290. }
  291. }
  292. if (this._buffers && !this.writable) {
  293. this._end();
  294. }
  295. }
  296. catch (ex) {
  297. this.emit('error', ex);
  298. }
  299. };
  300. });
  301. // Adam 7
  302. // 0 1 2 3 4 5 6 7
  303. // 0 x 6 4 6 x 6 4 6
  304. // 1 7 7 7 7 7 7 7 7
  305. // 2 5 6 5 6 5 6 5 6
  306. // 3 7 7 7 7 7 7 7 7
  307. // 4 3 6 4 6 3 6 4 6
  308. // 5 7 7 7 7 7 7 7 7
  309. // 6 5 6 5 6 5 6 5 6
  310. // 7 7 7 7 7 7 7 7 7
  311. var imagePasses = [
  312. { // pass 1 - 1px
  313. x: [0],
  314. y: [0]
  315. },
  316. { // pass 2 - 1px
  317. x: [4],
  318. y: [0]
  319. },
  320. { // pass 3 - 2px
  321. x: [0, 4],
  322. y: [4]
  323. },
  324. { // pass 4 - 4px
  325. x: [2, 6],
  326. y: [0, 4]
  327. },
  328. { // pass 5 - 8px
  329. x: [0, 2, 4, 6],
  330. y: [2, 6]
  331. },
  332. { // pass 6 - 16px
  333. x: [1, 3, 5, 7],
  334. y: [0, 2, 4, 6]
  335. },
  336. { // pass 7 - 32px
  337. x: [0, 1, 2, 3, 4, 5, 6, 7],
  338. y: [1, 3, 5, 7]
  339. }
  340. ];
  341. var getImagePasses = function(width, height) {
  342. var images = [];
  343. var xLeftOver = width % 8;
  344. var yLeftOver = height % 8;
  345. var xRepeats = (width - xLeftOver) / 8;
  346. var yRepeats = (height - yLeftOver) / 8;
  347. for (var i = 0; i < imagePasses.length; i++) {
  348. var pass = imagePasses[i];
  349. var passWidth = xRepeats * pass.x.length;
  350. var passHeight = yRepeats * pass.y.length;
  351. for (var j = 0; j < pass.x.length; j++) {
  352. if (pass.x[j] < xLeftOver) {
  353. passWidth++;
  354. }
  355. else {
  356. break;
  357. }
  358. }
  359. for (j = 0; j < pass.y.length; j++) {
  360. if (pass.y[j] < yLeftOver) {
  361. passHeight++;
  362. }
  363. else {
  364. break;
  365. }
  366. }
  367. if (passWidth > 0 && passHeight > 0) {
  368. images.push({ width: passWidth, height: passHeight, index: i });
  369. }
  370. }
  371. return images;
  372. };
  373. var getInterlaceIterator = function(width) {
  374. return function(x, y, pass) {
  375. var outerXLeftOver = x % imagePasses[pass].x.length;
  376. var outerX = (((x - outerXLeftOver) / imagePasses[pass].x.length) * 8) + imagePasses[pass].x[outerXLeftOver];
  377. var outerYLeftOver = y % imagePasses[pass].y.length;
  378. var outerY = (((y - outerYLeftOver) / imagePasses[pass].y.length) * 8) + imagePasses[pass].y[outerYLeftOver];
  379. return (outerX * 4) + (outerY * width * 4);
  380. };
  381. };
  382. var interlace = {
  383. getImagePasses: getImagePasses,
  384. getInterlaceIterator: getInterlaceIterator
  385. };
  386. var paethPredictor = function paethPredictor(left, above, upLeft) {
  387. var paeth = left + above - upLeft;
  388. var pLeft = Math.abs(paeth - left);
  389. var pAbove = Math.abs(paeth - above);
  390. var pUpLeft = Math.abs(paeth - upLeft);
  391. if (pLeft <= pAbove && pLeft <= pUpLeft) {
  392. return left;
  393. }
  394. if (pAbove <= pUpLeft) {
  395. return above;
  396. }
  397. return upLeft;
  398. };
  399. var filterParse = createCommonjsModule(function (module) {
  400. function getByteWidth(width, bpp, depth) {
  401. var byteWidth = width * bpp;
  402. if (depth !== 8) {
  403. byteWidth = Math.ceil(byteWidth / (8 / depth));
  404. }
  405. return byteWidth;
  406. }
  407. var Filter = module.exports = function(bitmapInfo, dependencies) {
  408. var width = bitmapInfo.width;
  409. var height = bitmapInfo.height;
  410. var interlace$1 = bitmapInfo.interlace;
  411. var bpp = bitmapInfo.bpp;
  412. var depth = bitmapInfo.depth;
  413. this.read = dependencies.read;
  414. this.write = dependencies.write;
  415. this.complete = dependencies.complete;
  416. this._imageIndex = 0;
  417. this._images = [];
  418. if (interlace$1) {
  419. var passes = interlace.getImagePasses(width, height);
  420. for (var i = 0; i < passes.length; i++) {
  421. this._images.push({
  422. byteWidth: getByteWidth(passes[i].width, bpp, depth),
  423. height: passes[i].height,
  424. lineIndex: 0
  425. });
  426. }
  427. }
  428. else {
  429. this._images.push({
  430. byteWidth: getByteWidth(width, bpp, depth),
  431. height: height,
  432. lineIndex: 0
  433. });
  434. }
  435. // when filtering the line we look at the pixel to the left
  436. // the spec also says it is done on a byte level regardless of the number of pixels
  437. // so if the depth is byte compatible (8 or 16) we subtract the bpp in order to compare back
  438. // a pixel rather than just a different byte part. However if we are sub byte, we ignore.
  439. if (depth === 8) {
  440. this._xComparison = bpp;
  441. }
  442. else if (depth === 16) {
  443. this._xComparison = bpp * 2;
  444. }
  445. else {
  446. this._xComparison = 1;
  447. }
  448. };
  449. Filter.prototype.start = function() {
  450. this.read(this._images[this._imageIndex].byteWidth + 1, this._reverseFilterLine.bind(this));
  451. };
  452. Filter.prototype._unFilterType1 = function(rawData, unfilteredLine, byteWidth) {
  453. var xComparison = this._xComparison;
  454. var xBiggerThan = xComparison - 1;
  455. for (var x = 0; x < byteWidth; x++) {
  456. var rawByte = rawData[1 + x];
  457. var f1Left = x > xBiggerThan ? unfilteredLine[x - xComparison] : 0;
  458. unfilteredLine[x] = rawByte + f1Left;
  459. }
  460. };
  461. Filter.prototype._unFilterType2 = function(rawData, unfilteredLine, byteWidth) {
  462. var lastLine = this._lastLine;
  463. for (var x = 0; x < byteWidth; x++) {
  464. var rawByte = rawData[1 + x];
  465. var f2Up = lastLine ? lastLine[x] : 0;
  466. unfilteredLine[x] = rawByte + f2Up;
  467. }
  468. };
  469. Filter.prototype._unFilterType3 = function(rawData, unfilteredLine, byteWidth) {
  470. var xComparison = this._xComparison;
  471. var xBiggerThan = xComparison - 1;
  472. var lastLine = this._lastLine;
  473. for (var x = 0; x < byteWidth; x++) {
  474. var rawByte = rawData[1 + x];
  475. var f3Up = lastLine ? lastLine[x] : 0;
  476. var f3Left = x > xBiggerThan ? unfilteredLine[x - xComparison] : 0;
  477. var f3Add = Math.floor((f3Left + f3Up) / 2);
  478. unfilteredLine[x] = rawByte + f3Add;
  479. }
  480. };
  481. Filter.prototype._unFilterType4 = function(rawData, unfilteredLine, byteWidth) {
  482. var xComparison = this._xComparison;
  483. var xBiggerThan = xComparison - 1;
  484. var lastLine = this._lastLine;
  485. for (var x = 0; x < byteWidth; x++) {
  486. var rawByte = rawData[1 + x];
  487. var f4Up = lastLine ? lastLine[x] : 0;
  488. var f4Left = x > xBiggerThan ? unfilteredLine[x - xComparison] : 0;
  489. var f4UpLeft = x > xBiggerThan && lastLine ? lastLine[x - xComparison] : 0;
  490. var f4Add = paethPredictor(f4Left, f4Up, f4UpLeft);
  491. unfilteredLine[x] = rawByte + f4Add;
  492. }
  493. };
  494. Filter.prototype._reverseFilterLine = function(rawData) {
  495. var filter = rawData[0];
  496. var unfilteredLine;
  497. var currentImage = this._images[this._imageIndex];
  498. var byteWidth = currentImage.byteWidth;
  499. if (filter === 0) {
  500. unfilteredLine = rawData.slice(1, byteWidth + 1);
  501. }
  502. else {
  503. unfilteredLine = new Buffer(byteWidth);
  504. switch (filter) {
  505. case 1:
  506. this._unFilterType1(rawData, unfilteredLine, byteWidth);
  507. break;
  508. case 2:
  509. this._unFilterType2(rawData, unfilteredLine, byteWidth);
  510. break;
  511. case 3:
  512. this._unFilterType3(rawData, unfilteredLine, byteWidth);
  513. break;
  514. case 4:
  515. this._unFilterType4(rawData, unfilteredLine, byteWidth);
  516. break;
  517. default:
  518. throw new Error('Unrecognised filter type - ' + filter);
  519. }
  520. }
  521. this.write(unfilteredLine);
  522. currentImage.lineIndex++;
  523. if (currentImage.lineIndex >= currentImage.height) {
  524. this._lastLine = null;
  525. this._imageIndex++;
  526. currentImage = this._images[this._imageIndex];
  527. }
  528. else {
  529. this._lastLine = unfilteredLine;
  530. }
  531. if (currentImage) {
  532. // read, using the byte width that may be from the new current image
  533. this.read(currentImage.byteWidth + 1, this._reverseFilterLine.bind(this));
  534. }
  535. else {
  536. this._lastLine = null;
  537. this.complete();
  538. }
  539. };
  540. });
  541. var filterParseAsync = createCommonjsModule(function (module) {
  542. var FilterAsync = module.exports = function(bitmapInfo) {
  543. chunkstream.call(this);
  544. var buffers = [];
  545. var that = this;
  546. this._filter = new filterParse(bitmapInfo, {
  547. read: this.read.bind(this),
  548. write: function(buffer) {
  549. buffers.push(buffer);
  550. },
  551. complete: function() {
  552. that.emit('complete', Buffer.concat(buffers));
  553. }
  554. });
  555. this._filter.start();
  556. };
  557. util__default['default'].inherits(FilterAsync, chunkstream);
  558. });
  559. var constants = {
  560. PNG_SIGNATURE: [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a],
  561. TYPE_IHDR: 0x49484452,
  562. TYPE_IEND: 0x49454e44,
  563. TYPE_IDAT: 0x49444154,
  564. TYPE_PLTE: 0x504c5445,
  565. TYPE_tRNS: 0x74524e53, // eslint-disable-line camelcase
  566. TYPE_gAMA: 0x67414d41, // eslint-disable-line camelcase
  567. // color-type bits
  568. COLORTYPE_GRAYSCALE: 0,
  569. COLORTYPE_PALETTE: 1,
  570. COLORTYPE_COLOR: 2,
  571. COLORTYPE_ALPHA: 4, // e.g. grayscale and alpha
  572. // color-type combinations
  573. COLORTYPE_PALETTE_COLOR: 3,
  574. COLORTYPE_COLOR_ALPHA: 6,
  575. COLORTYPE_TO_BPP_MAP: {
  576. 0: 1,
  577. 2: 3,
  578. 3: 1,
  579. 4: 2,
  580. 6: 4
  581. },
  582. GAMMA_DIVISION: 100000
  583. };
  584. var crc = createCommonjsModule(function (module) {
  585. var crcTable = [];
  586. (function() {
  587. for (var i = 0; i < 256; i++) {
  588. var currentCrc = i;
  589. for (var j = 0; j < 8; j++) {
  590. if (currentCrc & 1) {
  591. currentCrc = 0xedb88320 ^ (currentCrc >>> 1);
  592. }
  593. else {
  594. currentCrc = currentCrc >>> 1;
  595. }
  596. }
  597. crcTable[i] = currentCrc;
  598. }
  599. }());
  600. var CrcCalculator = module.exports = function() {
  601. this._crc = -1;
  602. };
  603. CrcCalculator.prototype.write = function(data) {
  604. for (var i = 0; i < data.length; i++) {
  605. this._crc = crcTable[(this._crc ^ data[i]) & 0xff] ^ (this._crc >>> 8);
  606. }
  607. return true;
  608. };
  609. CrcCalculator.prototype.crc32 = function() {
  610. return this._crc ^ -1;
  611. };
  612. CrcCalculator.crc32 = function(buf) {
  613. var crc = -1;
  614. for (var i = 0; i < buf.length; i++) {
  615. crc = crcTable[(crc ^ buf[i]) & 0xff] ^ (crc >>> 8);
  616. }
  617. return crc ^ -1;
  618. };
  619. });
  620. var parser = createCommonjsModule(function (module) {
  621. var Parser = module.exports = function(options, dependencies) {
  622. this._options = options;
  623. options.checkCRC = options.checkCRC !== false;
  624. this._hasIHDR = false;
  625. this._hasIEND = false;
  626. this._emittedHeadersFinished = false;
  627. // input flags/metadata
  628. this._palette = [];
  629. this._colorType = 0;
  630. this._chunks = {};
  631. this._chunks[constants.TYPE_IHDR] = this._handleIHDR.bind(this);
  632. this._chunks[constants.TYPE_IEND] = this._handleIEND.bind(this);
  633. this._chunks[constants.TYPE_IDAT] = this._handleIDAT.bind(this);
  634. this._chunks[constants.TYPE_PLTE] = this._handlePLTE.bind(this);
  635. this._chunks[constants.TYPE_tRNS] = this._handleTRNS.bind(this);
  636. this._chunks[constants.TYPE_gAMA] = this._handleGAMA.bind(this);
  637. this.read = dependencies.read;
  638. this.error = dependencies.error;
  639. this.metadata = dependencies.metadata;
  640. this.gamma = dependencies.gamma;
  641. this.transColor = dependencies.transColor;
  642. this.palette = dependencies.palette;
  643. this.parsed = dependencies.parsed;
  644. this.inflateData = dependencies.inflateData;
  645. this.finished = dependencies.finished;
  646. this.simpleTransparency = dependencies.simpleTransparency;
  647. this.headersFinished = dependencies.headersFinished || function() {};
  648. };
  649. Parser.prototype.start = function() {
  650. this.read(constants.PNG_SIGNATURE.length,
  651. this._parseSignature.bind(this)
  652. );
  653. };
  654. Parser.prototype._parseSignature = function(data) {
  655. var signature = constants.PNG_SIGNATURE;
  656. for (var i = 0; i < signature.length; i++) {
  657. if (data[i] !== signature[i]) {
  658. this.error(new Error('Invalid file signature'));
  659. return;
  660. }
  661. }
  662. this.read(8, this._parseChunkBegin.bind(this));
  663. };
  664. Parser.prototype._parseChunkBegin = function(data) {
  665. // chunk content length
  666. var length = data.readUInt32BE(0);
  667. // chunk type
  668. var type = data.readUInt32BE(4);
  669. var name = '';
  670. for (var i = 4; i < 8; i++) {
  671. name += String.fromCharCode(data[i]);
  672. }
  673. //console.log('chunk ', name, length);
  674. // chunk flags
  675. var ancillary = Boolean(data[4] & 0x20); // or critical
  676. // priv = Boolean(data[5] & 0x20), // or public
  677. // safeToCopy = Boolean(data[7] & 0x20); // or unsafe
  678. if (!this._hasIHDR && type !== constants.TYPE_IHDR) {
  679. this.error(new Error('Expected IHDR on beggining'));
  680. return;
  681. }
  682. this._crc = new crc();
  683. this._crc.write(new Buffer(name));
  684. if (this._chunks[type]) {
  685. return this._chunks[type](length);
  686. }
  687. if (!ancillary) {
  688. this.error(new Error('Unsupported critical chunk type ' + name));
  689. return;
  690. }
  691. this.read(length + 4, this._skipChunk.bind(this));
  692. };
  693. Parser.prototype._skipChunk = function(/*data*/) {
  694. this.read(8, this._parseChunkBegin.bind(this));
  695. };
  696. Parser.prototype._handleChunkEnd = function() {
  697. this.read(4, this._parseChunkEnd.bind(this));
  698. };
  699. Parser.prototype._parseChunkEnd = function(data) {
  700. var fileCrc = data.readInt32BE(0);
  701. var calcCrc = this._crc.crc32();
  702. // check CRC
  703. if (this._options.checkCRC && calcCrc !== fileCrc) {
  704. this.error(new Error('Crc error - ' + fileCrc + ' - ' + calcCrc));
  705. return;
  706. }
  707. if (!this._hasIEND) {
  708. this.read(8, this._parseChunkBegin.bind(this));
  709. }
  710. };
  711. Parser.prototype._handleIHDR = function(length) {
  712. this.read(length, this._parseIHDR.bind(this));
  713. };
  714. Parser.prototype._parseIHDR = function(data) {
  715. this._crc.write(data);
  716. var width = data.readUInt32BE(0);
  717. var height = data.readUInt32BE(4);
  718. var depth = data[8];
  719. var colorType = data[9]; // bits: 1 palette, 2 color, 4 alpha
  720. var compr = data[10];
  721. var filter = data[11];
  722. var interlace = data[12];
  723. // console.log(' width', width, 'height', height,
  724. // 'depth', depth, 'colorType', colorType,
  725. // 'compr', compr, 'filter', filter, 'interlace', interlace
  726. // );
  727. if (depth !== 8 && depth !== 4 && depth !== 2 && depth !== 1 && depth !== 16) {
  728. this.error(new Error('Unsupported bit depth ' + depth));
  729. return;
  730. }
  731. if (!(colorType in constants.COLORTYPE_TO_BPP_MAP)) {
  732. this.error(new Error('Unsupported color type'));
  733. return;
  734. }
  735. if (compr !== 0) {
  736. this.error(new Error('Unsupported compression method'));
  737. return;
  738. }
  739. if (filter !== 0) {
  740. this.error(new Error('Unsupported filter method'));
  741. return;
  742. }
  743. if (interlace !== 0 && interlace !== 1) {
  744. this.error(new Error('Unsupported interlace method'));
  745. return;
  746. }
  747. this._colorType = colorType;
  748. var bpp = constants.COLORTYPE_TO_BPP_MAP[this._colorType];
  749. this._hasIHDR = true;
  750. this.metadata({
  751. width: width,
  752. height: height,
  753. depth: depth,
  754. interlace: Boolean(interlace),
  755. palette: Boolean(colorType & constants.COLORTYPE_PALETTE),
  756. color: Boolean(colorType & constants.COLORTYPE_COLOR),
  757. alpha: Boolean(colorType & constants.COLORTYPE_ALPHA),
  758. bpp: bpp,
  759. colorType: colorType
  760. });
  761. this._handleChunkEnd();
  762. };
  763. Parser.prototype._handlePLTE = function(length) {
  764. this.read(length, this._parsePLTE.bind(this));
  765. };
  766. Parser.prototype._parsePLTE = function(data) {
  767. this._crc.write(data);
  768. var entries = Math.floor(data.length / 3);
  769. // console.log('Palette:', entries);
  770. for (var i = 0; i < entries; i++) {
  771. this._palette.push([
  772. data[i * 3],
  773. data[i * 3 + 1],
  774. data[i * 3 + 2],
  775. 0xff
  776. ]);
  777. }
  778. this.palette(this._palette);
  779. this._handleChunkEnd();
  780. };
  781. Parser.prototype._handleTRNS = function(length) {
  782. this.simpleTransparency();
  783. this.read(length, this._parseTRNS.bind(this));
  784. };
  785. Parser.prototype._parseTRNS = function(data) {
  786. this._crc.write(data);
  787. // palette
  788. if (this._colorType === constants.COLORTYPE_PALETTE_COLOR) {
  789. if (this._palette.length === 0) {
  790. this.error(new Error('Transparency chunk must be after palette'));
  791. return;
  792. }
  793. if (data.length > this._palette.length) {
  794. this.error(new Error('More transparent colors than palette size'));
  795. return;
  796. }
  797. for (var i = 0; i < data.length; i++) {
  798. this._palette[i][3] = data[i];
  799. }
  800. this.palette(this._palette);
  801. }
  802. // for colorType 0 (grayscale) and 2 (rgb)
  803. // there might be one gray/color defined as transparent
  804. if (this._colorType === constants.COLORTYPE_GRAYSCALE) {
  805. // grey, 2 bytes
  806. this.transColor([data.readUInt16BE(0)]);
  807. }
  808. if (this._colorType === constants.COLORTYPE_COLOR) {
  809. this.transColor([data.readUInt16BE(0), data.readUInt16BE(2), data.readUInt16BE(4)]);
  810. }
  811. this._handleChunkEnd();
  812. };
  813. Parser.prototype._handleGAMA = function(length) {
  814. this.read(length, this._parseGAMA.bind(this));
  815. };
  816. Parser.prototype._parseGAMA = function(data) {
  817. this._crc.write(data);
  818. this.gamma(data.readUInt32BE(0) / constants.GAMMA_DIVISION);
  819. this._handleChunkEnd();
  820. };
  821. Parser.prototype._handleIDAT = function(length) {
  822. if (!this._emittedHeadersFinished) {
  823. this._emittedHeadersFinished = true;
  824. this.headersFinished();
  825. }
  826. this.read(-length, this._parseIDAT.bind(this, length));
  827. };
  828. Parser.prototype._parseIDAT = function(length, data) {
  829. this._crc.write(data);
  830. if (this._colorType === constants.COLORTYPE_PALETTE_COLOR && this._palette.length === 0) {
  831. throw new Error('Expected palette not found');
  832. }
  833. this.inflateData(data);
  834. var leftOverLength = length - data.length;
  835. if (leftOverLength > 0) {
  836. this._handleIDAT(leftOverLength);
  837. }
  838. else {
  839. this._handleChunkEnd();
  840. }
  841. };
  842. Parser.prototype._handleIEND = function(length) {
  843. this.read(length, this._parseIEND.bind(this));
  844. };
  845. Parser.prototype._parseIEND = function(data) {
  846. this._crc.write(data);
  847. this._hasIEND = true;
  848. this._handleChunkEnd();
  849. if (this.finished) {
  850. this.finished();
  851. }
  852. };
  853. });
  854. var pixelBppMapper = [
  855. // 0 - dummy entry
  856. function() {},
  857. // 1 - L
  858. // 0: 0, 1: 0, 2: 0, 3: 0xff
  859. function(pxData, data, pxPos, rawPos) {
  860. if (rawPos === data.length) {
  861. throw new Error('Ran out of data');
  862. }
  863. var pixel = data[rawPos];
  864. pxData[pxPos] = pixel;
  865. pxData[pxPos + 1] = pixel;
  866. pxData[pxPos + 2] = pixel;
  867. pxData[pxPos + 3] = 0xff;
  868. },
  869. // 2 - LA
  870. // 0: 0, 1: 0, 2: 0, 3: 1
  871. function(pxData, data, pxPos, rawPos) {
  872. if (rawPos + 1 >= data.length) {
  873. throw new Error('Ran out of data');
  874. }
  875. var pixel = data[rawPos];
  876. pxData[pxPos] = pixel;
  877. pxData[pxPos + 1] = pixel;
  878. pxData[pxPos + 2] = pixel;
  879. pxData[pxPos + 3] = data[rawPos + 1];
  880. },
  881. // 3 - RGB
  882. // 0: 0, 1: 1, 2: 2, 3: 0xff
  883. function(pxData, data, pxPos, rawPos) {
  884. if (rawPos + 2 >= data.length) {
  885. throw new Error('Ran out of data');
  886. }
  887. pxData[pxPos] = data[rawPos];
  888. pxData[pxPos + 1] = data[rawPos + 1];
  889. pxData[pxPos + 2] = data[rawPos + 2];
  890. pxData[pxPos + 3] = 0xff;
  891. },
  892. // 4 - RGBA
  893. // 0: 0, 1: 1, 2: 2, 3: 3
  894. function(pxData, data, pxPos, rawPos) {
  895. if (rawPos + 3 >= data.length) {
  896. throw new Error('Ran out of data');
  897. }
  898. pxData[pxPos] = data[rawPos];
  899. pxData[pxPos + 1] = data[rawPos + 1];
  900. pxData[pxPos + 2] = data[rawPos + 2];
  901. pxData[pxPos + 3] = data[rawPos + 3];
  902. }
  903. ];
  904. var pixelBppCustomMapper = [
  905. // 0 - dummy entry
  906. function() {},
  907. // 1 - L
  908. // 0: 0, 1: 0, 2: 0, 3: 0xff
  909. function(pxData, pixelData, pxPos, maxBit) {
  910. var pixel = pixelData[0];
  911. pxData[pxPos] = pixel;
  912. pxData[pxPos + 1] = pixel;
  913. pxData[pxPos + 2] = pixel;
  914. pxData[pxPos + 3] = maxBit;
  915. },
  916. // 2 - LA
  917. // 0: 0, 1: 0, 2: 0, 3: 1
  918. function(pxData, pixelData, pxPos) {
  919. var pixel = pixelData[0];
  920. pxData[pxPos] = pixel;
  921. pxData[pxPos + 1] = pixel;
  922. pxData[pxPos + 2] = pixel;
  923. pxData[pxPos + 3] = pixelData[1];
  924. },
  925. // 3 - RGB
  926. // 0: 0, 1: 1, 2: 2, 3: 0xff
  927. function(pxData, pixelData, pxPos, maxBit) {
  928. pxData[pxPos] = pixelData[0];
  929. pxData[pxPos + 1] = pixelData[1];
  930. pxData[pxPos + 2] = pixelData[2];
  931. pxData[pxPos + 3] = maxBit;
  932. },
  933. // 4 - RGBA
  934. // 0: 0, 1: 1, 2: 2, 3: 3
  935. function(pxData, pixelData, pxPos) {
  936. pxData[pxPos] = pixelData[0];
  937. pxData[pxPos + 1] = pixelData[1];
  938. pxData[pxPos + 2] = pixelData[2];
  939. pxData[pxPos + 3] = pixelData[3];
  940. }
  941. ];
  942. function bitRetriever(data, depth) {
  943. var leftOver = [];
  944. var i = 0;
  945. function split() {
  946. if (i === data.length) {
  947. throw new Error('Ran out of data');
  948. }
  949. var byte = data[i];
  950. i++;
  951. var byte8, byte7, byte6, byte5, byte4, byte3, byte2, byte1;
  952. switch (depth) {
  953. default:
  954. throw new Error('unrecognised depth');
  955. case 16:
  956. byte2 = data[i];
  957. i++;
  958. leftOver.push(((byte << 8) + byte2));
  959. break;
  960. case 4:
  961. byte2 = byte & 0x0f;
  962. byte1 = byte >> 4;
  963. leftOver.push(byte1, byte2);
  964. break;
  965. case 2:
  966. byte4 = byte & 3;
  967. byte3 = byte >> 2 & 3;
  968. byte2 = byte >> 4 & 3;
  969. byte1 = byte >> 6 & 3;
  970. leftOver.push(byte1, byte2, byte3, byte4);
  971. break;
  972. case 1:
  973. byte8 = byte & 1;
  974. byte7 = byte >> 1 & 1;
  975. byte6 = byte >> 2 & 1;
  976. byte5 = byte >> 3 & 1;
  977. byte4 = byte >> 4 & 1;
  978. byte3 = byte >> 5 & 1;
  979. byte2 = byte >> 6 & 1;
  980. byte1 = byte >> 7 & 1;
  981. leftOver.push(byte1, byte2, byte3, byte4, byte5, byte6, byte7, byte8);
  982. break;
  983. }
  984. }
  985. return {
  986. get: function(count) {
  987. while (leftOver.length < count) {
  988. split();
  989. }
  990. var returner = leftOver.slice(0, count);
  991. leftOver = leftOver.slice(count);
  992. return returner;
  993. },
  994. resetAfterLine: function() {
  995. leftOver.length = 0;
  996. },
  997. end: function() {
  998. if (i !== data.length) {
  999. throw new Error('extra data found');
  1000. }
  1001. }
  1002. };
  1003. }
  1004. function mapImage8Bit(image, pxData, getPxPos, bpp, data, rawPos) { // eslint-disable-line max-params
  1005. var imageWidth = image.width;
  1006. var imageHeight = image.height;
  1007. var imagePass = image.index;
  1008. for (var y = 0; y < imageHeight; y++) {
  1009. for (var x = 0; x < imageWidth; x++) {
  1010. var pxPos = getPxPos(x, y, imagePass);
  1011. pixelBppMapper[bpp](pxData, data, pxPos, rawPos);
  1012. rawPos += bpp; //eslint-disable-line no-param-reassign
  1013. }
  1014. }
  1015. return rawPos;
  1016. }
  1017. function mapImageCustomBit(image, pxData, getPxPos, bpp, bits, maxBit) { // eslint-disable-line max-params
  1018. var imageWidth = image.width;
  1019. var imageHeight = image.height;
  1020. var imagePass = image.index;
  1021. for (var y = 0; y < imageHeight; y++) {
  1022. for (var x = 0; x < imageWidth; x++) {
  1023. var pixelData = bits.get(bpp);
  1024. var pxPos = getPxPos(x, y, imagePass);
  1025. pixelBppCustomMapper[bpp](pxData, pixelData, pxPos, maxBit);
  1026. }
  1027. bits.resetAfterLine();
  1028. }
  1029. }
  1030. var dataToBitMap = function(data, bitmapInfo) {
  1031. var width = bitmapInfo.width;
  1032. var height = bitmapInfo.height;
  1033. var depth = bitmapInfo.depth;
  1034. var bpp = bitmapInfo.bpp;
  1035. var interlace$1 = bitmapInfo.interlace;
  1036. if (depth !== 8) {
  1037. var bits = bitRetriever(data, depth);
  1038. }
  1039. var pxData;
  1040. if (depth <= 8) {
  1041. pxData = new Buffer(width * height * 4);
  1042. }
  1043. else {
  1044. pxData = new Uint16Array(width * height * 4);
  1045. }
  1046. var maxBit = Math.pow(2, depth) - 1;
  1047. var rawPos = 0;
  1048. var images;
  1049. var getPxPos;
  1050. if (interlace$1) {
  1051. images = interlace.getImagePasses(width, height);
  1052. getPxPos = interlace.getInterlaceIterator(width, height);
  1053. }
  1054. else {
  1055. var nonInterlacedPxPos = 0;
  1056. getPxPos = function() {
  1057. var returner = nonInterlacedPxPos;
  1058. nonInterlacedPxPos += 4;
  1059. return returner;
  1060. };
  1061. images = [{ width: width, height: height }];
  1062. }
  1063. for (var imageIndex = 0; imageIndex < images.length; imageIndex++) {
  1064. if (depth === 8) {
  1065. rawPos = mapImage8Bit(images[imageIndex], pxData, getPxPos, bpp, data, rawPos);
  1066. }
  1067. else {
  1068. mapImageCustomBit(images[imageIndex], pxData, getPxPos, bpp, bits, maxBit);
  1069. }
  1070. }
  1071. if (depth === 8) {
  1072. if (rawPos !== data.length) {
  1073. throw new Error('extra data found');
  1074. }
  1075. }
  1076. else {
  1077. bits.end();
  1078. }
  1079. return pxData;
  1080. };
  1081. var bitmapper = {
  1082. dataToBitMap: dataToBitMap
  1083. };
  1084. function dePalette(indata, outdata, width, height, palette) {
  1085. var pxPos = 0;
  1086. // use values from palette
  1087. for (var y = 0; y < height; y++) {
  1088. for (var x = 0; x < width; x++) {
  1089. var color = palette[indata[pxPos]];
  1090. if (!color) {
  1091. throw new Error('index ' + indata[pxPos] + ' not in palette');
  1092. }
  1093. for (var i = 0; i < 4; i++) {
  1094. outdata[pxPos + i] = color[i];
  1095. }
  1096. pxPos += 4;
  1097. }
  1098. }
  1099. }
  1100. function replaceTransparentColor(indata, outdata, width, height, transColor) {
  1101. var pxPos = 0;
  1102. for (var y = 0; y < height; y++) {
  1103. for (var x = 0; x < width; x++) {
  1104. var makeTrans = false;
  1105. if (transColor.length === 1) {
  1106. if (transColor[0] === indata[pxPos]) {
  1107. makeTrans = true;
  1108. }
  1109. }
  1110. else if (transColor[0] === indata[pxPos] && transColor[1] === indata[pxPos + 1] && transColor[2] === indata[pxPos + 2]) {
  1111. makeTrans = true;
  1112. }
  1113. if (makeTrans) {
  1114. for (var i = 0; i < 4; i++) {
  1115. outdata[pxPos + i] = 0;
  1116. }
  1117. }
  1118. pxPos += 4;
  1119. }
  1120. }
  1121. }
  1122. function scaleDepth(indata, outdata, width, height, depth) {
  1123. var maxOutSample = 255;
  1124. var maxInSample = Math.pow(2, depth) - 1;
  1125. var pxPos = 0;
  1126. for (var y = 0; y < height; y++) {
  1127. for (var x = 0; x < width; x++) {
  1128. for (var i = 0; i < 4; i++) {
  1129. outdata[pxPos + i] = Math.floor((indata[pxPos + i] * maxOutSample) / maxInSample + 0.5);
  1130. }
  1131. pxPos += 4;
  1132. }
  1133. }
  1134. }
  1135. var formatNormaliser = function(indata, imageData) {
  1136. var depth = imageData.depth;
  1137. var width = imageData.width;
  1138. var height = imageData.height;
  1139. var colorType = imageData.colorType;
  1140. var transColor = imageData.transColor;
  1141. var palette = imageData.palette;
  1142. var outdata = indata; // only different for 16 bits
  1143. if (colorType === 3) { // paletted
  1144. dePalette(indata, outdata, width, height, palette);
  1145. }
  1146. else {
  1147. if (transColor) {
  1148. replaceTransparentColor(indata, outdata, width, height, transColor);
  1149. }
  1150. // if it needs scaling
  1151. if (depth !== 8) {
  1152. // if we need to change the buffer size
  1153. if (depth === 16) {
  1154. outdata = new Buffer(width * height * 4);
  1155. }
  1156. scaleDepth(indata, outdata, width, height, depth);
  1157. }
  1158. }
  1159. return outdata;
  1160. };
  1161. var parserAsync = createCommonjsModule(function (module) {
  1162. var ParserAsync = module.exports = function(options) {
  1163. chunkstream.call(this);
  1164. this._parser = new parser(options, {
  1165. read: this.read.bind(this),
  1166. error: this._handleError.bind(this),
  1167. metadata: this._handleMetaData.bind(this),
  1168. gamma: this.emit.bind(this, 'gamma'),
  1169. palette: this._handlePalette.bind(this),
  1170. transColor: this._handleTransColor.bind(this),
  1171. finished: this._finished.bind(this),
  1172. inflateData: this._inflateData.bind(this),
  1173. simpleTransparency: this._simpleTransparency.bind(this),
  1174. headersFinished: this._headersFinished.bind(this)
  1175. });
  1176. this._options = options;
  1177. this.writable = true;
  1178. this._parser.start();
  1179. };
  1180. util__default['default'].inherits(ParserAsync, chunkstream);
  1181. ParserAsync.prototype._handleError = function(err) {
  1182. this.emit('error', err);
  1183. this.writable = false;
  1184. this.destroy();
  1185. if (this._inflate && this._inflate.destroy) {
  1186. this._inflate.destroy();
  1187. }
  1188. if (this._filter) {
  1189. this._filter.destroy();
  1190. // For backward compatibility with Node 7 and below.
  1191. // Suppress errors due to _inflate calling write() even after
  1192. // it's destroy()'ed.
  1193. this._filter.on('error', function() {});
  1194. }
  1195. this.errord = true;
  1196. };
  1197. ParserAsync.prototype._inflateData = function(data) {
  1198. if (!this._inflate) {
  1199. if (this._bitmapInfo.interlace) {
  1200. this._inflate = zlib__default['default'].createInflate();
  1201. this._inflate.on('error', this.emit.bind(this, 'error'));
  1202. this._filter.on('complete', this._complete.bind(this));
  1203. this._inflate.pipe(this._filter);
  1204. }
  1205. else {
  1206. var rowSize = ((this._bitmapInfo.width * this._bitmapInfo.bpp * this._bitmapInfo.depth + 7) >> 3) + 1;
  1207. var imageSize = rowSize * this._bitmapInfo.height;
  1208. var chunkSize = Math.max(imageSize, zlib__default['default'].Z_MIN_CHUNK);
  1209. this._inflate = zlib__default['default'].createInflate({ chunkSize: chunkSize });
  1210. var leftToInflate = imageSize;
  1211. var emitError = this.emit.bind(this, 'error');
  1212. this._inflate.on('error', function(err) {
  1213. if (!leftToInflate) {
  1214. return;
  1215. }
  1216. emitError(err);
  1217. });
  1218. this._filter.on('complete', this._complete.bind(this));
  1219. var filterWrite = this._filter.write.bind(this._filter);
  1220. this._inflate.on('data', function(chunk) {
  1221. if (!leftToInflate) {
  1222. return;
  1223. }
  1224. if (chunk.length > leftToInflate) {
  1225. chunk = chunk.slice(0, leftToInflate);
  1226. }
  1227. leftToInflate -= chunk.length;
  1228. filterWrite(chunk);
  1229. });
  1230. this._inflate.on('end', this._filter.end.bind(this._filter));
  1231. }
  1232. }
  1233. this._inflate.write(data);
  1234. };
  1235. ParserAsync.prototype._handleMetaData = function(metaData) {
  1236. this._metaData = metaData;
  1237. this._bitmapInfo = Object.create(metaData);
  1238. this._filter = new filterParseAsync(this._bitmapInfo);
  1239. };
  1240. ParserAsync.prototype._handleTransColor = function(transColor) {
  1241. this._bitmapInfo.transColor = transColor;
  1242. };
  1243. ParserAsync.prototype._handlePalette = function(palette) {
  1244. this._bitmapInfo.palette = palette;
  1245. };
  1246. ParserAsync.prototype._simpleTransparency = function() {
  1247. this._metaData.alpha = true;
  1248. };
  1249. ParserAsync.prototype._headersFinished = function() {
  1250. // Up until this point, we don't know if we have a tRNS chunk (alpha)
  1251. // so we can't emit metadata any earlier
  1252. this.emit('metadata', this._metaData);
  1253. };
  1254. ParserAsync.prototype._finished = function() {
  1255. if (this.errord) {
  1256. return;
  1257. }
  1258. if (!this._inflate) {
  1259. this.emit('error', 'No Inflate block');
  1260. }
  1261. else {
  1262. // no more data to inflate
  1263. this._inflate.end();
  1264. }
  1265. this.destroySoon();
  1266. };
  1267. ParserAsync.prototype._complete = function(filteredData) {
  1268. if (this.errord) {
  1269. return;
  1270. }
  1271. try {
  1272. var bitmapData = bitmapper.dataToBitMap(filteredData, this._bitmapInfo);
  1273. var normalisedBitmapData = formatNormaliser(bitmapData, this._bitmapInfo);
  1274. bitmapData = null;
  1275. }
  1276. catch (ex) {
  1277. this._handleError(ex);
  1278. return;
  1279. }
  1280. this.emit('parsed', normalisedBitmapData);
  1281. };
  1282. });
  1283. var bitpacker = function(dataIn, width, height, options) {
  1284. var outHasAlpha = [constants.COLORTYPE_COLOR_ALPHA, constants.COLORTYPE_ALPHA].indexOf(options.colorType) !== -1;
  1285. if (options.colorType === options.inputColorType) {
  1286. var bigEndian = (function() {
  1287. var buffer = new ArrayBuffer(2);
  1288. new DataView(buffer).setInt16(0, 256, true /* littleEndian */);
  1289. // Int16Array uses the platform's endianness.
  1290. return new Int16Array(buffer)[0] !== 256;
  1291. })();
  1292. // If no need to convert to grayscale and alpha is present/absent in both, take a fast route
  1293. if (options.bitDepth === 8 || (options.bitDepth === 16 && bigEndian)) {
  1294. return dataIn;
  1295. }
  1296. }
  1297. // map to a UInt16 array if data is 16bit, fix endianness below
  1298. var data = options.bitDepth !== 16 ? dataIn : new Uint16Array(dataIn.buffer);
  1299. var maxValue = 255;
  1300. var inBpp = constants.COLORTYPE_TO_BPP_MAP[options.inputColorType];
  1301. if (inBpp === 4 && !options.inputHasAlpha) {
  1302. inBpp = 3;
  1303. }
  1304. var outBpp = constants.COLORTYPE_TO_BPP_MAP[options.colorType];
  1305. if (options.bitDepth === 16) {
  1306. maxValue = 65535;
  1307. outBpp *= 2;
  1308. }
  1309. var outData = new Buffer(width * height * outBpp);
  1310. var inIndex = 0;
  1311. var outIndex = 0;
  1312. var bgColor = options.bgColor || {};
  1313. if (bgColor.red === undefined) {
  1314. bgColor.red = maxValue;
  1315. }
  1316. if (bgColor.green === undefined) {
  1317. bgColor.green = maxValue;
  1318. }
  1319. if (bgColor.blue === undefined) {
  1320. bgColor.blue = maxValue;
  1321. }
  1322. function getRGBA() {
  1323. var red;
  1324. var green;
  1325. var blue;
  1326. var alpha = maxValue;
  1327. switch (options.inputColorType) {
  1328. case constants.COLORTYPE_COLOR_ALPHA:
  1329. alpha = data[inIndex + 3];
  1330. red = data[inIndex];
  1331. green = data[inIndex + 1];
  1332. blue = data[inIndex + 2];
  1333. break;
  1334. case constants.COLORTYPE_COLOR:
  1335. red = data[inIndex];
  1336. green = data[inIndex + 1];
  1337. blue = data[inIndex + 2];
  1338. break;
  1339. case constants.COLORTYPE_ALPHA:
  1340. alpha = data[inIndex + 1];
  1341. red = data[inIndex];
  1342. green = red;
  1343. blue = red;
  1344. break;
  1345. case constants.COLORTYPE_GRAYSCALE:
  1346. red = data[inIndex];
  1347. green = red;
  1348. blue = red;
  1349. break;
  1350. default:
  1351. throw new Error('input color type:' + options.inputColorType + ' is not supported at present');
  1352. }
  1353. if (options.inputHasAlpha) {
  1354. if (!outHasAlpha) {
  1355. alpha /= maxValue;
  1356. red = Math.min(Math.max(Math.round((1 - alpha) * bgColor.red + alpha * red), 0), maxValue);
  1357. green = Math.min(Math.max(Math.round((1 - alpha) * bgColor.green + alpha * green), 0), maxValue);
  1358. blue = Math.min(Math.max(Math.round((1 - alpha) * bgColor.blue + alpha * blue), 0), maxValue);
  1359. }
  1360. }
  1361. return { red: red, green: green, blue: blue, alpha: alpha };
  1362. }
  1363. for (var y = 0; y < height; y++) {
  1364. for (var x = 0; x < width; x++) {
  1365. var rgba = getRGBA();
  1366. switch (options.colorType) {
  1367. case constants.COLORTYPE_COLOR_ALPHA:
  1368. case constants.COLORTYPE_COLOR:
  1369. if (options.bitDepth === 8) {
  1370. outData[outIndex] = rgba.red;
  1371. outData[outIndex + 1] = rgba.green;
  1372. outData[outIndex + 2] = rgba.blue;
  1373. if (outHasAlpha) {
  1374. outData[outIndex + 3] = rgba.alpha;
  1375. }
  1376. }
  1377. else {
  1378. outData.writeUInt16BE(rgba.red, outIndex);
  1379. outData.writeUInt16BE(rgba.green, outIndex + 2);
  1380. outData.writeUInt16BE(rgba.blue, outIndex + 4);
  1381. if (outHasAlpha) {
  1382. outData.writeUInt16BE(rgba.alpha, outIndex + 6);
  1383. }
  1384. }
  1385. break;
  1386. case constants.COLORTYPE_ALPHA:
  1387. case constants.COLORTYPE_GRAYSCALE:
  1388. // Convert to grayscale and alpha
  1389. var grayscale = (rgba.red + rgba.green + rgba.blue) / 3;
  1390. if (options.bitDepth === 8) {
  1391. outData[outIndex] = grayscale;
  1392. if (outHasAlpha) {
  1393. outData[outIndex + 1] = rgba.alpha;
  1394. }
  1395. }
  1396. else {
  1397. outData.writeUInt16BE(grayscale, outIndex);
  1398. if (outHasAlpha) {
  1399. outData.writeUInt16BE(rgba.alpha, outIndex + 2);
  1400. }
  1401. }
  1402. break;
  1403. default:
  1404. throw new Error('unrecognised color Type ' + options.colorType);
  1405. }
  1406. inIndex += inBpp;
  1407. outIndex += outBpp;
  1408. }
  1409. }
  1410. return outData;
  1411. };
  1412. function filterNone(pxData, pxPos, byteWidth, rawData, rawPos) {
  1413. for (var x = 0; x < byteWidth; x++) {
  1414. rawData[rawPos + x] = pxData[pxPos + x];
  1415. }
  1416. }
  1417. function filterSumNone(pxData, pxPos, byteWidth) {
  1418. var sum = 0;
  1419. var length = pxPos + byteWidth;
  1420. for (var i = pxPos; i < length; i++) {
  1421. sum += Math.abs(pxData[i]);
  1422. }
  1423. return sum;
  1424. }
  1425. function filterSub(pxData, pxPos, byteWidth, rawData, rawPos, bpp) {
  1426. for (var x = 0; x < byteWidth; x++) {
  1427. var left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
  1428. var val = pxData[pxPos + x] - left;
  1429. rawData[rawPos + x] = val;
  1430. }
  1431. }
  1432. function filterSumSub(pxData, pxPos, byteWidth, bpp) {
  1433. var sum = 0;
  1434. for (var x = 0; x < byteWidth; x++) {
  1435. var left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
  1436. var val = pxData[pxPos + x] - left;
  1437. sum += Math.abs(val);
  1438. }
  1439. return sum;
  1440. }
  1441. function filterUp(pxData, pxPos, byteWidth, rawData, rawPos) {
  1442. for (var x = 0; x < byteWidth; x++) {
  1443. var up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
  1444. var val = pxData[pxPos + x] - up;
  1445. rawData[rawPos + x] = val;
  1446. }
  1447. }
  1448. function filterSumUp(pxData, pxPos, byteWidth) {
  1449. var sum = 0;
  1450. var length = pxPos + byteWidth;
  1451. for (var x = pxPos; x < length; x++) {
  1452. var up = pxPos > 0 ? pxData[x - byteWidth] : 0;
  1453. var val = pxData[x] - up;
  1454. sum += Math.abs(val);
  1455. }
  1456. return sum;
  1457. }
  1458. function filterAvg(pxData, pxPos, byteWidth, rawData, rawPos, bpp) {
  1459. for (var x = 0; x < byteWidth; x++) {
  1460. var left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
  1461. var up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
  1462. var val = pxData[pxPos + x] - ((left + up) >> 1);
  1463. rawData[rawPos + x] = val;
  1464. }
  1465. }
  1466. function filterSumAvg(pxData, pxPos, byteWidth, bpp) {
  1467. var sum = 0;
  1468. for (var x = 0; x < byteWidth; x++) {
  1469. var left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
  1470. var up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
  1471. var val = pxData[pxPos + x] - ((left + up) >> 1);
  1472. sum += Math.abs(val);
  1473. }
  1474. return sum;
  1475. }
  1476. function filterPaeth(pxData, pxPos, byteWidth, rawData, rawPos, bpp) {
  1477. for (var x = 0; x < byteWidth; x++) {
  1478. var left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
  1479. var up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
  1480. var upleft = pxPos > 0 && x >= bpp ? pxData[pxPos + x - (byteWidth + bpp)] : 0;
  1481. var val = pxData[pxPos + x] - paethPredictor(left, up, upleft);
  1482. rawData[rawPos + x] = val;
  1483. }
  1484. }
  1485. function filterSumPaeth(pxData, pxPos, byteWidth, bpp) {
  1486. var sum = 0;
  1487. for (var x = 0; x < byteWidth; x++) {
  1488. var left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
  1489. var up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
  1490. var upleft = pxPos > 0 && x >= bpp ? pxData[pxPos + x - (byteWidth + bpp)] : 0;
  1491. var val = pxData[pxPos + x] - paethPredictor(left, up, upleft);
  1492. sum += Math.abs(val);
  1493. }
  1494. return sum;
  1495. }
  1496. var filters = {
  1497. 0: filterNone,
  1498. 1: filterSub,
  1499. 2: filterUp,
  1500. 3: filterAvg,
  1501. 4: filterPaeth
  1502. };
  1503. var filterSums = {
  1504. 0: filterSumNone,
  1505. 1: filterSumSub,
  1506. 2: filterSumUp,
  1507. 3: filterSumAvg,
  1508. 4: filterSumPaeth
  1509. };
  1510. var filterPack = function(pxData, width, height, options, bpp) {
  1511. var filterTypes;
  1512. if (!('filterType' in options) || options.filterType === -1) {
  1513. filterTypes = [0, 1, 2, 3, 4];
  1514. }
  1515. else if (typeof options.filterType === 'number') {
  1516. filterTypes = [options.filterType];
  1517. }
  1518. else {
  1519. throw new Error('unrecognised filter types');
  1520. }
  1521. if (options.bitDepth === 16) {
  1522. bpp *= 2;
  1523. }
  1524. var byteWidth = width * bpp;
  1525. var rawPos = 0;
  1526. var pxPos = 0;
  1527. var rawData = new Buffer((byteWidth + 1) * height);
  1528. var sel = filterTypes[0];
  1529. for (var y = 0; y < height; y++) {
  1530. if (filterTypes.length > 1) {
  1531. // find best filter for this line (with lowest sum of values)
  1532. var min = Infinity;
  1533. for (var i = 0; i < filterTypes.length; i++) {
  1534. var sum = filterSums[filterTypes[i]](pxData, pxPos, byteWidth, bpp);
  1535. if (sum < min) {
  1536. sel = filterTypes[i];
  1537. min = sum;
  1538. }
  1539. }
  1540. }
  1541. rawData[rawPos] = sel;
  1542. rawPos++;
  1543. filters[sel](pxData, pxPos, byteWidth, rawData, rawPos, bpp);
  1544. rawPos += byteWidth;
  1545. pxPos += byteWidth;
  1546. }
  1547. return rawData;
  1548. };
  1549. var packer = createCommonjsModule(function (module) {
  1550. var Packer = module.exports = function(options) {
  1551. this._options = options;
  1552. options.deflateChunkSize = options.deflateChunkSize || 32 * 1024;
  1553. options.deflateLevel = options.deflateLevel != null ? options.deflateLevel : 9;
  1554. options.deflateStrategy = options.deflateStrategy != null ? options.deflateStrategy : 3;
  1555. options.inputHasAlpha = options.inputHasAlpha != null ? options.inputHasAlpha : true;
  1556. options.deflateFactory = options.deflateFactory || zlib__default['default'].createDeflate;
  1557. options.bitDepth = options.bitDepth || 8;
  1558. // This is outputColorType
  1559. options.colorType = (typeof options.colorType === 'number') ? options.colorType : constants.COLORTYPE_COLOR_ALPHA;
  1560. options.inputColorType = (typeof options.inputColorType === 'number') ? options.inputColorType : constants.COLORTYPE_COLOR_ALPHA;
  1561. if ([
  1562. constants.COLORTYPE_GRAYSCALE,
  1563. constants.COLORTYPE_COLOR,
  1564. constants.COLORTYPE_COLOR_ALPHA,
  1565. constants.COLORTYPE_ALPHA
  1566. ].indexOf(options.colorType) === -1) {
  1567. throw new Error('option color type:' + options.colorType + ' is not supported at present');
  1568. }
  1569. if ([
  1570. constants.COLORTYPE_GRAYSCALE,
  1571. constants.COLORTYPE_COLOR,
  1572. constants.COLORTYPE_COLOR_ALPHA,
  1573. constants.COLORTYPE_ALPHA
  1574. ].indexOf(options.inputColorType) === -1) {
  1575. throw new Error('option input color type:' + options.inputColorType + ' is not supported at present');
  1576. }
  1577. if (options.bitDepth !== 8 && options.bitDepth !== 16) {
  1578. throw new Error('option bit depth:' + options.bitDepth + ' is not supported at present');
  1579. }
  1580. };
  1581. Packer.prototype.getDeflateOptions = function() {
  1582. return {
  1583. chunkSize: this._options.deflateChunkSize,
  1584. level: this._options.deflateLevel,
  1585. strategy: this._options.deflateStrategy
  1586. };
  1587. };
  1588. Packer.prototype.createDeflate = function() {
  1589. return this._options.deflateFactory(this.getDeflateOptions());
  1590. };
  1591. Packer.prototype.filterData = function(data, width, height) {
  1592. // convert to correct format for filtering (e.g. right bpp and bit depth)
  1593. var packedData = bitpacker(data, width, height, this._options);
  1594. // filter pixel data
  1595. var bpp = constants.COLORTYPE_TO_BPP_MAP[this._options.colorType];
  1596. var filteredData = filterPack(packedData, width, height, this._options, bpp);
  1597. return filteredData;
  1598. };
  1599. Packer.prototype._packChunk = function(type, data) {
  1600. var len = (data ? data.length : 0);
  1601. var buf = new Buffer(len + 12);
  1602. buf.writeUInt32BE(len, 0);
  1603. buf.writeUInt32BE(type, 4);
  1604. if (data) {
  1605. data.copy(buf, 8);
  1606. }
  1607. buf.writeInt32BE(crc.crc32(buf.slice(4, buf.length - 4)), buf.length - 4);
  1608. return buf;
  1609. };
  1610. Packer.prototype.packGAMA = function(gamma) {
  1611. var buf = new Buffer(4);
  1612. buf.writeUInt32BE(Math.floor(gamma * constants.GAMMA_DIVISION), 0);
  1613. return this._packChunk(constants.TYPE_gAMA, buf);
  1614. };
  1615. Packer.prototype.packIHDR = function(width, height) {
  1616. var buf = new Buffer(13);
  1617. buf.writeUInt32BE(width, 0);
  1618. buf.writeUInt32BE(height, 4);
  1619. buf[8] = this._options.bitDepth; // Bit depth
  1620. buf[9] = this._options.colorType; // colorType
  1621. buf[10] = 0; // compression
  1622. buf[11] = 0; // filter
  1623. buf[12] = 0; // interlace
  1624. return this._packChunk(constants.TYPE_IHDR, buf);
  1625. };
  1626. Packer.prototype.packIDAT = function(data) {
  1627. return this._packChunk(constants.TYPE_IDAT, data);
  1628. };
  1629. Packer.prototype.packIEND = function() {
  1630. return this._packChunk(constants.TYPE_IEND, null);
  1631. };
  1632. });
  1633. var packerAsync = createCommonjsModule(function (module) {
  1634. var PackerAsync = module.exports = function(opt) {
  1635. Stream__default['default'].call(this);
  1636. var options = opt || {};
  1637. this._packer = new packer(options);
  1638. this._deflate = this._packer.createDeflate();
  1639. this.readable = true;
  1640. };
  1641. util__default['default'].inherits(PackerAsync, Stream__default['default']);
  1642. PackerAsync.prototype.pack = function(data, width, height, gamma) {
  1643. // Signature
  1644. this.emit('data', new Buffer(constants.PNG_SIGNATURE));
  1645. this.emit('data', this._packer.packIHDR(width, height));
  1646. if (gamma) {
  1647. this.emit('data', this._packer.packGAMA(gamma));
  1648. }
  1649. var filteredData = this._packer.filterData(data, width, height);
  1650. // compress it
  1651. this._deflate.on('error', this.emit.bind(this, 'error'));
  1652. this._deflate.on('data', function(compressedData) {
  1653. this.emit('data', this._packer.packIDAT(compressedData));
  1654. }.bind(this));
  1655. this._deflate.on('end', function() {
  1656. this.emit('data', this._packer.packIEND());
  1657. this.emit('end');
  1658. }.bind(this));
  1659. this._deflate.end(filteredData);
  1660. };
  1661. });
  1662. var syncInflate = createCommonjsModule(function (module, exports) {
  1663. var assert = require$$0__default['default'].ok;
  1664. var kMaxLength = require$$1__default['default'].kMaxLength;
  1665. function Inflate(opts) {
  1666. if (!(this instanceof Inflate)) {
  1667. return new Inflate(opts);
  1668. }
  1669. if (opts && opts.chunkSize < zlib__default['default'].Z_MIN_CHUNK) {
  1670. opts.chunkSize = zlib__default['default'].Z_MIN_CHUNK;
  1671. }
  1672. zlib__default['default'].Inflate.call(this, opts);
  1673. // Node 8 --> 9 compatibility check
  1674. this._offset = this._offset === undefined ? this._outOffset : this._offset;
  1675. this._buffer = this._buffer || this._outBuffer;
  1676. if (opts && opts.maxLength != null) {
  1677. this._maxLength = opts.maxLength;
  1678. }
  1679. }
  1680. function createInflate(opts) {
  1681. return new Inflate(opts);
  1682. }
  1683. function _close(engine, callback) {
  1684. if (callback) {
  1685. process.nextTick(callback);
  1686. }
  1687. // Caller may invoke .close after a zlib error (which will null _handle).
  1688. if (!engine._handle) {
  1689. return;
  1690. }
  1691. engine._handle.close();
  1692. engine._handle = null;
  1693. }
  1694. Inflate.prototype._processChunk = function(chunk, flushFlag, asyncCb) {
  1695. if (typeof asyncCb === 'function') {
  1696. return zlib__default['default'].Inflate._processChunk.call(this, chunk, flushFlag, asyncCb);
  1697. }
  1698. var self = this;
  1699. var availInBefore = chunk && chunk.length;
  1700. var availOutBefore = this._chunkSize - this._offset;
  1701. var leftToInflate = this._maxLength;
  1702. var inOff = 0;
  1703. var buffers = [];
  1704. var nread = 0;
  1705. var error;
  1706. this.on('error', function(err) {
  1707. error = err;
  1708. });
  1709. function handleChunk(availInAfter, availOutAfter) {
  1710. if (self._hadError) {
  1711. return;
  1712. }
  1713. var have = availOutBefore - availOutAfter;
  1714. assert(have >= 0, 'have should not go down');
  1715. if (have > 0) {
  1716. var out = self._buffer.slice(self._offset, self._offset + have);
  1717. self._offset += have;
  1718. if (out.length > leftToInflate) {
  1719. out = out.slice(0, leftToInflate);
  1720. }
  1721. buffers.push(out);
  1722. nread += out.length;
  1723. leftToInflate -= out.length;
  1724. if (leftToInflate === 0) {
  1725. return false;
  1726. }
  1727. }
  1728. if (availOutAfter === 0 || self._offset >= self._chunkSize) {
  1729. availOutBefore = self._chunkSize;
  1730. self._offset = 0;
  1731. self._buffer = Buffer.allocUnsafe(self._chunkSize);
  1732. }
  1733. if (availOutAfter === 0) {
  1734. inOff += (availInBefore - availInAfter);
  1735. availInBefore = availInAfter;
  1736. return true;
  1737. }
  1738. return false;
  1739. }
  1740. assert(this._handle, 'zlib binding closed');
  1741. do {
  1742. var res = this._handle.writeSync(flushFlag,
  1743. chunk, // in
  1744. inOff, // in_off
  1745. availInBefore, // in_len
  1746. this._buffer, // out
  1747. this._offset, //out_off
  1748. availOutBefore); // out_len
  1749. // Node 8 --> 9 compatibility check
  1750. res = res || this._writeState;
  1751. } while (!this._hadError && handleChunk(res[0], res[1]));
  1752. if (this._hadError) {
  1753. throw error;
  1754. }
  1755. if (nread >= kMaxLength) {
  1756. _close(this);
  1757. throw new RangeError('Cannot create final Buffer. It would be larger than 0x' + kMaxLength.toString(16) + ' bytes');
  1758. }
  1759. var buf = Buffer.concat(buffers, nread);
  1760. _close(this);
  1761. return buf;
  1762. };
  1763. util__default['default'].inherits(Inflate, zlib__default['default'].Inflate);
  1764. function zlibBufferSync(engine, buffer) {
  1765. if (typeof buffer === 'string') {
  1766. buffer = Buffer.from(buffer);
  1767. }
  1768. if (!(buffer instanceof Buffer)) {
  1769. throw new TypeError('Not a string or buffer');
  1770. }
  1771. var flushFlag = engine._finishFlushFlag;
  1772. if (flushFlag == null) {
  1773. flushFlag = zlib__default['default'].Z_FINISH;
  1774. }
  1775. return engine._processChunk(buffer, flushFlag);
  1776. }
  1777. function inflateSync(buffer, opts) {
  1778. return zlibBufferSync(new Inflate(opts), buffer);
  1779. }
  1780. module.exports = exports = inflateSync;
  1781. exports.Inflate = Inflate;
  1782. exports.createInflate = createInflate;
  1783. exports.inflateSync = inflateSync;
  1784. });
  1785. var syncReader = createCommonjsModule(function (module) {
  1786. var SyncReader = module.exports = function(buffer) {
  1787. this._buffer = buffer;
  1788. this._reads = [];
  1789. };
  1790. SyncReader.prototype.read = function(length, callback) {
  1791. this._reads.push({
  1792. length: Math.abs(length), // if length < 0 then at most this length
  1793. allowLess: length < 0,
  1794. func: callback
  1795. });
  1796. };
  1797. SyncReader.prototype.process = function() {
  1798. // as long as there is any data and read requests
  1799. while (this._reads.length > 0 && this._buffer.length) {
  1800. var read = this._reads[0];
  1801. if (this._buffer.length && (this._buffer.length >= read.length || read.allowLess)) {
  1802. // ok there is any data so that we can satisfy this request
  1803. this._reads.shift(); // == read
  1804. var buf = this._buffer;
  1805. this._buffer = buf.slice(read.length);
  1806. read.func.call(this, buf.slice(0, read.length));
  1807. }
  1808. else {
  1809. break;
  1810. }
  1811. }
  1812. if (this._reads.length > 0) {
  1813. return new Error('There are some read requests waitng on finished stream');
  1814. }
  1815. if (this._buffer.length > 0) {
  1816. return new Error('unrecognised content at end of stream');
  1817. }
  1818. };
  1819. });
  1820. var process_1 = function(inBuffer, bitmapInfo) {
  1821. var outBuffers = [];
  1822. var reader = new syncReader(inBuffer);
  1823. var filter = new filterParse(bitmapInfo, {
  1824. read: reader.read.bind(reader),
  1825. write: function(bufferPart) {
  1826. outBuffers.push(bufferPart);
  1827. },
  1828. complete: function() {
  1829. }
  1830. });
  1831. filter.start();
  1832. reader.process();
  1833. return Buffer.concat(outBuffers);
  1834. };
  1835. var filterParseSync = {
  1836. process: process_1
  1837. };
  1838. var hasSyncZlib$1 = true;
  1839. if (!zlib__default['default'].deflateSync) {
  1840. hasSyncZlib$1 = false;
  1841. }
  1842. var parserSync = function(buffer, options) {
  1843. if (!hasSyncZlib$1) {
  1844. throw new Error('To use the sync capability of this library in old node versions, please pin pngjs to v2.3.0');
  1845. }
  1846. var err;
  1847. function handleError(_err_) {
  1848. err = _err_;
  1849. }
  1850. var metaData;
  1851. function handleMetaData(_metaData_) {
  1852. metaData = _metaData_;
  1853. }
  1854. function handleTransColor(transColor) {
  1855. metaData.transColor = transColor;
  1856. }
  1857. function handlePalette(palette) {
  1858. metaData.palette = palette;
  1859. }
  1860. function handleSimpleTransparency() {
  1861. metaData.alpha = true;
  1862. }
  1863. var gamma;
  1864. function handleGamma(_gamma_) {
  1865. gamma = _gamma_;
  1866. }
  1867. var inflateDataList = [];
  1868. function handleInflateData(inflatedData) {
  1869. inflateDataList.push(inflatedData);
  1870. }
  1871. var reader = new syncReader(buffer);
  1872. var parser$1 = new parser(options, {
  1873. read: reader.read.bind(reader),
  1874. error: handleError,
  1875. metadata: handleMetaData,
  1876. gamma: handleGamma,
  1877. palette: handlePalette,
  1878. transColor: handleTransColor,
  1879. inflateData: handleInflateData,
  1880. simpleTransparency: handleSimpleTransparency
  1881. });
  1882. parser$1.start();
  1883. reader.process();
  1884. if (err) {
  1885. throw err;
  1886. }
  1887. //join together the inflate datas
  1888. var inflateData = Buffer.concat(inflateDataList);
  1889. inflateDataList.length = 0;
  1890. var inflatedData;
  1891. if (metaData.interlace) {
  1892. inflatedData = zlib__default['default'].inflateSync(inflateData);
  1893. }
  1894. else {
  1895. var rowSize = ((metaData.width * metaData.bpp * metaData.depth + 7) >> 3) + 1;
  1896. var imageSize = rowSize * metaData.height;
  1897. inflatedData = syncInflate(inflateData, { chunkSize: imageSize, maxLength: imageSize });
  1898. }
  1899. inflateData = null;
  1900. if (!inflatedData || !inflatedData.length) {
  1901. throw new Error('bad png - invalid inflate data response');
  1902. }
  1903. var unfilteredData = filterParseSync.process(inflatedData, metaData);
  1904. inflateData = null;
  1905. var bitmapData = bitmapper.dataToBitMap(unfilteredData, metaData);
  1906. unfilteredData = null;
  1907. var normalisedBitmapData = formatNormaliser(bitmapData, metaData);
  1908. metaData.data = normalisedBitmapData;
  1909. metaData.gamma = gamma || 0;
  1910. return metaData;
  1911. };
  1912. var hasSyncZlib = true;
  1913. if (!zlib__default['default'].deflateSync) {
  1914. hasSyncZlib = false;
  1915. }
  1916. var packerSync = function(metaData, opt) {
  1917. if (!hasSyncZlib) {
  1918. throw new Error('To use the sync capability of this library in old node versions, please pin pngjs to v2.3.0');
  1919. }
  1920. var options = opt || {};
  1921. var packer$1 = new packer(options);
  1922. var chunks = [];
  1923. // Signature
  1924. chunks.push(new Buffer(constants.PNG_SIGNATURE));
  1925. // Header
  1926. chunks.push(packer$1.packIHDR(metaData.width, metaData.height));
  1927. if (metaData.gamma) {
  1928. chunks.push(packer$1.packGAMA(metaData.gamma));
  1929. }
  1930. var filteredData = packer$1.filterData(metaData.data, metaData.width, metaData.height);
  1931. // compress it
  1932. var compressedData = zlib__default['default'].deflateSync(filteredData, packer$1.getDeflateOptions());
  1933. filteredData = null;
  1934. if (!compressedData || !compressedData.length) {
  1935. throw new Error('bad png - invalid compressed data response');
  1936. }
  1937. chunks.push(packer$1.packIDAT(compressedData));
  1938. // End
  1939. chunks.push(packer$1.packIEND());
  1940. return Buffer.concat(chunks);
  1941. };
  1942. var read = function(buffer, options) {
  1943. return parserSync(buffer, options || {});
  1944. };
  1945. var write = function(png, options) {
  1946. return packerSync(png, options);
  1947. };
  1948. var pngSync = {
  1949. read: read,
  1950. write: write
  1951. };
  1952. var png = createCommonjsModule(function (module, exports) {
  1953. var PNG = exports.PNG = function(options) {
  1954. Stream__default['default'].call(this);
  1955. options = options || {}; // eslint-disable-line no-param-reassign
  1956. // coerce pixel dimensions to integers (also coerces undefined -> 0):
  1957. this.width = options.width | 0;
  1958. this.height = options.height | 0;
  1959. this.data = this.width > 0 && this.height > 0 ?
  1960. new Buffer(4 * this.width * this.height) : null;
  1961. if (options.fill && this.data) {
  1962. this.data.fill(0);
  1963. }
  1964. this.gamma = 0;
  1965. this.readable = this.writable = true;
  1966. this._parser = new parserAsync(options);
  1967. this._parser.on('error', this.emit.bind(this, 'error'));
  1968. this._parser.on('close', this._handleClose.bind(this));
  1969. this._parser.on('metadata', this._metadata.bind(this));
  1970. this._parser.on('gamma', this._gamma.bind(this));
  1971. this._parser.on('parsed', function(data) {
  1972. this.data = data;
  1973. this.emit('parsed', data);
  1974. }.bind(this));
  1975. this._packer = new packerAsync(options);
  1976. this._packer.on('data', this.emit.bind(this, 'data'));
  1977. this._packer.on('end', this.emit.bind(this, 'end'));
  1978. this._parser.on('close', this._handleClose.bind(this));
  1979. this._packer.on('error', this.emit.bind(this, 'error'));
  1980. };
  1981. util__default['default'].inherits(PNG, Stream__default['default']);
  1982. PNG.sync = pngSync;
  1983. PNG.prototype.pack = function() {
  1984. if (!this.data || !this.data.length) {
  1985. this.emit('error', 'No data provided');
  1986. return this;
  1987. }
  1988. process.nextTick(function() {
  1989. this._packer.pack(this.data, this.width, this.height, this.gamma);
  1990. }.bind(this));
  1991. return this;
  1992. };
  1993. PNG.prototype.parse = function(data, callback) {
  1994. if (callback) {
  1995. var onParsed, onError;
  1996. onParsed = function(parsedData) {
  1997. this.removeListener('error', onError);
  1998. this.data = parsedData;
  1999. callback(null, this);
  2000. }.bind(this);
  2001. onError = function(err) {
  2002. this.removeListener('parsed', onParsed);
  2003. callback(err, null);
  2004. }.bind(this);
  2005. this.once('parsed', onParsed);
  2006. this.once('error', onError);
  2007. }
  2008. this.end(data);
  2009. return this;
  2010. };
  2011. PNG.prototype.write = function(data) {
  2012. this._parser.write(data);
  2013. return true;
  2014. };
  2015. PNG.prototype.end = function(data) {
  2016. this._parser.end(data);
  2017. };
  2018. PNG.prototype._metadata = function(metadata) {
  2019. this.width = metadata.width;
  2020. this.height = metadata.height;
  2021. this.emit('metadata', metadata);
  2022. };
  2023. PNG.prototype._gamma = function(gamma) {
  2024. this.gamma = gamma;
  2025. };
  2026. PNG.prototype._handleClose = function() {
  2027. if (!this._parser.writable && !this._packer.readable) {
  2028. this.emit('close');
  2029. }
  2030. };
  2031. PNG.bitblt = function(src, dst, srcX, srcY, width, height, deltaX, deltaY) { // eslint-disable-line max-params
  2032. // coerce pixel dimensions to integers (also coerces undefined -> 0):
  2033. /* eslint-disable no-param-reassign */
  2034. srcX |= 0;
  2035. srcY |= 0;
  2036. width |= 0;
  2037. height |= 0;
  2038. deltaX |= 0;
  2039. deltaY |= 0;
  2040. /* eslint-enable no-param-reassign */
  2041. if (srcX > src.width || srcY > src.height || srcX + width > src.width || srcY + height > src.height) {
  2042. throw new Error('bitblt reading outside image');
  2043. }
  2044. if (deltaX > dst.width || deltaY > dst.height || deltaX + width > dst.width || deltaY + height > dst.height) {
  2045. throw new Error('bitblt writing outside image');
  2046. }
  2047. for (var y = 0; y < height; y++) {
  2048. src.data.copy(dst.data,
  2049. ((deltaY + y) * dst.width + deltaX) << 2,
  2050. ((srcY + y) * src.width + srcX) << 2,
  2051. ((srcY + y) * src.width + srcX + width) << 2
  2052. );
  2053. }
  2054. };
  2055. PNG.prototype.bitblt = function(dst, srcX, srcY, width, height, deltaX, deltaY) { // eslint-disable-line max-params
  2056. PNG.bitblt(this, dst, srcX, srcY, width, height, deltaX, deltaY);
  2057. return this;
  2058. };
  2059. PNG.adjustGamma = function(src) {
  2060. if (src.gamma) {
  2061. for (var y = 0; y < src.height; y++) {
  2062. for (var x = 0; x < src.width; x++) {
  2063. var idx = (src.width * y + x) << 2;
  2064. for (var i = 0; i < 3; i++) {
  2065. var sample = src.data[idx + i] / 255;
  2066. sample = Math.pow(sample, 1 / 2.2 / src.gamma);
  2067. src.data[idx + i] = Math.round(sample * 255);
  2068. }
  2069. }
  2070. }
  2071. src.gamma = 0;
  2072. }
  2073. };
  2074. PNG.prototype.adjustGamma = function() {
  2075. PNG.adjustGamma(this);
  2076. };
  2077. });
  2078. function getMismatchedPixels(pixelMatchInput) {
  2079. const imgA = fs__default['default'].createReadStream(pixelMatchInput.imageAPath).pipe(new png.PNG()).on('parsed', doneReading);
  2080. const imgB = fs__default['default'].createReadStream(pixelMatchInput.imageBPath).pipe(new png.PNG()).on('parsed', doneReading);
  2081. let filesRead = 0;
  2082. function doneReading() {
  2083. if (++filesRead < 2)
  2084. return;
  2085. const mismatchedPixels = pixelmatch_1(imgA.data, imgB.data, null, pixelMatchInput.width, pixelMatchInput.height, {
  2086. threshold: pixelMatchInput.pixelmatchThreshold,
  2087. includeAA: false,
  2088. });
  2089. process.send(mismatchedPixels);
  2090. }
  2091. }
  2092. process.on('message', getMismatchedPixels);