12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807 |
- 'use strict';
- var fs = require('fs');
- var util = require('util');
- var Stream = require('stream');
- var zlib = require('zlib');
- var require$$0 = require('assert');
- var require$$1 = require('buffer');
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
- var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
- var util__default = /*#__PURE__*/_interopDefaultLegacy(util);
- var Stream__default = /*#__PURE__*/_interopDefaultLegacy(Stream);
- var zlib__default = /*#__PURE__*/_interopDefaultLegacy(zlib);
- var require$$0__default = /*#__PURE__*/_interopDefaultLegacy(require$$0);
- var require$$1__default = /*#__PURE__*/_interopDefaultLegacy(require$$1);
- var pixelmatch_1 = pixelmatch;
- const defaultOptions = {
- threshold: 0.1, // matching threshold (0 to 1); smaller is more sensitive
- includeAA: false, // whether to skip anti-aliasing detection
- alpha: 0.1, // opacity of original image in diff output
- aaColor: [255, 255, 0], // color of anti-aliased pixels in diff output
- diffColor: [255, 0, 0], // color of different pixels in diff output
- diffColorAlt: null, // whether to detect dark on light differences between img1 and img2 and set an alternative color to differentiate between the two
- diffMask: false // draw the diff over a transparent background (a mask)
- };
- function pixelmatch(img1, img2, output, width, height, options) {
- if (!isPixelData(img1) || !isPixelData(img2) || (output && !isPixelData(output)))
- throw new Error('Image data: Uint8Array, Uint8ClampedArray or Buffer expected.');
- if (img1.length !== img2.length || (output && output.length !== img1.length))
- throw new Error('Image sizes do not match.');
- if (img1.length !== width * height * 4) throw new Error('Image data size does not match width/height.');
- options = Object.assign({}, defaultOptions, options);
- // check if images are identical
- const len = width * height;
- const a32 = new Uint32Array(img1.buffer, img1.byteOffset, len);
- const b32 = new Uint32Array(img2.buffer, img2.byteOffset, len);
- let identical = true;
- for (let i = 0; i < len; i++) {
- if (a32[i] !== b32[i]) { identical = false; break; }
- }
- if (identical) { // fast path if identical
- if (output && !options.diffMask) {
- for (let i = 0; i < len; i++) drawGrayPixel(img1, 4 * i, options.alpha, output);
- }
- return 0;
- }
- // maximum acceptable square distance between two colors;
- // 35215 is the maximum possible value for the YIQ difference metric
- const maxDelta = 35215 * options.threshold * options.threshold;
- let diff = 0;
- // compare each pixel of one image against the other one
- for (let y = 0; y < height; y++) {
- for (let x = 0; x < width; x++) {
- const pos = (y * width + x) * 4;
- // squared YUV distance between colors at this pixel position, negative if the img2 pixel is darker
- const delta = colorDelta(img1, img2, pos, pos);
- // the color difference is above the threshold
- if (Math.abs(delta) > maxDelta) {
- // check it's a real rendering difference or just anti-aliasing
- if (!options.includeAA && (antialiased(img1, x, y, width, height, img2) ||
- antialiased(img2, x, y, width, height, img1))) {
- // one of the pixels is anti-aliasing; draw as yellow and do not count as difference
- // note that we do not include such pixels in a mask
- if (output && !options.diffMask) drawPixel(output, pos, ...options.aaColor);
- } else {
- // found substantial difference not caused by anti-aliasing; draw it as such
- if (output) {
- drawPixel(output, pos, ...(delta < 0 && options.diffColorAlt || options.diffColor));
- }
- diff++;
- }
- } else if (output) {
- // pixels are similar; draw background as grayscale image blended with white
- if (!options.diffMask) drawGrayPixel(img1, pos, options.alpha, output);
- }
- }
- }
- // return the number of different pixels
- return diff;
- }
- function isPixelData(arr) {
- // work around instanceof Uint8Array not working properly in some Jest environments
- return ArrayBuffer.isView(arr) && arr.constructor.BYTES_PER_ELEMENT === 1;
- }
- // check if a pixel is likely a part of anti-aliasing;
- // based on "Anti-aliased Pixel and Intensity Slope Detector" paper by V. Vysniauskas, 2009
- function antialiased(img, x1, y1, width, height, img2) {
- const x0 = Math.max(x1 - 1, 0);
- const y0 = Math.max(y1 - 1, 0);
- const x2 = Math.min(x1 + 1, width - 1);
- const y2 = Math.min(y1 + 1, height - 1);
- const pos = (y1 * width + x1) * 4;
- let zeroes = x1 === x0 || x1 === x2 || y1 === y0 || y1 === y2 ? 1 : 0;
- let min = 0;
- let max = 0;
- let minX, minY, maxX, maxY;
- // go through 8 adjacent pixels
- for (let x = x0; x <= x2; x++) {
- for (let y = y0; y <= y2; y++) {
- if (x === x1 && y === y1) continue;
- // brightness delta between the center pixel and adjacent one
- const delta = colorDelta(img, img, pos, (y * width + x) * 4, true);
- // count the number of equal, darker and brighter adjacent pixels
- if (delta === 0) {
- zeroes++;
- // if found more than 2 equal siblings, it's definitely not anti-aliasing
- if (zeroes > 2) return false;
- // remember the darkest pixel
- } else if (delta < min) {
- min = delta;
- minX = x;
- minY = y;
- // remember the brightest pixel
- } else if (delta > max) {
- max = delta;
- maxX = x;
- maxY = y;
- }
- }
- }
- // if there are no both darker and brighter pixels among siblings, it's not anti-aliasing
- if (min === 0 || max === 0) return false;
- // if either the darkest or the brightest pixel has 3+ equal siblings in both images
- // (definitely not anti-aliased), this pixel is anti-aliased
- return (hasManySiblings(img, minX, minY, width, height) && hasManySiblings(img2, minX, minY, width, height)) ||
- (hasManySiblings(img, maxX, maxY, width, height) && hasManySiblings(img2, maxX, maxY, width, height));
- }
- // check if a pixel has 3+ adjacent pixels of the same color.
- function hasManySiblings(img, x1, y1, width, height) {
- const x0 = Math.max(x1 - 1, 0);
- const y0 = Math.max(y1 - 1, 0);
- const x2 = Math.min(x1 + 1, width - 1);
- const y2 = Math.min(y1 + 1, height - 1);
- const pos = (y1 * width + x1) * 4;
- let zeroes = x1 === x0 || x1 === x2 || y1 === y0 || y1 === y2 ? 1 : 0;
- // go through 8 adjacent pixels
- for (let x = x0; x <= x2; x++) {
- for (let y = y0; y <= y2; y++) {
- if (x === x1 && y === y1) continue;
- const pos2 = (y * width + x) * 4;
- if (img[pos] === img[pos2] &&
- img[pos + 1] === img[pos2 + 1] &&
- img[pos + 2] === img[pos2 + 2] &&
- img[pos + 3] === img[pos2 + 3]) zeroes++;
- if (zeroes > 2) return true;
- }
- }
- return false;
- }
- // calculate color difference according to the paper "Measuring perceived color difference
- // using YIQ NTSC transmission color space in mobile applications" by Y. Kotsarenko and F. Ramos
- function colorDelta(img1, img2, k, m, yOnly) {
- let r1 = img1[k + 0];
- let g1 = img1[k + 1];
- let b1 = img1[k + 2];
- let a1 = img1[k + 3];
- let r2 = img2[m + 0];
- let g2 = img2[m + 1];
- let b2 = img2[m + 2];
- let a2 = img2[m + 3];
- if (a1 === a2 && r1 === r2 && g1 === g2 && b1 === b2) return 0;
- if (a1 < 255) {
- a1 /= 255;
- r1 = blend(r1, a1);
- g1 = blend(g1, a1);
- b1 = blend(b1, a1);
- }
- if (a2 < 255) {
- a2 /= 255;
- r2 = blend(r2, a2);
- g2 = blend(g2, a2);
- b2 = blend(b2, a2);
- }
- const y1 = rgb2y(r1, g1, b1);
- const y2 = rgb2y(r2, g2, b2);
- const y = y1 - y2;
- if (yOnly) return y; // brightness difference only
- const i = rgb2i(r1, g1, b1) - rgb2i(r2, g2, b2);
- const q = rgb2q(r1, g1, b1) - rgb2q(r2, g2, b2);
- const delta = 0.5053 * y * y + 0.299 * i * i + 0.1957 * q * q;
- // encode whether the pixel lightens or darkens in the sign
- return y1 > y2 ? -delta : delta;
- }
- function rgb2y(r, g, b) { return r * 0.29889531 + g * 0.58662247 + b * 0.11448223; }
- function rgb2i(r, g, b) { return r * 0.59597799 - g * 0.27417610 - b * 0.32180189; }
- function rgb2q(r, g, b) { return r * 0.21147017 - g * 0.52261711 + b * 0.31114694; }
- // blend semi-transparent color with white
- function blend(c, a) {
- return 255 + (c - 255) * a;
- }
- function drawPixel(output, pos, r, g, b) {
- output[pos + 0] = r;
- output[pos + 1] = g;
- output[pos + 2] = b;
- output[pos + 3] = 255;
- }
- function drawGrayPixel(img, i, alpha, output) {
- const r = img[i + 0];
- const g = img[i + 1];
- const b = img[i + 2];
- const val = blend(rgb2y(r, g, b), alpha * img[i + 3] / 255);
- drawPixel(output, i, val, val, val);
- }
- function createCommonjsModule(fn, basedir, module) {
- return module = {
- path: basedir,
- exports: {},
- require: function (path, base) {
- return commonjsRequire(path, (base === undefined || base === null) ? module.path : base);
- }
- }, fn(module, module.exports), module.exports;
- }
- function commonjsRequire () {
- throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs');
- }
- var chunkstream = createCommonjsModule(function (module) {
- let ChunkStream = (module.exports = function () {
- Stream__default['default'].call(this);
- this._buffers = [];
- this._buffered = 0;
- this._reads = [];
- this._paused = false;
- this._encoding = "utf8";
- this.writable = true;
- });
- util__default['default'].inherits(ChunkStream, Stream__default['default']);
- ChunkStream.prototype.read = function (length, callback) {
- this._reads.push({
- length: Math.abs(length), // if length < 0 then at most this length
- allowLess: length < 0,
- func: callback,
- });
- process.nextTick(
- function () {
- this._process();
- // its paused and there is not enought data then ask for more
- if (this._paused && this._reads && this._reads.length > 0) {
- this._paused = false;
- this.emit("drain");
- }
- }.bind(this)
- );
- };
- ChunkStream.prototype.write = function (data, encoding) {
- if (!this.writable) {
- this.emit("error", new Error("Stream not writable"));
- return false;
- }
- let dataBuffer;
- if (Buffer.isBuffer(data)) {
- dataBuffer = data;
- } else {
- dataBuffer = Buffer.from(data, encoding || this._encoding);
- }
- this._buffers.push(dataBuffer);
- this._buffered += dataBuffer.length;
- this._process();
- // ok if there are no more read requests
- if (this._reads && this._reads.length === 0) {
- this._paused = true;
- }
- return this.writable && !this._paused;
- };
- ChunkStream.prototype.end = function (data, encoding) {
- if (data) {
- this.write(data, encoding);
- }
- this.writable = false;
- // already destroyed
- if (!this._buffers) {
- return;
- }
- // enqueue or handle end
- if (this._buffers.length === 0) {
- this._end();
- } else {
- this._buffers.push(null);
- this._process();
- }
- };
- ChunkStream.prototype.destroySoon = ChunkStream.prototype.end;
- ChunkStream.prototype._end = function () {
- if (this._reads.length > 0) {
- this.emit("error", new Error("Unexpected end of input"));
- }
- this.destroy();
- };
- ChunkStream.prototype.destroy = function () {
- if (!this._buffers) {
- return;
- }
- this.writable = false;
- this._reads = null;
- this._buffers = null;
- this.emit("close");
- };
- ChunkStream.prototype._processReadAllowingLess = function (read) {
- // ok there is any data so that we can satisfy this request
- this._reads.shift(); // == read
- // first we need to peek into first buffer
- let smallerBuf = this._buffers[0];
- // ok there is more data than we need
- if (smallerBuf.length > read.length) {
- this._buffered -= read.length;
- this._buffers[0] = smallerBuf.slice(read.length);
- read.func.call(this, smallerBuf.slice(0, read.length));
- } else {
- // ok this is less than maximum length so use it all
- this._buffered -= smallerBuf.length;
- this._buffers.shift(); // == smallerBuf
- read.func.call(this, smallerBuf);
- }
- };
- ChunkStream.prototype._processRead = function (read) {
- this._reads.shift(); // == read
- let pos = 0;
- let count = 0;
- let data = Buffer.alloc(read.length);
- // create buffer for all data
- while (pos < read.length) {
- let buf = this._buffers[count++];
- let len = Math.min(buf.length, read.length - pos);
- buf.copy(data, pos, 0, len);
- pos += len;
- // last buffer wasn't used all so just slice it and leave
- if (len !== buf.length) {
- this._buffers[--count] = buf.slice(len);
- }
- }
- // remove all used buffers
- if (count > 0) {
- this._buffers.splice(0, count);
- }
- this._buffered -= read.length;
- read.func.call(this, data);
- };
- ChunkStream.prototype._process = function () {
- try {
- // as long as there is any data and read requests
- while (this._buffered > 0 && this._reads && this._reads.length > 0) {
- let read = this._reads[0];
- // read any data (but no more than length)
- if (read.allowLess) {
- this._processReadAllowingLess(read);
- } else if (this._buffered >= read.length) {
- // ok we can meet some expectations
- this._processRead(read);
- } else {
- // not enought data to satisfy first request in queue
- // so we need to wait for more
- break;
- }
- }
- if (this._buffers && !this.writable) {
- this._end();
- }
- } catch (ex) {
- this.emit("error", ex);
- }
- };
- });
- // Adam 7
- // 0 1 2 3 4 5 6 7
- // 0 x 6 4 6 x 6 4 6
- // 1 7 7 7 7 7 7 7 7
- // 2 5 6 5 6 5 6 5 6
- // 3 7 7 7 7 7 7 7 7
- // 4 3 6 4 6 3 6 4 6
- // 5 7 7 7 7 7 7 7 7
- // 6 5 6 5 6 5 6 5 6
- // 7 7 7 7 7 7 7 7 7
- let imagePasses = [
- {
- // pass 1 - 1px
- x: [0],
- y: [0],
- },
- {
- // pass 2 - 1px
- x: [4],
- y: [0],
- },
- {
- // pass 3 - 2px
- x: [0, 4],
- y: [4],
- },
- {
- // pass 4 - 4px
- x: [2, 6],
- y: [0, 4],
- },
- {
- // pass 5 - 8px
- x: [0, 2, 4, 6],
- y: [2, 6],
- },
- {
- // pass 6 - 16px
- x: [1, 3, 5, 7],
- y: [0, 2, 4, 6],
- },
- {
- // pass 7 - 32px
- x: [0, 1, 2, 3, 4, 5, 6, 7],
- y: [1, 3, 5, 7],
- },
- ];
- var getImagePasses = function (width, height) {
- let images = [];
- let xLeftOver = width % 8;
- let yLeftOver = height % 8;
- let xRepeats = (width - xLeftOver) / 8;
- let yRepeats = (height - yLeftOver) / 8;
- for (let i = 0; i < imagePasses.length; i++) {
- let pass = imagePasses[i];
- let passWidth = xRepeats * pass.x.length;
- let passHeight = yRepeats * pass.y.length;
- for (let j = 0; j < pass.x.length; j++) {
- if (pass.x[j] < xLeftOver) {
- passWidth++;
- } else {
- break;
- }
- }
- for (let j = 0; j < pass.y.length; j++) {
- if (pass.y[j] < yLeftOver) {
- passHeight++;
- } else {
- break;
- }
- }
- if (passWidth > 0 && passHeight > 0) {
- images.push({ width: passWidth, height: passHeight, index: i });
- }
- }
- return images;
- };
- var getInterlaceIterator = function (width) {
- return function (x, y, pass) {
- let outerXLeftOver = x % imagePasses[pass].x.length;
- let outerX =
- ((x - outerXLeftOver) / imagePasses[pass].x.length) * 8 +
- imagePasses[pass].x[outerXLeftOver];
- let outerYLeftOver = y % imagePasses[pass].y.length;
- let outerY =
- ((y - outerYLeftOver) / imagePasses[pass].y.length) * 8 +
- imagePasses[pass].y[outerYLeftOver];
- return outerX * 4 + outerY * width * 4;
- };
- };
- var interlace = {
- getImagePasses: getImagePasses,
- getInterlaceIterator: getInterlaceIterator
- };
- var paethPredictor = function paethPredictor(left, above, upLeft) {
- let paeth = left + above - upLeft;
- let pLeft = Math.abs(paeth - left);
- let pAbove = Math.abs(paeth - above);
- let pUpLeft = Math.abs(paeth - upLeft);
- if (pLeft <= pAbove && pLeft <= pUpLeft) {
- return left;
- }
- if (pAbove <= pUpLeft) {
- return above;
- }
- return upLeft;
- };
- var filterParse = createCommonjsModule(function (module) {
- function getByteWidth(width, bpp, depth) {
- let byteWidth = width * bpp;
- if (depth !== 8) {
- byteWidth = Math.ceil(byteWidth / (8 / depth));
- }
- return byteWidth;
- }
- let Filter = (module.exports = function (bitmapInfo, dependencies) {
- let width = bitmapInfo.width;
- let height = bitmapInfo.height;
- let interlace$1 = bitmapInfo.interlace;
- let bpp = bitmapInfo.bpp;
- let depth = bitmapInfo.depth;
- this.read = dependencies.read;
- this.write = dependencies.write;
- this.complete = dependencies.complete;
- this._imageIndex = 0;
- this._images = [];
- if (interlace$1) {
- let passes = interlace.getImagePasses(width, height);
- for (let i = 0; i < passes.length; i++) {
- this._images.push({
- byteWidth: getByteWidth(passes[i].width, bpp, depth),
- height: passes[i].height,
- lineIndex: 0,
- });
- }
- } else {
- this._images.push({
- byteWidth: getByteWidth(width, bpp, depth),
- height: height,
- lineIndex: 0,
- });
- }
- // when filtering the line we look at the pixel to the left
- // the spec also says it is done on a byte level regardless of the number of pixels
- // so if the depth is byte compatible (8 or 16) we subtract the bpp in order to compare back
- // a pixel rather than just a different byte part. However if we are sub byte, we ignore.
- if (depth === 8) {
- this._xComparison = bpp;
- } else if (depth === 16) {
- this._xComparison = bpp * 2;
- } else {
- this._xComparison = 1;
- }
- });
- Filter.prototype.start = function () {
- this.read(
- this._images[this._imageIndex].byteWidth + 1,
- this._reverseFilterLine.bind(this)
- );
- };
- Filter.prototype._unFilterType1 = function (
- rawData,
- unfilteredLine,
- byteWidth
- ) {
- let xComparison = this._xComparison;
- let xBiggerThan = xComparison - 1;
- for (let x = 0; x < byteWidth; x++) {
- let rawByte = rawData[1 + x];
- let f1Left = x > xBiggerThan ? unfilteredLine[x - xComparison] : 0;
- unfilteredLine[x] = rawByte + f1Left;
- }
- };
- Filter.prototype._unFilterType2 = function (
- rawData,
- unfilteredLine,
- byteWidth
- ) {
- let lastLine = this._lastLine;
- for (let x = 0; x < byteWidth; x++) {
- let rawByte = rawData[1 + x];
- let f2Up = lastLine ? lastLine[x] : 0;
- unfilteredLine[x] = rawByte + f2Up;
- }
- };
- Filter.prototype._unFilterType3 = function (
- rawData,
- unfilteredLine,
- byteWidth
- ) {
- let xComparison = this._xComparison;
- let xBiggerThan = xComparison - 1;
- let lastLine = this._lastLine;
- for (let x = 0; x < byteWidth; x++) {
- let rawByte = rawData[1 + x];
- let f3Up = lastLine ? lastLine[x] : 0;
- let f3Left = x > xBiggerThan ? unfilteredLine[x - xComparison] : 0;
- let f3Add = Math.floor((f3Left + f3Up) / 2);
- unfilteredLine[x] = rawByte + f3Add;
- }
- };
- Filter.prototype._unFilterType4 = function (
- rawData,
- unfilteredLine,
- byteWidth
- ) {
- let xComparison = this._xComparison;
- let xBiggerThan = xComparison - 1;
- let lastLine = this._lastLine;
- for (let x = 0; x < byteWidth; x++) {
- let rawByte = rawData[1 + x];
- let f4Up = lastLine ? lastLine[x] : 0;
- let f4Left = x > xBiggerThan ? unfilteredLine[x - xComparison] : 0;
- let f4UpLeft = x > xBiggerThan && lastLine ? lastLine[x - xComparison] : 0;
- let f4Add = paethPredictor(f4Left, f4Up, f4UpLeft);
- unfilteredLine[x] = rawByte + f4Add;
- }
- };
- Filter.prototype._reverseFilterLine = function (rawData) {
- let filter = rawData[0];
- let unfilteredLine;
- let currentImage = this._images[this._imageIndex];
- let byteWidth = currentImage.byteWidth;
- if (filter === 0) {
- unfilteredLine = rawData.slice(1, byteWidth + 1);
- } else {
- unfilteredLine = Buffer.alloc(byteWidth);
- switch (filter) {
- case 1:
- this._unFilterType1(rawData, unfilteredLine, byteWidth);
- break;
- case 2:
- this._unFilterType2(rawData, unfilteredLine, byteWidth);
- break;
- case 3:
- this._unFilterType3(rawData, unfilteredLine, byteWidth);
- break;
- case 4:
- this._unFilterType4(rawData, unfilteredLine, byteWidth);
- break;
- default:
- throw new Error("Unrecognised filter type - " + filter);
- }
- }
- this.write(unfilteredLine);
- currentImage.lineIndex++;
- if (currentImage.lineIndex >= currentImage.height) {
- this._lastLine = null;
- this._imageIndex++;
- currentImage = this._images[this._imageIndex];
- } else {
- this._lastLine = unfilteredLine;
- }
- if (currentImage) {
- // read, using the byte width that may be from the new current image
- this.read(currentImage.byteWidth + 1, this._reverseFilterLine.bind(this));
- } else {
- this._lastLine = null;
- this.complete();
- }
- };
- });
- var filterParseAsync = createCommonjsModule(function (module) {
- let FilterAsync = (module.exports = function (bitmapInfo) {
- chunkstream.call(this);
- let buffers = [];
- let that = this;
- this._filter = new filterParse(bitmapInfo, {
- read: this.read.bind(this),
- write: function (buffer) {
- buffers.push(buffer);
- },
- complete: function () {
- that.emit("complete", Buffer.concat(buffers));
- },
- });
- this._filter.start();
- });
- util__default['default'].inherits(FilterAsync, chunkstream);
- });
- var constants = {
- PNG_SIGNATURE: [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a],
- TYPE_IHDR: 0x49484452,
- TYPE_IEND: 0x49454e44,
- TYPE_IDAT: 0x49444154,
- TYPE_PLTE: 0x504c5445,
- TYPE_tRNS: 0x74524e53, // eslint-disable-line camelcase
- TYPE_gAMA: 0x67414d41, // eslint-disable-line camelcase
- // color-type bits
- COLORTYPE_GRAYSCALE: 0,
- COLORTYPE_PALETTE: 1,
- COLORTYPE_COLOR: 2,
- COLORTYPE_ALPHA: 4, // e.g. grayscale and alpha
- // color-type combinations
- COLORTYPE_PALETTE_COLOR: 3,
- COLORTYPE_COLOR_ALPHA: 6,
- COLORTYPE_TO_BPP_MAP: {
- 0: 1,
- 2: 3,
- 3: 1,
- 4: 2,
- 6: 4,
- },
- GAMMA_DIVISION: 100000,
- };
- var crc = createCommonjsModule(function (module) {
- let crcTable = [];
- (function () {
- for (let i = 0; i < 256; i++) {
- let currentCrc = i;
- for (let j = 0; j < 8; j++) {
- if (currentCrc & 1) {
- currentCrc = 0xedb88320 ^ (currentCrc >>> 1);
- } else {
- currentCrc = currentCrc >>> 1;
- }
- }
- crcTable[i] = currentCrc;
- }
- })();
- let CrcCalculator = (module.exports = function () {
- this._crc = -1;
- });
- CrcCalculator.prototype.write = function (data) {
- for (let i = 0; i < data.length; i++) {
- this._crc = crcTable[(this._crc ^ data[i]) & 0xff] ^ (this._crc >>> 8);
- }
- return true;
- };
- CrcCalculator.prototype.crc32 = function () {
- return this._crc ^ -1;
- };
- CrcCalculator.crc32 = function (buf) {
- let crc = -1;
- for (let i = 0; i < buf.length; i++) {
- crc = crcTable[(crc ^ buf[i]) & 0xff] ^ (crc >>> 8);
- }
- return crc ^ -1;
- };
- });
- var parser = createCommonjsModule(function (module) {
- let Parser = (module.exports = function (options, dependencies) {
- this._options = options;
- options.checkCRC = options.checkCRC !== false;
- this._hasIHDR = false;
- this._hasIEND = false;
- this._emittedHeadersFinished = false;
- // input flags/metadata
- this._palette = [];
- this._colorType = 0;
- this._chunks = {};
- this._chunks[constants.TYPE_IHDR] = this._handleIHDR.bind(this);
- this._chunks[constants.TYPE_IEND] = this._handleIEND.bind(this);
- this._chunks[constants.TYPE_IDAT] = this._handleIDAT.bind(this);
- this._chunks[constants.TYPE_PLTE] = this._handlePLTE.bind(this);
- this._chunks[constants.TYPE_tRNS] = this._handleTRNS.bind(this);
- this._chunks[constants.TYPE_gAMA] = this._handleGAMA.bind(this);
- this.read = dependencies.read;
- this.error = dependencies.error;
- this.metadata = dependencies.metadata;
- this.gamma = dependencies.gamma;
- this.transColor = dependencies.transColor;
- this.palette = dependencies.palette;
- this.parsed = dependencies.parsed;
- this.inflateData = dependencies.inflateData;
- this.finished = dependencies.finished;
- this.simpleTransparency = dependencies.simpleTransparency;
- this.headersFinished = dependencies.headersFinished || function () {};
- });
- Parser.prototype.start = function () {
- this.read(constants.PNG_SIGNATURE.length, this._parseSignature.bind(this));
- };
- Parser.prototype._parseSignature = function (data) {
- let signature = constants.PNG_SIGNATURE;
- for (let i = 0; i < signature.length; i++) {
- if (data[i] !== signature[i]) {
- this.error(new Error("Invalid file signature"));
- return;
- }
- }
- this.read(8, this._parseChunkBegin.bind(this));
- };
- Parser.prototype._parseChunkBegin = function (data) {
- // chunk content length
- let length = data.readUInt32BE(0);
- // chunk type
- let type = data.readUInt32BE(4);
- let name = "";
- for (let i = 4; i < 8; i++) {
- name += String.fromCharCode(data[i]);
- }
- //console.log('chunk ', name, length);
- // chunk flags
- let ancillary = Boolean(data[4] & 0x20); // or critical
- // priv = Boolean(data[5] & 0x20), // or public
- // safeToCopy = Boolean(data[7] & 0x20); // or unsafe
- if (!this._hasIHDR && type !== constants.TYPE_IHDR) {
- this.error(new Error("Expected IHDR on beggining"));
- return;
- }
- this._crc = new crc();
- this._crc.write(Buffer.from(name));
- if (this._chunks[type]) {
- return this._chunks[type](length);
- }
- if (!ancillary) {
- this.error(new Error("Unsupported critical chunk type " + name));
- return;
- }
- this.read(length + 4, this._skipChunk.bind(this));
- };
- Parser.prototype._skipChunk = function (/*data*/) {
- this.read(8, this._parseChunkBegin.bind(this));
- };
- Parser.prototype._handleChunkEnd = function () {
- this.read(4, this._parseChunkEnd.bind(this));
- };
- Parser.prototype._parseChunkEnd = function (data) {
- let fileCrc = data.readInt32BE(0);
- let calcCrc = this._crc.crc32();
- // check CRC
- if (this._options.checkCRC && calcCrc !== fileCrc) {
- this.error(new Error("Crc error - " + fileCrc + " - " + calcCrc));
- return;
- }
- if (!this._hasIEND) {
- this.read(8, this._parseChunkBegin.bind(this));
- }
- };
- Parser.prototype._handleIHDR = function (length) {
- this.read(length, this._parseIHDR.bind(this));
- };
- Parser.prototype._parseIHDR = function (data) {
- this._crc.write(data);
- let width = data.readUInt32BE(0);
- let height = data.readUInt32BE(4);
- let depth = data[8];
- let colorType = data[9]; // bits: 1 palette, 2 color, 4 alpha
- let compr = data[10];
- let filter = data[11];
- let interlace = data[12];
- // console.log(' width', width, 'height', height,
- // 'depth', depth, 'colorType', colorType,
- // 'compr', compr, 'filter', filter, 'interlace', interlace
- // );
- if (
- depth !== 8 &&
- depth !== 4 &&
- depth !== 2 &&
- depth !== 1 &&
- depth !== 16
- ) {
- this.error(new Error("Unsupported bit depth " + depth));
- return;
- }
- if (!(colorType in constants.COLORTYPE_TO_BPP_MAP)) {
- this.error(new Error("Unsupported color type"));
- return;
- }
- if (compr !== 0) {
- this.error(new Error("Unsupported compression method"));
- return;
- }
- if (filter !== 0) {
- this.error(new Error("Unsupported filter method"));
- return;
- }
- if (interlace !== 0 && interlace !== 1) {
- this.error(new Error("Unsupported interlace method"));
- return;
- }
- this._colorType = colorType;
- let bpp = constants.COLORTYPE_TO_BPP_MAP[this._colorType];
- this._hasIHDR = true;
- this.metadata({
- width: width,
- height: height,
- depth: depth,
- interlace: Boolean(interlace),
- palette: Boolean(colorType & constants.COLORTYPE_PALETTE),
- color: Boolean(colorType & constants.COLORTYPE_COLOR),
- alpha: Boolean(colorType & constants.COLORTYPE_ALPHA),
- bpp: bpp,
- colorType: colorType,
- });
- this._handleChunkEnd();
- };
- Parser.prototype._handlePLTE = function (length) {
- this.read(length, this._parsePLTE.bind(this));
- };
- Parser.prototype._parsePLTE = function (data) {
- this._crc.write(data);
- let entries = Math.floor(data.length / 3);
- // console.log('Palette:', entries);
- for (let i = 0; i < entries; i++) {
- this._palette.push([data[i * 3], data[i * 3 + 1], data[i * 3 + 2], 0xff]);
- }
- this.palette(this._palette);
- this._handleChunkEnd();
- };
- Parser.prototype._handleTRNS = function (length) {
- this.simpleTransparency();
- this.read(length, this._parseTRNS.bind(this));
- };
- Parser.prototype._parseTRNS = function (data) {
- this._crc.write(data);
- // palette
- if (this._colorType === constants.COLORTYPE_PALETTE_COLOR) {
- if (this._palette.length === 0) {
- this.error(new Error("Transparency chunk must be after palette"));
- return;
- }
- if (data.length > this._palette.length) {
- this.error(new Error("More transparent colors than palette size"));
- return;
- }
- for (let i = 0; i < data.length; i++) {
- this._palette[i][3] = data[i];
- }
- this.palette(this._palette);
- }
- // for colorType 0 (grayscale) and 2 (rgb)
- // there might be one gray/color defined as transparent
- if (this._colorType === constants.COLORTYPE_GRAYSCALE) {
- // grey, 2 bytes
- this.transColor([data.readUInt16BE(0)]);
- }
- if (this._colorType === constants.COLORTYPE_COLOR) {
- this.transColor([
- data.readUInt16BE(0),
- data.readUInt16BE(2),
- data.readUInt16BE(4),
- ]);
- }
- this._handleChunkEnd();
- };
- Parser.prototype._handleGAMA = function (length) {
- this.read(length, this._parseGAMA.bind(this));
- };
- Parser.prototype._parseGAMA = function (data) {
- this._crc.write(data);
- this.gamma(data.readUInt32BE(0) / constants.GAMMA_DIVISION);
- this._handleChunkEnd();
- };
- Parser.prototype._handleIDAT = function (length) {
- if (!this._emittedHeadersFinished) {
- this._emittedHeadersFinished = true;
- this.headersFinished();
- }
- this.read(-length, this._parseIDAT.bind(this, length));
- };
- Parser.prototype._parseIDAT = function (length, data) {
- this._crc.write(data);
- if (
- this._colorType === constants.COLORTYPE_PALETTE_COLOR &&
- this._palette.length === 0
- ) {
- throw new Error("Expected palette not found");
- }
- this.inflateData(data);
- let leftOverLength = length - data.length;
- if (leftOverLength > 0) {
- this._handleIDAT(leftOverLength);
- } else {
- this._handleChunkEnd();
- }
- };
- Parser.prototype._handleIEND = function (length) {
- this.read(length, this._parseIEND.bind(this));
- };
- Parser.prototype._parseIEND = function (data) {
- this._crc.write(data);
- this._hasIEND = true;
- this._handleChunkEnd();
- if (this.finished) {
- this.finished();
- }
- };
- });
- let pixelBppMapper = [
- // 0 - dummy entry
- function () {},
- // 1 - L
- // 0: 0, 1: 0, 2: 0, 3: 0xff
- function (pxData, data, pxPos, rawPos) {
- if (rawPos === data.length) {
- throw new Error("Ran out of data");
- }
- let pixel = data[rawPos];
- pxData[pxPos] = pixel;
- pxData[pxPos + 1] = pixel;
- pxData[pxPos + 2] = pixel;
- pxData[pxPos + 3] = 0xff;
- },
- // 2 - LA
- // 0: 0, 1: 0, 2: 0, 3: 1
- function (pxData, data, pxPos, rawPos) {
- if (rawPos + 1 >= data.length) {
- throw new Error("Ran out of data");
- }
- let pixel = data[rawPos];
- pxData[pxPos] = pixel;
- pxData[pxPos + 1] = pixel;
- pxData[pxPos + 2] = pixel;
- pxData[pxPos + 3] = data[rawPos + 1];
- },
- // 3 - RGB
- // 0: 0, 1: 1, 2: 2, 3: 0xff
- function (pxData, data, pxPos, rawPos) {
- if (rawPos + 2 >= data.length) {
- throw new Error("Ran out of data");
- }
- pxData[pxPos] = data[rawPos];
- pxData[pxPos + 1] = data[rawPos + 1];
- pxData[pxPos + 2] = data[rawPos + 2];
- pxData[pxPos + 3] = 0xff;
- },
- // 4 - RGBA
- // 0: 0, 1: 1, 2: 2, 3: 3
- function (pxData, data, pxPos, rawPos) {
- if (rawPos + 3 >= data.length) {
- throw new Error("Ran out of data");
- }
- pxData[pxPos] = data[rawPos];
- pxData[pxPos + 1] = data[rawPos + 1];
- pxData[pxPos + 2] = data[rawPos + 2];
- pxData[pxPos + 3] = data[rawPos + 3];
- },
- ];
- let pixelBppCustomMapper = [
- // 0 - dummy entry
- function () {},
- // 1 - L
- // 0: 0, 1: 0, 2: 0, 3: 0xff
- function (pxData, pixelData, pxPos, maxBit) {
- let pixel = pixelData[0];
- pxData[pxPos] = pixel;
- pxData[pxPos + 1] = pixel;
- pxData[pxPos + 2] = pixel;
- pxData[pxPos + 3] = maxBit;
- },
- // 2 - LA
- // 0: 0, 1: 0, 2: 0, 3: 1
- function (pxData, pixelData, pxPos) {
- let pixel = pixelData[0];
- pxData[pxPos] = pixel;
- pxData[pxPos + 1] = pixel;
- pxData[pxPos + 2] = pixel;
- pxData[pxPos + 3] = pixelData[1];
- },
- // 3 - RGB
- // 0: 0, 1: 1, 2: 2, 3: 0xff
- function (pxData, pixelData, pxPos, maxBit) {
- pxData[pxPos] = pixelData[0];
- pxData[pxPos + 1] = pixelData[1];
- pxData[pxPos + 2] = pixelData[2];
- pxData[pxPos + 3] = maxBit;
- },
- // 4 - RGBA
- // 0: 0, 1: 1, 2: 2, 3: 3
- function (pxData, pixelData, pxPos) {
- pxData[pxPos] = pixelData[0];
- pxData[pxPos + 1] = pixelData[1];
- pxData[pxPos + 2] = pixelData[2];
- pxData[pxPos + 3] = pixelData[3];
- },
- ];
- function bitRetriever(data, depth) {
- let leftOver = [];
- let i = 0;
- function split() {
- if (i === data.length) {
- throw new Error("Ran out of data");
- }
- let byte = data[i];
- i++;
- let byte8, byte7, byte6, byte5, byte4, byte3, byte2, byte1;
- switch (depth) {
- default:
- throw new Error("unrecognised depth");
- case 16:
- byte2 = data[i];
- i++;
- leftOver.push((byte << 8) + byte2);
- break;
- case 4:
- byte2 = byte & 0x0f;
- byte1 = byte >> 4;
- leftOver.push(byte1, byte2);
- break;
- case 2:
- byte4 = byte & 3;
- byte3 = (byte >> 2) & 3;
- byte2 = (byte >> 4) & 3;
- byte1 = (byte >> 6) & 3;
- leftOver.push(byte1, byte2, byte3, byte4);
- break;
- case 1:
- byte8 = byte & 1;
- byte7 = (byte >> 1) & 1;
- byte6 = (byte >> 2) & 1;
- byte5 = (byte >> 3) & 1;
- byte4 = (byte >> 4) & 1;
- byte3 = (byte >> 5) & 1;
- byte2 = (byte >> 6) & 1;
- byte1 = (byte >> 7) & 1;
- leftOver.push(byte1, byte2, byte3, byte4, byte5, byte6, byte7, byte8);
- break;
- }
- }
- return {
- get: function (count) {
- while (leftOver.length < count) {
- split();
- }
- let returner = leftOver.slice(0, count);
- leftOver = leftOver.slice(count);
- return returner;
- },
- resetAfterLine: function () {
- leftOver.length = 0;
- },
- end: function () {
- if (i !== data.length) {
- throw new Error("extra data found");
- }
- },
- };
- }
- function mapImage8Bit(image, pxData, getPxPos, bpp, data, rawPos) {
- // eslint-disable-line max-params
- let imageWidth = image.width;
- let imageHeight = image.height;
- let imagePass = image.index;
- for (let y = 0; y < imageHeight; y++) {
- for (let x = 0; x < imageWidth; x++) {
- let pxPos = getPxPos(x, y, imagePass);
- pixelBppMapper[bpp](pxData, data, pxPos, rawPos);
- rawPos += bpp; //eslint-disable-line no-param-reassign
- }
- }
- return rawPos;
- }
- function mapImageCustomBit(image, pxData, getPxPos, bpp, bits, maxBit) {
- // eslint-disable-line max-params
- let imageWidth = image.width;
- let imageHeight = image.height;
- let imagePass = image.index;
- for (let y = 0; y < imageHeight; y++) {
- for (let x = 0; x < imageWidth; x++) {
- let pixelData = bits.get(bpp);
- let pxPos = getPxPos(x, y, imagePass);
- pixelBppCustomMapper[bpp](pxData, pixelData, pxPos, maxBit);
- }
- bits.resetAfterLine();
- }
- }
- var dataToBitMap = function (data, bitmapInfo) {
- let width = bitmapInfo.width;
- let height = bitmapInfo.height;
- let depth = bitmapInfo.depth;
- let bpp = bitmapInfo.bpp;
- let interlace$1 = bitmapInfo.interlace;
- let bits;
- if (depth !== 8) {
- bits = bitRetriever(data, depth);
- }
- let pxData;
- if (depth <= 8) {
- pxData = Buffer.alloc(width * height * 4);
- } else {
- pxData = new Uint16Array(width * height * 4);
- }
- let maxBit = Math.pow(2, depth) - 1;
- let rawPos = 0;
- let images;
- let getPxPos;
- if (interlace$1) {
- images = interlace.getImagePasses(width, height);
- getPxPos = interlace.getInterlaceIterator(width, height);
- } else {
- let nonInterlacedPxPos = 0;
- getPxPos = function () {
- let returner = nonInterlacedPxPos;
- nonInterlacedPxPos += 4;
- return returner;
- };
- images = [{ width: width, height: height }];
- }
- for (let imageIndex = 0; imageIndex < images.length; imageIndex++) {
- if (depth === 8) {
- rawPos = mapImage8Bit(
- images[imageIndex],
- pxData,
- getPxPos,
- bpp,
- data,
- rawPos
- );
- } else {
- mapImageCustomBit(
- images[imageIndex],
- pxData,
- getPxPos,
- bpp,
- bits,
- maxBit
- );
- }
- }
- if (depth === 8) {
- if (rawPos !== data.length) {
- throw new Error("extra data found");
- }
- } else {
- bits.end();
- }
- return pxData;
- };
- var bitmapper = {
- dataToBitMap: dataToBitMap
- };
- function dePalette(indata, outdata, width, height, palette) {
- let pxPos = 0;
- // use values from palette
- for (let y = 0; y < height; y++) {
- for (let x = 0; x < width; x++) {
- let color = palette[indata[pxPos]];
- if (!color) {
- throw new Error("index " + indata[pxPos] + " not in palette");
- }
- for (let i = 0; i < 4; i++) {
- outdata[pxPos + i] = color[i];
- }
- pxPos += 4;
- }
- }
- }
- function replaceTransparentColor(indata, outdata, width, height, transColor) {
- let pxPos = 0;
- for (let y = 0; y < height; y++) {
- for (let x = 0; x < width; x++) {
- let makeTrans = false;
- if (transColor.length === 1) {
- if (transColor[0] === indata[pxPos]) {
- makeTrans = true;
- }
- } else if (
- transColor[0] === indata[pxPos] &&
- transColor[1] === indata[pxPos + 1] &&
- transColor[2] === indata[pxPos + 2]
- ) {
- makeTrans = true;
- }
- if (makeTrans) {
- for (let i = 0; i < 4; i++) {
- outdata[pxPos + i] = 0;
- }
- }
- pxPos += 4;
- }
- }
- }
- function scaleDepth(indata, outdata, width, height, depth) {
- let maxOutSample = 255;
- let maxInSample = Math.pow(2, depth) - 1;
- let pxPos = 0;
- for (let y = 0; y < height; y++) {
- for (let x = 0; x < width; x++) {
- for (let i = 0; i < 4; i++) {
- outdata[pxPos + i] = Math.floor(
- (indata[pxPos + i] * maxOutSample) / maxInSample + 0.5
- );
- }
- pxPos += 4;
- }
- }
- }
- var formatNormaliser = function (indata, imageData, skipRescale = false) {
- let depth = imageData.depth;
- let width = imageData.width;
- let height = imageData.height;
- let colorType = imageData.colorType;
- let transColor = imageData.transColor;
- let palette = imageData.palette;
- let outdata = indata; // only different for 16 bits
- if (colorType === 3) {
- // paletted
- dePalette(indata, outdata, width, height, palette);
- } else {
- if (transColor) {
- replaceTransparentColor(indata, outdata, width, height, transColor);
- }
- // if it needs scaling
- if (depth !== 8 && !skipRescale) {
- // if we need to change the buffer size
- if (depth === 16) {
- outdata = Buffer.alloc(width * height * 4);
- }
- scaleDepth(indata, outdata, width, height, depth);
- }
- }
- return outdata;
- };
- var parserAsync = createCommonjsModule(function (module) {
- let ParserAsync = (module.exports = function (options) {
- chunkstream.call(this);
- this._parser = new parser(options, {
- read: this.read.bind(this),
- error: this._handleError.bind(this),
- metadata: this._handleMetaData.bind(this),
- gamma: this.emit.bind(this, "gamma"),
- palette: this._handlePalette.bind(this),
- transColor: this._handleTransColor.bind(this),
- finished: this._finished.bind(this),
- inflateData: this._inflateData.bind(this),
- simpleTransparency: this._simpleTransparency.bind(this),
- headersFinished: this._headersFinished.bind(this),
- });
- this._options = options;
- this.writable = true;
- this._parser.start();
- });
- util__default['default'].inherits(ParserAsync, chunkstream);
- ParserAsync.prototype._handleError = function (err) {
- this.emit("error", err);
- this.writable = false;
- this.destroy();
- if (this._inflate && this._inflate.destroy) {
- this._inflate.destroy();
- }
- if (this._filter) {
- this._filter.destroy();
- // For backward compatibility with Node 7 and below.
- // Suppress errors due to _inflate calling write() even after
- // it's destroy()'ed.
- this._filter.on("error", function () {});
- }
- this.errord = true;
- };
- ParserAsync.prototype._inflateData = function (data) {
- if (!this._inflate) {
- if (this._bitmapInfo.interlace) {
- this._inflate = zlib__default['default'].createInflate();
- this._inflate.on("error", this.emit.bind(this, "error"));
- this._filter.on("complete", this._complete.bind(this));
- this._inflate.pipe(this._filter);
- } else {
- let rowSize =
- ((this._bitmapInfo.width *
- this._bitmapInfo.bpp *
- this._bitmapInfo.depth +
- 7) >>
- 3) +
- 1;
- let imageSize = rowSize * this._bitmapInfo.height;
- let chunkSize = Math.max(imageSize, zlib__default['default'].Z_MIN_CHUNK);
- this._inflate = zlib__default['default'].createInflate({ chunkSize: chunkSize });
- let leftToInflate = imageSize;
- let emitError = this.emit.bind(this, "error");
- this._inflate.on("error", function (err) {
- if (!leftToInflate) {
- return;
- }
- emitError(err);
- });
- this._filter.on("complete", this._complete.bind(this));
- let filterWrite = this._filter.write.bind(this._filter);
- this._inflate.on("data", function (chunk) {
- if (!leftToInflate) {
- return;
- }
- if (chunk.length > leftToInflate) {
- chunk = chunk.slice(0, leftToInflate);
- }
- leftToInflate -= chunk.length;
- filterWrite(chunk);
- });
- this._inflate.on("end", this._filter.end.bind(this._filter));
- }
- }
- this._inflate.write(data);
- };
- ParserAsync.prototype._handleMetaData = function (metaData) {
- this._metaData = metaData;
- this._bitmapInfo = Object.create(metaData);
- this._filter = new filterParseAsync(this._bitmapInfo);
- };
- ParserAsync.prototype._handleTransColor = function (transColor) {
- this._bitmapInfo.transColor = transColor;
- };
- ParserAsync.prototype._handlePalette = function (palette) {
- this._bitmapInfo.palette = palette;
- };
- ParserAsync.prototype._simpleTransparency = function () {
- this._metaData.alpha = true;
- };
- ParserAsync.prototype._headersFinished = function () {
- // Up until this point, we don't know if we have a tRNS chunk (alpha)
- // so we can't emit metadata any earlier
- this.emit("metadata", this._metaData);
- };
- ParserAsync.prototype._finished = function () {
- if (this.errord) {
- return;
- }
- if (!this._inflate) {
- this.emit("error", "No Inflate block");
- } else {
- // no more data to inflate
- this._inflate.end();
- }
- };
- ParserAsync.prototype._complete = function (filteredData) {
- if (this.errord) {
- return;
- }
- let normalisedBitmapData;
- try {
- let bitmapData = bitmapper.dataToBitMap(filteredData, this._bitmapInfo);
- normalisedBitmapData = formatNormaliser(
- bitmapData,
- this._bitmapInfo,
- this._options.skipRescale
- );
- bitmapData = null;
- } catch (ex) {
- this._handleError(ex);
- return;
- }
- this.emit("parsed", normalisedBitmapData);
- };
- });
- var bitpacker = function (dataIn, width, height, options) {
- let outHasAlpha =
- [constants.COLORTYPE_COLOR_ALPHA, constants.COLORTYPE_ALPHA].indexOf(
- options.colorType
- ) !== -1;
- if (options.colorType === options.inputColorType) {
- let bigEndian = (function () {
- let buffer = new ArrayBuffer(2);
- new DataView(buffer).setInt16(0, 256, true /* littleEndian */);
- // Int16Array uses the platform's endianness.
- return new Int16Array(buffer)[0] !== 256;
- })();
- // If no need to convert to grayscale and alpha is present/absent in both, take a fast route
- if (options.bitDepth === 8 || (options.bitDepth === 16 && bigEndian)) {
- return dataIn;
- }
- }
- // map to a UInt16 array if data is 16bit, fix endianness below
- let data = options.bitDepth !== 16 ? dataIn : new Uint16Array(dataIn.buffer);
- let maxValue = 255;
- let inBpp = constants.COLORTYPE_TO_BPP_MAP[options.inputColorType];
- if (inBpp === 4 && !options.inputHasAlpha) {
- inBpp = 3;
- }
- let outBpp = constants.COLORTYPE_TO_BPP_MAP[options.colorType];
- if (options.bitDepth === 16) {
- maxValue = 65535;
- outBpp *= 2;
- }
- let outData = Buffer.alloc(width * height * outBpp);
- let inIndex = 0;
- let outIndex = 0;
- let bgColor = options.bgColor || {};
- if (bgColor.red === undefined) {
- bgColor.red = maxValue;
- }
- if (bgColor.green === undefined) {
- bgColor.green = maxValue;
- }
- if (bgColor.blue === undefined) {
- bgColor.blue = maxValue;
- }
- function getRGBA() {
- let red;
- let green;
- let blue;
- let alpha = maxValue;
- switch (options.inputColorType) {
- case constants.COLORTYPE_COLOR_ALPHA:
- alpha = data[inIndex + 3];
- red = data[inIndex];
- green = data[inIndex + 1];
- blue = data[inIndex + 2];
- break;
- case constants.COLORTYPE_COLOR:
- red = data[inIndex];
- green = data[inIndex + 1];
- blue = data[inIndex + 2];
- break;
- case constants.COLORTYPE_ALPHA:
- alpha = data[inIndex + 1];
- red = data[inIndex];
- green = red;
- blue = red;
- break;
- case constants.COLORTYPE_GRAYSCALE:
- red = data[inIndex];
- green = red;
- blue = red;
- break;
- default:
- throw new Error(
- "input color type:" +
- options.inputColorType +
- " is not supported at present"
- );
- }
- if (options.inputHasAlpha) {
- if (!outHasAlpha) {
- alpha /= maxValue;
- red = Math.min(
- Math.max(Math.round((1 - alpha) * bgColor.red + alpha * red), 0),
- maxValue
- );
- green = Math.min(
- Math.max(Math.round((1 - alpha) * bgColor.green + alpha * green), 0),
- maxValue
- );
- blue = Math.min(
- Math.max(Math.round((1 - alpha) * bgColor.blue + alpha * blue), 0),
- maxValue
- );
- }
- }
- return { red: red, green: green, blue: blue, alpha: alpha };
- }
- for (let y = 0; y < height; y++) {
- for (let x = 0; x < width; x++) {
- let rgba = getRGBA();
- switch (options.colorType) {
- case constants.COLORTYPE_COLOR_ALPHA:
- case constants.COLORTYPE_COLOR:
- if (options.bitDepth === 8) {
- outData[outIndex] = rgba.red;
- outData[outIndex + 1] = rgba.green;
- outData[outIndex + 2] = rgba.blue;
- if (outHasAlpha) {
- outData[outIndex + 3] = rgba.alpha;
- }
- } else {
- outData.writeUInt16BE(rgba.red, outIndex);
- outData.writeUInt16BE(rgba.green, outIndex + 2);
- outData.writeUInt16BE(rgba.blue, outIndex + 4);
- if (outHasAlpha) {
- outData.writeUInt16BE(rgba.alpha, outIndex + 6);
- }
- }
- break;
- case constants.COLORTYPE_ALPHA:
- case constants.COLORTYPE_GRAYSCALE: {
- // Convert to grayscale and alpha
- let grayscale = (rgba.red + rgba.green + rgba.blue) / 3;
- if (options.bitDepth === 8) {
- outData[outIndex] = grayscale;
- if (outHasAlpha) {
- outData[outIndex + 1] = rgba.alpha;
- }
- } else {
- outData.writeUInt16BE(grayscale, outIndex);
- if (outHasAlpha) {
- outData.writeUInt16BE(rgba.alpha, outIndex + 2);
- }
- }
- break;
- }
- default:
- throw new Error("unrecognised color Type " + options.colorType);
- }
- inIndex += inBpp;
- outIndex += outBpp;
- }
- }
- return outData;
- };
- function filterNone(pxData, pxPos, byteWidth, rawData, rawPos) {
- for (let x = 0; x < byteWidth; x++) {
- rawData[rawPos + x] = pxData[pxPos + x];
- }
- }
- function filterSumNone(pxData, pxPos, byteWidth) {
- let sum = 0;
- let length = pxPos + byteWidth;
- for (let i = pxPos; i < length; i++) {
- sum += Math.abs(pxData[i]);
- }
- return sum;
- }
- function filterSub(pxData, pxPos, byteWidth, rawData, rawPos, bpp) {
- for (let x = 0; x < byteWidth; x++) {
- let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
- let val = pxData[pxPos + x] - left;
- rawData[rawPos + x] = val;
- }
- }
- function filterSumSub(pxData, pxPos, byteWidth, bpp) {
- let sum = 0;
- for (let x = 0; x < byteWidth; x++) {
- let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
- let val = pxData[pxPos + x] - left;
- sum += Math.abs(val);
- }
- return sum;
- }
- function filterUp(pxData, pxPos, byteWidth, rawData, rawPos) {
- for (let x = 0; x < byteWidth; x++) {
- let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
- let val = pxData[pxPos + x] - up;
- rawData[rawPos + x] = val;
- }
- }
- function filterSumUp(pxData, pxPos, byteWidth) {
- let sum = 0;
- let length = pxPos + byteWidth;
- for (let x = pxPos; x < length; x++) {
- let up = pxPos > 0 ? pxData[x - byteWidth] : 0;
- let val = pxData[x] - up;
- sum += Math.abs(val);
- }
- return sum;
- }
- function filterAvg(pxData, pxPos, byteWidth, rawData, rawPos, bpp) {
- for (let x = 0; x < byteWidth; x++) {
- let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
- let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
- let val = pxData[pxPos + x] - ((left + up) >> 1);
- rawData[rawPos + x] = val;
- }
- }
- function filterSumAvg(pxData, pxPos, byteWidth, bpp) {
- let sum = 0;
- for (let x = 0; x < byteWidth; x++) {
- let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
- let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
- let val = pxData[pxPos + x] - ((left + up) >> 1);
- sum += Math.abs(val);
- }
- return sum;
- }
- function filterPaeth(pxData, pxPos, byteWidth, rawData, rawPos, bpp) {
- for (let x = 0; x < byteWidth; x++) {
- let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
- let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
- let upleft =
- pxPos > 0 && x >= bpp ? pxData[pxPos + x - (byteWidth + bpp)] : 0;
- let val = pxData[pxPos + x] - paethPredictor(left, up, upleft);
- rawData[rawPos + x] = val;
- }
- }
- function filterSumPaeth(pxData, pxPos, byteWidth, bpp) {
- let sum = 0;
- for (let x = 0; x < byteWidth; x++) {
- let left = x >= bpp ? pxData[pxPos + x - bpp] : 0;
- let up = pxPos > 0 ? pxData[pxPos + x - byteWidth] : 0;
- let upleft =
- pxPos > 0 && x >= bpp ? pxData[pxPos + x - (byteWidth + bpp)] : 0;
- let val = pxData[pxPos + x] - paethPredictor(left, up, upleft);
- sum += Math.abs(val);
- }
- return sum;
- }
- let filters = {
- 0: filterNone,
- 1: filterSub,
- 2: filterUp,
- 3: filterAvg,
- 4: filterPaeth,
- };
- let filterSums = {
- 0: filterSumNone,
- 1: filterSumSub,
- 2: filterSumUp,
- 3: filterSumAvg,
- 4: filterSumPaeth,
- };
- var filterPack = function (pxData, width, height, options, bpp) {
- let filterTypes;
- if (!("filterType" in options) || options.filterType === -1) {
- filterTypes = [0, 1, 2, 3, 4];
- } else if (typeof options.filterType === "number") {
- filterTypes = [options.filterType];
- } else {
- throw new Error("unrecognised filter types");
- }
- if (options.bitDepth === 16) {
- bpp *= 2;
- }
- let byteWidth = width * bpp;
- let rawPos = 0;
- let pxPos = 0;
- let rawData = Buffer.alloc((byteWidth + 1) * height);
- let sel = filterTypes[0];
- for (let y = 0; y < height; y++) {
- if (filterTypes.length > 1) {
- // find best filter for this line (with lowest sum of values)
- let min = Infinity;
- for (let i = 0; i < filterTypes.length; i++) {
- let sum = filterSums[filterTypes[i]](pxData, pxPos, byteWidth, bpp);
- if (sum < min) {
- sel = filterTypes[i];
- min = sum;
- }
- }
- }
- rawData[rawPos] = sel;
- rawPos++;
- filters[sel](pxData, pxPos, byteWidth, rawData, rawPos, bpp);
- rawPos += byteWidth;
- pxPos += byteWidth;
- }
- return rawData;
- };
- var packer = createCommonjsModule(function (module) {
- let Packer = (module.exports = function (options) {
- this._options = options;
- options.deflateChunkSize = options.deflateChunkSize || 32 * 1024;
- options.deflateLevel =
- options.deflateLevel != null ? options.deflateLevel : 9;
- options.deflateStrategy =
- options.deflateStrategy != null ? options.deflateStrategy : 3;
- options.inputHasAlpha =
- options.inputHasAlpha != null ? options.inputHasAlpha : true;
- options.deflateFactory = options.deflateFactory || zlib__default['default'].createDeflate;
- options.bitDepth = options.bitDepth || 8;
- // This is outputColorType
- options.colorType =
- typeof options.colorType === "number"
- ? options.colorType
- : constants.COLORTYPE_COLOR_ALPHA;
- options.inputColorType =
- typeof options.inputColorType === "number"
- ? options.inputColorType
- : constants.COLORTYPE_COLOR_ALPHA;
- if (
- [
- constants.COLORTYPE_GRAYSCALE,
- constants.COLORTYPE_COLOR,
- constants.COLORTYPE_COLOR_ALPHA,
- constants.COLORTYPE_ALPHA,
- ].indexOf(options.colorType) === -1
- ) {
- throw new Error(
- "option color type:" + options.colorType + " is not supported at present"
- );
- }
- if (
- [
- constants.COLORTYPE_GRAYSCALE,
- constants.COLORTYPE_COLOR,
- constants.COLORTYPE_COLOR_ALPHA,
- constants.COLORTYPE_ALPHA,
- ].indexOf(options.inputColorType) === -1
- ) {
- throw new Error(
- "option input color type:" +
- options.inputColorType +
- " is not supported at present"
- );
- }
- if (options.bitDepth !== 8 && options.bitDepth !== 16) {
- throw new Error(
- "option bit depth:" + options.bitDepth + " is not supported at present"
- );
- }
- });
- Packer.prototype.getDeflateOptions = function () {
- return {
- chunkSize: this._options.deflateChunkSize,
- level: this._options.deflateLevel,
- strategy: this._options.deflateStrategy,
- };
- };
- Packer.prototype.createDeflate = function () {
- return this._options.deflateFactory(this.getDeflateOptions());
- };
- Packer.prototype.filterData = function (data, width, height) {
- // convert to correct format for filtering (e.g. right bpp and bit depth)
- let packedData = bitpacker(data, width, height, this._options);
- // filter pixel data
- let bpp = constants.COLORTYPE_TO_BPP_MAP[this._options.colorType];
- let filteredData = filterPack(packedData, width, height, this._options, bpp);
- return filteredData;
- };
- Packer.prototype._packChunk = function (type, data) {
- let len = data ? data.length : 0;
- let buf = Buffer.alloc(len + 12);
- buf.writeUInt32BE(len, 0);
- buf.writeUInt32BE(type, 4);
- if (data) {
- data.copy(buf, 8);
- }
- buf.writeInt32BE(
- crc.crc32(buf.slice(4, buf.length - 4)),
- buf.length - 4
- );
- return buf;
- };
- Packer.prototype.packGAMA = function (gamma) {
- let buf = Buffer.alloc(4);
- buf.writeUInt32BE(Math.floor(gamma * constants.GAMMA_DIVISION), 0);
- return this._packChunk(constants.TYPE_gAMA, buf);
- };
- Packer.prototype.packIHDR = function (width, height) {
- let buf = Buffer.alloc(13);
- buf.writeUInt32BE(width, 0);
- buf.writeUInt32BE(height, 4);
- buf[8] = this._options.bitDepth; // Bit depth
- buf[9] = this._options.colorType; // colorType
- buf[10] = 0; // compression
- buf[11] = 0; // filter
- buf[12] = 0; // interlace
- return this._packChunk(constants.TYPE_IHDR, buf);
- };
- Packer.prototype.packIDAT = function (data) {
- return this._packChunk(constants.TYPE_IDAT, data);
- };
- Packer.prototype.packIEND = function () {
- return this._packChunk(constants.TYPE_IEND, null);
- };
- });
- var packerAsync = createCommonjsModule(function (module) {
- let PackerAsync = (module.exports = function (opt) {
- Stream__default['default'].call(this);
- let options = opt || {};
- this._packer = new packer(options);
- this._deflate = this._packer.createDeflate();
- this.readable = true;
- });
- util__default['default'].inherits(PackerAsync, Stream__default['default']);
- PackerAsync.prototype.pack = function (data, width, height, gamma) {
- // Signature
- this.emit("data", Buffer.from(constants.PNG_SIGNATURE));
- this.emit("data", this._packer.packIHDR(width, height));
- if (gamma) {
- this.emit("data", this._packer.packGAMA(gamma));
- }
- let filteredData = this._packer.filterData(data, width, height);
- // compress it
- this._deflate.on("error", this.emit.bind(this, "error"));
- this._deflate.on(
- "data",
- function (compressedData) {
- this.emit("data", this._packer.packIDAT(compressedData));
- }.bind(this)
- );
- this._deflate.on(
- "end",
- function () {
- this.emit("data", this._packer.packIEND());
- this.emit("end");
- }.bind(this)
- );
- this._deflate.end(filteredData);
- };
- });
- var syncInflate = createCommonjsModule(function (module, exports) {
- let assert = require$$0__default['default'].ok;
- let kMaxLength = require$$1__default['default'].kMaxLength;
- function Inflate(opts) {
- if (!(this instanceof Inflate)) {
- return new Inflate(opts);
- }
- if (opts && opts.chunkSize < zlib__default['default'].Z_MIN_CHUNK) {
- opts.chunkSize = zlib__default['default'].Z_MIN_CHUNK;
- }
- zlib__default['default'].Inflate.call(this, opts);
- // Node 8 --> 9 compatibility check
- this._offset = this._offset === undefined ? this._outOffset : this._offset;
- this._buffer = this._buffer || this._outBuffer;
- if (opts && opts.maxLength != null) {
- this._maxLength = opts.maxLength;
- }
- }
- function createInflate(opts) {
- return new Inflate(opts);
- }
- function _close(engine, callback) {
- if (callback) {
- process.nextTick(callback);
- }
- // Caller may invoke .close after a zlib error (which will null _handle).
- if (!engine._handle) {
- return;
- }
- engine._handle.close();
- engine._handle = null;
- }
- Inflate.prototype._processChunk = function (chunk, flushFlag, asyncCb) {
- if (typeof asyncCb === "function") {
- return zlib__default['default'].Inflate._processChunk.call(this, chunk, flushFlag, asyncCb);
- }
- let self = this;
- let availInBefore = chunk && chunk.length;
- let availOutBefore = this._chunkSize - this._offset;
- let leftToInflate = this._maxLength;
- let inOff = 0;
- let buffers = [];
- let nread = 0;
- let error;
- this.on("error", function (err) {
- error = err;
- });
- function handleChunk(availInAfter, availOutAfter) {
- if (self._hadError) {
- return;
- }
- let have = availOutBefore - availOutAfter;
- assert(have >= 0, "have should not go down");
- if (have > 0) {
- let out = self._buffer.slice(self._offset, self._offset + have);
- self._offset += have;
- if (out.length > leftToInflate) {
- out = out.slice(0, leftToInflate);
- }
- buffers.push(out);
- nread += out.length;
- leftToInflate -= out.length;
- if (leftToInflate === 0) {
- return false;
- }
- }
- if (availOutAfter === 0 || self._offset >= self._chunkSize) {
- availOutBefore = self._chunkSize;
- self._offset = 0;
- self._buffer = Buffer.allocUnsafe(self._chunkSize);
- }
- if (availOutAfter === 0) {
- inOff += availInBefore - availInAfter;
- availInBefore = availInAfter;
- return true;
- }
- return false;
- }
- assert(this._handle, "zlib binding closed");
- let res;
- do {
- res = this._handle.writeSync(
- flushFlag,
- chunk, // in
- inOff, // in_off
- availInBefore, // in_len
- this._buffer, // out
- this._offset, //out_off
- availOutBefore
- ); // out_len
- // Node 8 --> 9 compatibility check
- res = res || this._writeState;
- } while (!this._hadError && handleChunk(res[0], res[1]));
- if (this._hadError) {
- throw error;
- }
- if (nread >= kMaxLength) {
- _close(this);
- throw new RangeError(
- "Cannot create final Buffer. It would be larger than 0x" +
- kMaxLength.toString(16) +
- " bytes"
- );
- }
- let buf = Buffer.concat(buffers, nread);
- _close(this);
- return buf;
- };
- util__default['default'].inherits(Inflate, zlib__default['default'].Inflate);
- function zlibBufferSync(engine, buffer) {
- if (typeof buffer === "string") {
- buffer = Buffer.from(buffer);
- }
- if (!(buffer instanceof Buffer)) {
- throw new TypeError("Not a string or buffer");
- }
- let flushFlag = engine._finishFlushFlag;
- if (flushFlag == null) {
- flushFlag = zlib__default['default'].Z_FINISH;
- }
- return engine._processChunk(buffer, flushFlag);
- }
- function inflateSync(buffer, opts) {
- return zlibBufferSync(new Inflate(opts), buffer);
- }
- module.exports = exports = inflateSync;
- exports.Inflate = Inflate;
- exports.createInflate = createInflate;
- exports.inflateSync = inflateSync;
- });
- var syncReader = createCommonjsModule(function (module) {
- let SyncReader = (module.exports = function (buffer) {
- this._buffer = buffer;
- this._reads = [];
- });
- SyncReader.prototype.read = function (length, callback) {
- this._reads.push({
- length: Math.abs(length), // if length < 0 then at most this length
- allowLess: length < 0,
- func: callback,
- });
- };
- SyncReader.prototype.process = function () {
- // as long as there is any data and read requests
- while (this._reads.length > 0 && this._buffer.length) {
- let read = this._reads[0];
- if (
- this._buffer.length &&
- (this._buffer.length >= read.length || read.allowLess)
- ) {
- // ok there is any data so that we can satisfy this request
- this._reads.shift(); // == read
- let buf = this._buffer;
- this._buffer = buf.slice(read.length);
- read.func.call(this, buf.slice(0, read.length));
- } else {
- break;
- }
- }
- if (this._reads.length > 0) {
- throw new Error("There are some read requests waitng on finished stream");
- }
- if (this._buffer.length > 0) {
- throw new Error("unrecognised content at end of stream");
- }
- };
- });
- var process_1 = function (inBuffer, bitmapInfo) {
- let outBuffers = [];
- let reader = new syncReader(inBuffer);
- let filter = new filterParse(bitmapInfo, {
- read: reader.read.bind(reader),
- write: function (bufferPart) {
- outBuffers.push(bufferPart);
- },
- complete: function () {},
- });
- filter.start();
- reader.process();
- return Buffer.concat(outBuffers);
- };
- var filterParseSync = {
- process: process_1
- };
- let hasSyncZlib$1 = true;
- if (!zlib__default['default'].deflateSync) {
- hasSyncZlib$1 = false;
- }
- var parserSync = function (buffer, options) {
- if (!hasSyncZlib$1) {
- throw new Error(
- "To use the sync capability of this library in old node versions, please pin pngjs to v2.3.0"
- );
- }
- let err;
- function handleError(_err_) {
- err = _err_;
- }
- let metaData;
- function handleMetaData(_metaData_) {
- metaData = _metaData_;
- }
- function handleTransColor(transColor) {
- metaData.transColor = transColor;
- }
- function handlePalette(palette) {
- metaData.palette = palette;
- }
- function handleSimpleTransparency() {
- metaData.alpha = true;
- }
- let gamma;
- function handleGamma(_gamma_) {
- gamma = _gamma_;
- }
- let inflateDataList = [];
- function handleInflateData(inflatedData) {
- inflateDataList.push(inflatedData);
- }
- let reader = new syncReader(buffer);
- let parser$1 = new parser(options, {
- read: reader.read.bind(reader),
- error: handleError,
- metadata: handleMetaData,
- gamma: handleGamma,
- palette: handlePalette,
- transColor: handleTransColor,
- inflateData: handleInflateData,
- simpleTransparency: handleSimpleTransparency,
- });
- parser$1.start();
- reader.process();
- if (err) {
- throw err;
- }
- //join together the inflate datas
- let inflateData = Buffer.concat(inflateDataList);
- inflateDataList.length = 0;
- let inflatedData;
- if (metaData.interlace) {
- inflatedData = zlib__default['default'].inflateSync(inflateData);
- } else {
- let rowSize =
- ((metaData.width * metaData.bpp * metaData.depth + 7) >> 3) + 1;
- let imageSize = rowSize * metaData.height;
- inflatedData = syncInflate(inflateData, {
- chunkSize: imageSize,
- maxLength: imageSize,
- });
- }
- inflateData = null;
- if (!inflatedData || !inflatedData.length) {
- throw new Error("bad png - invalid inflate data response");
- }
- let unfilteredData = filterParseSync.process(inflatedData, metaData);
- inflateData = null;
- let bitmapData = bitmapper.dataToBitMap(unfilteredData, metaData);
- unfilteredData = null;
- let normalisedBitmapData = formatNormaliser(
- bitmapData,
- metaData,
- options.skipRescale
- );
- metaData.data = normalisedBitmapData;
- metaData.gamma = gamma || 0;
- return metaData;
- };
- let hasSyncZlib = true;
- if (!zlib__default['default'].deflateSync) {
- hasSyncZlib = false;
- }
- var packerSync = function (metaData, opt) {
- if (!hasSyncZlib) {
- throw new Error(
- "To use the sync capability of this library in old node versions, please pin pngjs to v2.3.0"
- );
- }
- let options = opt || {};
- let packer$1 = new packer(options);
- let chunks = [];
- // Signature
- chunks.push(Buffer.from(constants.PNG_SIGNATURE));
- // Header
- chunks.push(packer$1.packIHDR(metaData.width, metaData.height));
- if (metaData.gamma) {
- chunks.push(packer$1.packGAMA(metaData.gamma));
- }
- let filteredData = packer$1.filterData(
- metaData.data,
- metaData.width,
- metaData.height
- );
- // compress it
- let compressedData = zlib__default['default'].deflateSync(
- filteredData,
- packer$1.getDeflateOptions()
- );
- filteredData = null;
- if (!compressedData || !compressedData.length) {
- throw new Error("bad png - invalid compressed data response");
- }
- chunks.push(packer$1.packIDAT(compressedData));
- // End
- chunks.push(packer$1.packIEND());
- return Buffer.concat(chunks);
- };
- var read = function (buffer, options) {
- return parserSync(buffer, options || {});
- };
- var write = function (png, options) {
- return packerSync(png, options);
- };
- var pngSync = {
- read: read,
- write: write
- };
- var png = createCommonjsModule(function (module, exports) {
- let PNG = (exports.PNG = function (options) {
- Stream__default['default'].call(this);
- options = options || {}; // eslint-disable-line no-param-reassign
- // coerce pixel dimensions to integers (also coerces undefined -> 0):
- this.width = options.width | 0;
- this.height = options.height | 0;
- this.data =
- this.width > 0 && this.height > 0
- ? Buffer.alloc(4 * this.width * this.height)
- : null;
- if (options.fill && this.data) {
- this.data.fill(0);
- }
- this.gamma = 0;
- this.readable = this.writable = true;
- this._parser = new parserAsync(options);
- this._parser.on("error", this.emit.bind(this, "error"));
- this._parser.on("close", this._handleClose.bind(this));
- this._parser.on("metadata", this._metadata.bind(this));
- this._parser.on("gamma", this._gamma.bind(this));
- this._parser.on(
- "parsed",
- function (data) {
- this.data = data;
- this.emit("parsed", data);
- }.bind(this)
- );
- this._packer = new packerAsync(options);
- this._packer.on("data", this.emit.bind(this, "data"));
- this._packer.on("end", this.emit.bind(this, "end"));
- this._parser.on("close", this._handleClose.bind(this));
- this._packer.on("error", this.emit.bind(this, "error"));
- });
- util__default['default'].inherits(PNG, Stream__default['default']);
- PNG.sync = pngSync;
- PNG.prototype.pack = function () {
- if (!this.data || !this.data.length) {
- this.emit("error", "No data provided");
- return this;
- }
- process.nextTick(
- function () {
- this._packer.pack(this.data, this.width, this.height, this.gamma);
- }.bind(this)
- );
- return this;
- };
- PNG.prototype.parse = function (data, callback) {
- if (callback) {
- let onParsed, onError;
- onParsed = function (parsedData) {
- this.removeListener("error", onError);
- this.data = parsedData;
- callback(null, this);
- }.bind(this);
- onError = function (err) {
- this.removeListener("parsed", onParsed);
- callback(err, null);
- }.bind(this);
- this.once("parsed", onParsed);
- this.once("error", onError);
- }
- this.end(data);
- return this;
- };
- PNG.prototype.write = function (data) {
- this._parser.write(data);
- return true;
- };
- PNG.prototype.end = function (data) {
- this._parser.end(data);
- };
- PNG.prototype._metadata = function (metadata) {
- this.width = metadata.width;
- this.height = metadata.height;
- this.emit("metadata", metadata);
- };
- PNG.prototype._gamma = function (gamma) {
- this.gamma = gamma;
- };
- PNG.prototype._handleClose = function () {
- if (!this._parser.writable && !this._packer.readable) {
- this.emit("close");
- }
- };
- PNG.bitblt = function (src, dst, srcX, srcY, width, height, deltaX, deltaY) {
- // eslint-disable-line max-params
- // coerce pixel dimensions to integers (also coerces undefined -> 0):
- /* eslint-disable no-param-reassign */
- srcX |= 0;
- srcY |= 0;
- width |= 0;
- height |= 0;
- deltaX |= 0;
- deltaY |= 0;
- /* eslint-enable no-param-reassign */
- if (
- srcX > src.width ||
- srcY > src.height ||
- srcX + width > src.width ||
- srcY + height > src.height
- ) {
- throw new Error("bitblt reading outside image");
- }
- if (
- deltaX > dst.width ||
- deltaY > dst.height ||
- deltaX + width > dst.width ||
- deltaY + height > dst.height
- ) {
- throw new Error("bitblt writing outside image");
- }
- for (let y = 0; y < height; y++) {
- src.data.copy(
- dst.data,
- ((deltaY + y) * dst.width + deltaX) << 2,
- ((srcY + y) * src.width + srcX) << 2,
- ((srcY + y) * src.width + srcX + width) << 2
- );
- }
- };
- PNG.prototype.bitblt = function (
- dst,
- srcX,
- srcY,
- width,
- height,
- deltaX,
- deltaY
- ) {
- // eslint-disable-line max-params
- PNG.bitblt(this, dst, srcX, srcY, width, height, deltaX, deltaY);
- return this;
- };
- PNG.adjustGamma = function (src) {
- if (src.gamma) {
- for (let y = 0; y < src.height; y++) {
- for (let x = 0; x < src.width; x++) {
- let idx = (src.width * y + x) << 2;
- for (let i = 0; i < 3; i++) {
- let sample = src.data[idx + i] / 255;
- sample = Math.pow(sample, 1 / 2.2 / src.gamma);
- src.data[idx + i] = Math.round(sample * 255);
- }
- }
- }
- src.gamma = 0;
- }
- };
- PNG.prototype.adjustGamma = function () {
- PNG.adjustGamma(this);
- };
- });
- function getMismatchedPixels(pixelMatchInput) {
- const imgA = fs__default['default'].createReadStream(pixelMatchInput.imageAPath).pipe(new png.PNG()).on('parsed', doneReading);
- const imgB = fs__default['default'].createReadStream(pixelMatchInput.imageBPath).pipe(new png.PNG()).on('parsed', doneReading);
- let filesRead = 0;
- function doneReading() {
- if (++filesRead < 2)
- return;
- const mismatchedPixels = pixelmatch_1(imgA.data, imgB.data, null, pixelMatchInput.width, pixelMatchInput.height, {
- threshold: pixelMatchInput.pixelmatchThreshold,
- includeAA: false,
- });
- process.send(mismatchedPixels);
- }
- }
- process.on('message', getMismatchedPixels);
|