pixel-match.js 70 KB

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