webp.js 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', {
  3. value: true,
  4. });
  5. exports.default = exports.constants = void 0;
  6. const _fs2 = _interopRequireDefault(require('fs'));
  7. const _util = require('util');
  8. const _path = require('path');
  9. function _interopRequireDefault(obj) {
  10. return obj && obj.__esModule ? obj : {default: obj};
  11. }
  12. function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
  13. try {
  14. var info = gen[key](arg);
  15. var value = info.value;
  16. } catch (error) {
  17. reject(error);
  18. return;
  19. }
  20. if (info.done) {
  21. resolve(value);
  22. } else {
  23. Promise.resolve(value).then(_next, _throw);
  24. }
  25. }
  26. function _asyncToGenerator(fn) {
  27. return function() {
  28. const self = this;
  29. const args = arguments;
  30. return new Promise(function(resolve, reject) {
  31. const gen = fn.apply(self, args);
  32. function _next(value) {
  33. asyncGeneratorStep(gen, resolve, reject, _next, _throw, 'next', value);
  34. }
  35. function _throw(err) {
  36. asyncGeneratorStep(gen, resolve, reject, _next, _throw, 'throw', err);
  37. }
  38. _next(undefined);
  39. });
  40. };
  41. }
  42. function _defineProperty(obj, key, value) {
  43. if (key in obj) {
  44. Object.defineProperty(obj, key, {
  45. value: value,
  46. enumerable: true,
  47. configurable: true,
  48. writable: true,
  49. });
  50. } else {
  51. obj[key] = value;
  52. }
  53. return obj;
  54. }
  55. function _classPrivateMethodGet(receiver, privateSet, fn) {
  56. if (!privateSet.has(receiver)) {
  57. throw new TypeError('attempted to get private field on non-instance');
  58. }
  59. return fn;
  60. }
  61. const fs = {
  62. read: (0, _util.promisify)(_fs2.default.read),
  63. write: (0, _util.promisify)(_fs2.default.write),
  64. open: (0, _util.promisify)(_fs2.default.open),
  65. close: (0, _util.promisify)(_fs2.default.close),
  66. };
  67. const nullByte = Buffer.alloc(1);
  68. nullByte[0] = 0;
  69. const constants = {
  70. TYPE_LOSSY: 0,
  71. TYPE_LOSSLESS: 1,
  72. TYPE_EXTENDED: 2,
  73. };
  74. exports.constants = constants;
  75. function VP8Width(data) {
  76. const n = (data[7] << 8) | data[6];
  77. return n & 0b0011111111111111;
  78. }
  79. function VP8Height(data) {
  80. const n = (data[9] << 8) | data[8];
  81. return n & 0b0011111111111111;
  82. }
  83. function VP8LWidth(data) {
  84. const n = (data[2] << 8) | data[1];
  85. return (n & 0b0011111111111111) + 1;
  86. }
  87. function VP8LHeight(data) {
  88. let n = (data[4] << 16) | (data[3] << 8) | data[2];
  89. n = n >> 6;
  90. return (n & 0b0011111111111111) + 1;
  91. }
  92. function doesVP8LHaveAlpha(data) {
  93. return !!(data[4] & 0b00010000);
  94. }
  95. function createBasicChunk(name, data) {
  96. const chunk = Buffer.alloc(8);
  97. const size = data.length;
  98. let out;
  99. chunk.write(name, 0);
  100. chunk.writeUInt32LE(size, 4);
  101. out = [chunk, data];
  102. if (size & 1) {
  103. out[2] = nullByte;
  104. }
  105. return out;
  106. }
  107. const _convertToExtended = new WeakSet();
  108. const _demuxFrame = new WeakSet();
  109. const _readHeader = new WeakSet();
  110. const _readChunkHeader = new WeakSet();
  111. const _readChunkHeader_buf = new WeakSet();
  112. const _readChunk_raw = new WeakSet();
  113. const _readChunk_VP = new WeakSet();
  114. const _readChunk_VP8_buf = new WeakSet();
  115. const _readChunk_VP8L = new WeakSet();
  116. const _readChunk_VP8L_buf = new WeakSet();
  117. const _readChunk_VP8X = new WeakSet();
  118. const _readChunk_ANIM = new WeakSet();
  119. const _readChunk_ANMF = new WeakSet();
  120. const _readChunk_ALPH = new WeakSet();
  121. const _readChunk_ALPH_buf = new WeakSet();
  122. const _readChunk_ICCP = new WeakSet();
  123. const _readChunk_EXIF = new WeakSet();
  124. const _readChunk_XMP = new WeakSet();
  125. const _readChunk_Skip = new WeakSet();
  126. const _read = new WeakSet();
  127. class Image {
  128. constructor() {
  129. _read.add(this);
  130. _readChunk_Skip.add(this);
  131. _readChunk_XMP.add(this);
  132. _readChunk_EXIF.add(this);
  133. _readChunk_ICCP.add(this);
  134. _readChunk_ALPH_buf.add(this);
  135. _readChunk_ALPH.add(this);
  136. _readChunk_ANMF.add(this);
  137. _readChunk_ANIM.add(this);
  138. _readChunk_VP8X.add(this);
  139. _readChunk_VP8L_buf.add(this);
  140. _readChunk_VP8L.add(this);
  141. _readChunk_VP8_buf.add(this);
  142. _readChunk_VP.add(this);
  143. _readChunk_raw.add(this);
  144. _readChunkHeader_buf.add(this);
  145. _readChunkHeader.add(this);
  146. _readHeader.add(this);
  147. _demuxFrame.add(this);
  148. _convertToExtended.add(this);
  149. _defineProperty(this, 'data', null);
  150. _defineProperty(this, 'loaded', false);
  151. _defineProperty(this, 'path', '');
  152. }
  153. clear() {
  154. this.data = null;
  155. this.path = '';
  156. this.loaded = false;
  157. }
  158. get width() {
  159. if (!this.loaded) {
  160. return undefined;
  161. }
  162. const d = this.data;
  163. return d.extended ?
  164. d.extended.width :
  165. d.vp8l ?
  166. d.vp8l.width :
  167. d.vp8 ?
  168. d.vp8.width :
  169. undefined;
  170. }
  171. get height() {
  172. if (!this.loaded) {
  173. return undefined;
  174. }
  175. const d = this.data;
  176. return d.extended ?
  177. d.extended.height :
  178. d.vp8l ?
  179. d.vp8l.height :
  180. d.vp8 ?
  181. d.vp8.height :
  182. undefined;
  183. }
  184. get type() {
  185. return this.loaded ? this.data.type : undefined;
  186. }
  187. get hasAnim() {
  188. return this.loaded ?
  189. this.data.extended ?
  190. this.data.extended.hasAnim :
  191. false :
  192. false;
  193. }
  194. get anim() {
  195. return this.hasAnim ? this.data.anim : undefined;
  196. }
  197. get frameCount() {
  198. return this.anim ? this.anim.frameCount : 0;
  199. }
  200. get iccp() {
  201. return this.data.extended ?
  202. this.data.extended.hasICCP ?
  203. this.data.iccp.raw :
  204. undefined :
  205. undefined;
  206. }
  207. set iccp(raw) {
  208. if (!this.data.extended) {
  209. _classPrivateMethodGet(
  210. this,
  211. _convertToExtended,
  212. _convertToExtended2,
  213. ).call(this);
  214. }
  215. if (raw === undefined) {
  216. this.data.extended.hasICCP = false;
  217. delete this.data.iccp;
  218. } else {
  219. this.data.iccp = {
  220. raw,
  221. };
  222. this.data.extended.hasICCP = true;
  223. }
  224. }
  225. get exif() {
  226. return this.data.extended ?
  227. this.data.extended.hasEXIF ?
  228. this.data.exif.raw :
  229. undefined :
  230. undefined;
  231. }
  232. set exif(raw) {
  233. if (!this.data.extended) {
  234. _classPrivateMethodGet(
  235. this,
  236. _convertToExtended,
  237. _convertToExtended2,
  238. ).call(this);
  239. }
  240. if (raw === undefined) {
  241. this.data.extended.hasEXIF = false;
  242. delete this.data.exif;
  243. } else {
  244. this.data.exif = {
  245. raw,
  246. };
  247. this.data.extended.hasEXIF = true;
  248. }
  249. }
  250. get xmp() {
  251. return this.data.extended ?
  252. this.data.extended.hasXMP ?
  253. this.data.xmp.raw :
  254. undefined :
  255. undefined;
  256. }
  257. set xmp(raw) {
  258. if (!this.data.extended) {
  259. _classPrivateMethodGet(
  260. this,
  261. _convertToExtended,
  262. _convertToExtended2,
  263. ).call(this);
  264. }
  265. if (raw === undefined) {
  266. this.data.extended.hasXMP = false;
  267. delete this.data.xmp;
  268. } else {
  269. this.data.xmp = {
  270. raw,
  271. };
  272. this.data.extended.hasXMP = true;
  273. }
  274. }
  275. load(path) {
  276. const _this = this;
  277. return _asyncToGenerator(function* () {
  278. _this.path = path;
  279. _this.data = yield _classPrivateMethodGet(_this, _read, _read2).call(
  280. _this,
  281. path,
  282. );
  283. _this.loaded = true;
  284. })();
  285. }
  286. demuxAnim(path, frame = -1, prefix = '#FNAME#') {
  287. const _this2 = this;
  288. return _asyncToGenerator(function* () {
  289. let start = 0;
  290. let end = _this2.frameCount;
  291. if (end == 0) {
  292. throw new Error('This WebP isn\'t an animation');
  293. }
  294. if (frame != -1) {
  295. start = end = frame;
  296. }
  297. for (let i = start; i <= end; i++) {
  298. yield _classPrivateMethodGet(_this2, _demuxFrame, _demuxFrame2).call(
  299. _this2,
  300. `${path}/${prefix}_${i}.webp`.replace(
  301. /#FNAME#/g,
  302. (0, _path.basename)(_this2.path, '.webp'),
  303. ),
  304. _this2.anim.frames[i],
  305. );
  306. }
  307. })();
  308. }
  309. replaceFrame(path, frame) {
  310. const _this3 = this;
  311. return _asyncToGenerator(function* () {
  312. if (!_this3.hasAnim) {
  313. throw new Error('WebP isn\'t animated');
  314. }
  315. if (frame < 0 || frame >= _this3.frameCount) {
  316. throw new Error(
  317. `Frame index ${frame} out of bounds (0<=index<${_this3.frameCount})`,
  318. );
  319. }
  320. const r = new Image();
  321. yield r.load(path);
  322. switch (r.type) {
  323. case constants.TYPE_LOSSY:
  324. case constants.TYPE_LOSSLESS:
  325. break;
  326. case constants.TYPE_EXTENDED:
  327. if (r.hasAnim) {
  328. throw new Error('Merging animations not currently supported');
  329. }
  330. break;
  331. default:
  332. throw new Error('Unknown WebP type');
  333. }
  334. switch (_this3.anim.frames[frame].type) {
  335. case constants.TYPE_LOSSY:
  336. if (_this3.anim.frames[frame].vp8.alpha) {
  337. delete _this3.anim.frames[frame].alph;
  338. }
  339. delete _this3.anim.frames[frame].vp8;
  340. break;
  341. case constants.TYPE_LOSSLESS:
  342. delete _this3.anim.frames[frame].vp8l;
  343. break;
  344. default:
  345. throw new Error('Unknown frame type');
  346. }
  347. switch (r.type) {
  348. case constants.TYPE_LOSSY:
  349. _this3.anim.frames[frame].vp8 = r.data.vp8;
  350. break;
  351. case constants.TYPE_LOSSLESS:
  352. _this3.anim.frames[frame].vp8l = r.data.vp8l;
  353. break;
  354. case constants.TYPE_EXTENDED:
  355. if (r.data.vp8) {
  356. _this3.anim.frames[frame].vp8 = r.data.vp8;
  357. if (r.data.vp8.alpha) {
  358. _this3.anim.frames[frame].alph = r.data.alph;
  359. }
  360. } else if (r.data.vp8l) {
  361. _this3.anim.frames[frame].vp8l = r.data.vp8l;
  362. }
  363. break;
  364. }
  365. _this3.anim.frames[frame].width = r.width;
  366. _this3.anim.frames[frame].height = r.height;
  367. })();
  368. }
  369. muxAnim({path, bgColor = [255, 255, 255, 255], loops = 0} = {}) {
  370. const _this4 = this;
  371. return _asyncToGenerator(function* () {
  372. return Image.muxAnim({
  373. path,
  374. bgColor,
  375. loops,
  376. frames: _this4.frames,
  377. });
  378. })();
  379. }
  380. static muxAnim({
  381. path,
  382. frames,
  383. width = 0,
  384. height = 0,
  385. bgColor = [255, 255, 255, 255],
  386. loops = 0,
  387. delay = 100,
  388. x = 0,
  389. y = 0,
  390. blend = true,
  391. dispose = false,
  392. } = {}) {
  393. return _asyncToGenerator(function* () {
  394. const header = Buffer.alloc(12);
  395. let chunk = Buffer.alloc(18);
  396. const out = [];
  397. let img;
  398. let alpha = false;
  399. let size;
  400. let _w = 0;
  401. let _h = 0;
  402. const _width = width - 1;
  403. const _height = height - 1;
  404. if (frames.length == 0) {
  405. throw new Error('No frames to mux');
  406. } else if (_width <= 0 || _width > 1 << 24) {
  407. throw new Error('Width out of range');
  408. } else if (_height <= 0 || _height > 1 << 24) {
  409. throw new Error('Height out of range');
  410. } else if (_height * _width > Math.pow(2, 32) - 1) {
  411. throw new Error(`Width*height too large (${_width}, ${_height})`);
  412. } else if (loops < 0 || loops >= 1 << 24) {
  413. throw new Error('Loops out of range');
  414. } else if (delay < 0 || delay >= 1 << 24) {
  415. throw new Error('Delay out of range');
  416. } else if (x < 0 || x >= 1 << 24) {
  417. throw new Error('X out of range');
  418. } else if (y < 0 || y >= 1 << 24) {
  419. throw new Error('Y out of range');
  420. }
  421. header.write('RIFF', 0);
  422. header.write('WEBP', 8);
  423. chunk.write('VP8X', 0);
  424. chunk.writeUInt32LE(10, 4);
  425. chunk[8] |= 0b00000010;
  426. if (width != 0) {
  427. chunk.writeUIntLE(_width, 12, 3);
  428. }
  429. if (height != 0) {
  430. chunk.writeUIntLE(_height, 15, 3);
  431. }
  432. out.push(header, chunk);
  433. chunk = Buffer.alloc(14);
  434. chunk.write('ANIM', 0);
  435. chunk.writeUInt32LE(6, 4);
  436. chunk.writeUInt8(bgColor[2], 8);
  437. chunk.writeUInt8(bgColor[1], 9);
  438. chunk.writeUInt8(bgColor[0], 10);
  439. chunk.writeUInt8(bgColor[3], 11);
  440. chunk.writeUInt16LE(loops, 12);
  441. out.push(chunk);
  442. for (let i = 0, l = frames.length; i < l; i++) {
  443. const _delay =
  444. typeof frames[i].delay === 'undefined' ? delay : frames[i].delay;
  445. const _x = typeof frames[i].x === 'undefined' ? x : frames[i].x;
  446. const _y = typeof frames[i].y === 'undefined' ? y : frames[i].y;
  447. const _blend =
  448. typeof frames[i].blend === 'undefined' ? blend : frames[i].blend;
  449. const _dispose =
  450. typeof frames[i].dispose === 'undefined' ?
  451. dispose :
  452. frames[i].dispose;
  453. let size = 16;
  454. let keepChunk = true;
  455. let imgData;
  456. if (delay < 0 || delay >= 1 << 24) {
  457. throw new Error(`Delay out of range on frame ${i}`);
  458. } else if (x < 0 || x >= 1 << 24) {
  459. throw new Error(`X out of range on frame ${i}`);
  460. } else if (y < 0 || y >= 1 << 24) {
  461. throw new Error(`Y out of range on frame ${i}`);
  462. }
  463. chunk = Buffer.alloc(24);
  464. chunk.write('ANMF', 0);
  465. chunk.writeUIntLE(_x, 8, 3);
  466. chunk.writeUIntLE(_y, 11, 3);
  467. chunk.writeUIntLE(_delay, 20, 3);
  468. if (!_blend) {
  469. chunk[23] |= 0b00000010;
  470. }
  471. if (_dispose) {
  472. chunk[23] |= 0b00000001;
  473. }
  474. if (frames[i].path) {
  475. img = new Image();
  476. yield img.load(frames[i].path);
  477. } else {
  478. img = {
  479. data: frames[i],
  480. };
  481. }
  482. chunk.writeUIntLE(img.data.width - 1, 14, 3);
  483. chunk.writeUIntLE(img.data.height - 1, 17, 3);
  484. switch (img.data.type) {
  485. case constants.TYPE_LOSSY:
  486. {
  487. const c = img.data.vp8;
  488. _w = c.width > _w ? c.width : _w;
  489. _h = c.height > _h ? c.height : _h;
  490. size += c.raw.length + 8;
  491. imgData = createBasicChunk('VP8 ', c.raw);
  492. }
  493. break;
  494. case constants.TYPE_LOSSLESS:
  495. {
  496. const c = img.data.vp8l;
  497. _w = c.width > _w ? c.width : _w;
  498. _h = c.height > _h ? c.height : _h;
  499. size += c.raw.length + 8;
  500. if (c.alpha) {
  501. alpha = true;
  502. }
  503. imgData = createBasicChunk('VP8L', c.raw);
  504. }
  505. break;
  506. case constants.TYPE_EXTENDED:
  507. if (img.data.extended.hasAnim) {
  508. const fr = img.data.anim.frames;
  509. keepChunk = false;
  510. if (img.data.extended.hasAlpha) {
  511. alpha = true;
  512. }
  513. for (let i = 0, l = fr.length; i < l; i++) {
  514. _w = fr[i].width + _x > _w ? fr[i].width + _x : _w;
  515. _h = fr[i].height + _y > _h ? fr[i].height + _y : _h;
  516. let b = Buffer.alloc(8);
  517. b.write('ANMF', 0);
  518. b.writeUInt32LE(fr[i].raw.length, 4);
  519. out.push(b, fr[i].raw);
  520. if (fr[i].raw.length & 1) {
  521. out.push(nullByte);
  522. }
  523. b = fr[i].raw;
  524. b.writeUIntLE(_x, 0, 3);
  525. b.writeUIntLE(_y, 3, 3);
  526. b.writeUIntLE(_delay, 12, 3);
  527. if (!_blend) {
  528. b[15] |= 0b00000010;
  529. } else {
  530. b[15] &= 0b11111101;
  531. }
  532. if (_dispose) {
  533. b[15] |= 0b00000001;
  534. } else {
  535. b[15] &= 0b11111110;
  536. }
  537. }
  538. } else {
  539. _w = img.data.extended.width > _w ? img.data.extended.width : _w;
  540. _h =
  541. img.data.extended.height > _h ? img.data.extended.height : _h;
  542. if (img.data.vp8) {
  543. imgData = [];
  544. if (img.data.alph) {
  545. alpha = true;
  546. imgData.push(...createBasicChunk('ALPH', img.data.alph.raw));
  547. size += img.data.alph.raw.length + 8;
  548. }
  549. imgData.push(...createBasicChunk('VP8 ', img.data.vp8.raw));
  550. size += img.data.vp8.raw.length + 8;
  551. } else if (img.data.vp8l) {
  552. imgData = createBasicChunk('VP8L', img.data.vp8l.raw);
  553. if (img.data.vp8l.alpha) {
  554. alpha = true;
  555. }
  556. size += img.data.vp8l.raw.length + 8;
  557. }
  558. }
  559. break;
  560. default:
  561. throw new Error('Unknown image type');
  562. }
  563. if (keepChunk) {
  564. chunk.writeUInt32LE(size, 4);
  565. out.push(chunk, ...imgData);
  566. }
  567. }
  568. if (width == 0) {
  569. out[1].writeUIntLE(_w - 1, 12, 3);
  570. }
  571. if (height == 0) {
  572. out[1].writeUIntLE(_h - 1, 15, 3);
  573. }
  574. size = 4;
  575. for (let i = 1, l = out.length; i < l; i++) {
  576. size += out[i].length;
  577. }
  578. header.writeUInt32LE(size, 4);
  579. if (alpha) {
  580. out[1][8] |= 0b00010000;
  581. }
  582. const fp = yield fs.open(path, 'w');
  583. for (let i = 0, l = out.length; i < l; i++) {
  584. yield fs.write(fp, out[i], 0, undefined, undefined);
  585. }
  586. yield fs.close(fp);
  587. })();
  588. }
  589. }
  590. var _convertToExtended2 = function _convertToExtended2() {
  591. if (!this.loaded) {
  592. throw new Error('No image loaded');
  593. }
  594. this.data.type = constants.TYPE_EXTENDED;
  595. this.data.extended = {
  596. hasICC: false,
  597. hasAlpha: false,
  598. hasEXIF: false,
  599. hasXMP: false,
  600. width: this.vp8 ? this.vp8.width : this.vp8l ? this.vp8l.width : 1,
  601. height: this.vp8 ? this.vp8.height : this.vp8l ? this.vp8l.height : 1,
  602. };
  603. };
  604. var _demuxFrame2 = /* #__PURE__*/ (function() {
  605. const _demuxFrame3 = _asyncToGenerator(function* (path, frame) {
  606. const header = Buffer.alloc(12);
  607. let size;
  608. let chunk;
  609. const out = [];
  610. header.write('RIFF', 0);
  611. header.write('WEBP', 8);
  612. out.push(header);
  613. if (
  614. this.data.extended.hasICC ||
  615. this.data.extended.hasEXIF ||
  616. this.data.extended.hasXMP ||
  617. (frame.vp8 && frame.vp8.alpha)
  618. ) {
  619. chunk = Buffer.alloc(18);
  620. chunk.write('VP8X', 0);
  621. chunk.writeUInt32LE(10, 4);
  622. if (this.data.extended.hasICC) {
  623. chunk[8] |= 0b00100000;
  624. }
  625. if ((frame.vp8l && frame.vp8l.alpha) || (frame.vp8 && frame.vp8.alpha)) {
  626. chunk[8] |= 0b00010000;
  627. }
  628. if (this.data.extended.hasEXIF) {
  629. chunk[8] |= 0b00001000;
  630. }
  631. if (this.data.extended.hasXMP) {
  632. chunk[8] |= 0b00000100;
  633. }
  634. chunk.writeUIntLE(frame.width - 1, 12, 3);
  635. chunk.writeUIntLE(frame.height - 1, 15, 3);
  636. out.push(chunk);
  637. if (this.data.extended.hasICC) {
  638. out.push(...createBasicChunk('ICCP', this.data.extended.icc.raw));
  639. }
  640. }
  641. if (frame.vp8l) {
  642. out.push(...createBasicChunk('VP8L', frame.vp8l.raw));
  643. } else if (frame.vp8) {
  644. if (frame.vp8.alpha) {
  645. out.push(...createBasicChunk('ALPH', frame.alph.raw));
  646. }
  647. out.push(...createBasicChunk('VP8 ', frame.vp8.raw));
  648. } else {
  649. throw new Error('Frame has no VP8/VP8L?');
  650. }
  651. if (this.type == constants.TYPE_EXTENDED) {
  652. if (this.data.extended.hasEXIF) {
  653. out.push(...createBasicChunk('EXIF', this.data.extended.exif.raw));
  654. }
  655. if (this.data.extended.hasXMP) {
  656. out.push(...createBasicChunk('XMP ', this.data.extended.xmp.raw));
  657. }
  658. }
  659. size = 4;
  660. for (let i = 1, l = out.length; i < l; i++) {
  661. size += out[i].length;
  662. }
  663. header.writeUInt32LE(size, 4);
  664. const fp = yield fs.open(path, 'w');
  665. for (let i = 0, l = out.length; i < l; i++) {
  666. yield fs.write(fp, out[i], 0, undefined, undefined);
  667. }
  668. yield fs.close(fp);
  669. });
  670. function _demuxFrame2(_x2, _x3) {
  671. return _demuxFrame3.apply(this, arguments);
  672. }
  673. return _demuxFrame2;
  674. })();
  675. const _readHeader2 = /* #__PURE__*/ (function() {
  676. const _readHeader3 = _asyncToGenerator(function* (fd) {
  677. const buf = Buffer.alloc(12);
  678. const {bytesRead} = yield fs.read(fd, buf, 0, 12, undefined);
  679. if (bytesRead != 12) {
  680. throw new Error('Reached end of file while reading header');
  681. }
  682. if (buf.toString('utf8', 0, 4) != 'RIFF') {
  683. throw new Error('Bad header (not RIFF)');
  684. }
  685. if (buf.toString('utf8', 8, 12) != 'WEBP') {
  686. throw new Error('Bad header (not WEBP)');
  687. }
  688. return {
  689. fileSize: buf.readUInt32LE(4),
  690. };
  691. });
  692. function _readHeader2(_x4) {
  693. return _readHeader3.apply(this, arguments);
  694. }
  695. return _readHeader2;
  696. })();
  697. const _readChunkHeader2 = /* #__PURE__*/ (function() {
  698. const _readChunkHeader3 = _asyncToGenerator(function* (fd) {
  699. const buf = Buffer.alloc(8);
  700. const {bytesRead} = yield fs.read(fd, buf, 0, 8, undefined);
  701. if (bytesRead == 0) {
  702. return {
  703. fourCC: '\x00\x00\x00\x00',
  704. size: 0,
  705. };
  706. } else if (bytesRead < 8) {
  707. throw new Error('Reached end of file while reading chunk header');
  708. }
  709. return {
  710. fourCC: buf.toString('utf8', 0, 4),
  711. size: buf.readUInt32LE(4),
  712. };
  713. });
  714. function _readChunkHeader2(_x5) {
  715. return _readChunkHeader3.apply(this, arguments);
  716. }
  717. return _readChunkHeader2;
  718. })();
  719. const _readChunkHeader_buf2 = function _readChunkHeader_buf2(buf, cursor) {
  720. if (cursor >= buf.length) {
  721. return {
  722. fourCC: '\x00\x00\x00\x00',
  723. size: 0,
  724. };
  725. }
  726. return {
  727. fourCC: buf.toString('utf8', cursor, cursor + 4),
  728. size: buf.readUInt32LE(cursor + 4),
  729. };
  730. };
  731. const _readChunk_raw2 = /* #__PURE__*/ (function() {
  732. const _readChunk_raw3 = _asyncToGenerator(function* (n, fd, size) {
  733. const buf = Buffer.alloc(size);
  734. const discard = Buffer.alloc(1);
  735. const {bytesRead} = yield fs.read(fd, buf, 0, size, undefined);
  736. if (bytesRead != size) {
  737. throw new Error(`Reached end of file while reading ${n} chunk`);
  738. }
  739. if (size & 1) {
  740. yield fs.read(fd, discard, 0, 1, undefined);
  741. }
  742. return {
  743. raw: buf,
  744. };
  745. });
  746. function _readChunk_raw2(_x6, _x7, _x8) {
  747. return _readChunk_raw3.apply(this, arguments);
  748. }
  749. return _readChunk_raw2;
  750. })();
  751. const _readChunk_VP2 = /* #__PURE__*/ (function() {
  752. const _readChunk_VP3 = _asyncToGenerator(function* (fd, size) {
  753. const buf = Buffer.alloc(size);
  754. const discard = Buffer.alloc(1);
  755. const {bytesRead} = yield fs.read(fd, buf, 0, size, undefined);
  756. if (bytesRead != size) {
  757. throw new Error('Reached end of file while reading VP8 chunk');
  758. }
  759. if (size & 1) {
  760. yield fs.read(fd, discard, 0, 1, undefined);
  761. }
  762. return {
  763. raw: buf,
  764. width: VP8Width(buf, 8),
  765. height: VP8Height(buf, 8),
  766. };
  767. });
  768. function _readChunk_VP2(_x9, _x10) {
  769. return _readChunk_VP3.apply(this, arguments);
  770. }
  771. return _readChunk_VP2;
  772. })();
  773. const _readChunk_VP8_buf2 = function _readChunk_VP8_buf2(buf, size, cursor) {
  774. if (cursor >= buf.length) {
  775. throw new Error('Reached end of buffer while reading VP8 chunk');
  776. }
  777. const raw = buf.slice(cursor, cursor + size);
  778. return {
  779. raw,
  780. width: VP8Width(raw),
  781. height: VP8Height(raw),
  782. };
  783. };
  784. const _readChunk_VP8L2 = /* #__PURE__*/ (function() {
  785. const _readChunk_VP8L3 = _asyncToGenerator(function* (fd, size) {
  786. const buf = Buffer.alloc(size);
  787. const discard = Buffer.alloc(1);
  788. const {bytesRead} = yield fs.read(fd, buf, 0, size, undefined);
  789. if (bytesRead != size) {
  790. throw new Error('Reached end of file while reading VP8L chunk');
  791. }
  792. if (size & 1) {
  793. yield fs.read(fd, discard, 0, 1, undefined);
  794. }
  795. return {
  796. raw: buf,
  797. alpha: doesVP8LHaveAlpha(buf, 0),
  798. width: VP8LWidth(buf),
  799. height: VP8LHeight(buf),
  800. };
  801. });
  802. function _readChunk_VP8L2(_x11, _x12) {
  803. return _readChunk_VP8L3.apply(this, arguments);
  804. }
  805. return _readChunk_VP8L2;
  806. })();
  807. const _readChunk_VP8L_buf2 = function _readChunk_VP8L_buf2(buf, size, cursor) {
  808. if (cursor >= buf.length) {
  809. throw new Error('Reached end of buffer while reading VP8L chunk');
  810. }
  811. const raw = buf.slice(cursor, cursor + size);
  812. return {
  813. raw,
  814. alpha: doesVP8LHaveAlpha(raw),
  815. width: VP8LWidth(raw),
  816. height: VP8LHeight(raw),
  817. };
  818. };
  819. const _readChunk_VP8X2 = /* #__PURE__*/ (function() {
  820. const _readChunk_VP8X3 = _asyncToGenerator(function* (fd, size) {
  821. const buf = Buffer.alloc(size);
  822. const {bytesRead} = yield fs.read(fd, buf, 0, size, undefined);
  823. if (bytesRead != size) {
  824. throw new Error('Reached end of file while reading VP8X chunk');
  825. }
  826. return {
  827. raw: buf,
  828. hasICC: !!(buf[0] & 0b00100000),
  829. hasAlpha: !!(buf[0] & 0b00010000),
  830. hasEXIF: !!(buf[0] & 0b00001000),
  831. hasXMP: !!(buf[0] & 0b00000100),
  832. hasAnim: !!(buf[0] & 0b00000010),
  833. width: buf.readUIntLE(4, 3) + 1,
  834. height: buf.readUIntLE(7, 3) + 1,
  835. };
  836. });
  837. function _readChunk_VP8X2(_x13, _x14) {
  838. return _readChunk_VP8X3.apply(this, arguments);
  839. }
  840. return _readChunk_VP8X2;
  841. })();
  842. const _readChunk_ANIM2 = /* #__PURE__*/ (function() {
  843. const _readChunk_ANIM3 = _asyncToGenerator(function* (fd, size) {
  844. const buf = Buffer.alloc(size);
  845. const {bytesRead} = yield fs.read(fd, buf, 0, size, undefined);
  846. if (bytesRead != size) {
  847. throw new Error('Reached end of file while reading ANIM chunk');
  848. }
  849. return {
  850. raw: buf,
  851. bgColor: buf.slice(0, 4),
  852. loopCount: buf.readUInt16LE(4),
  853. };
  854. });
  855. function _readChunk_ANIM2(_x15, _x16) {
  856. return _readChunk_ANIM3.apply(this, arguments);
  857. }
  858. return _readChunk_ANIM2;
  859. })();
  860. const _readChunk_ANMF2 = /* #__PURE__*/ (function() {
  861. const _readChunk_ANMF3 = _asyncToGenerator(function* (fd, size) {
  862. const buf = Buffer.alloc(size);
  863. const discard = Buffer.alloc(1);
  864. const {bytesRead} = yield fs.read(fd, buf, 0, size, undefined);
  865. if (bytesRead != size) {
  866. throw new Error('Reached end of file while reading ANMF chunk');
  867. }
  868. if (size & 1) {
  869. yield fs.read(fd, discard, 0, 1, undefined);
  870. }
  871. const out = {
  872. raw: buf,
  873. x: buf.readUIntLE(0, 3),
  874. y: buf.readUIntLE(3, 3),
  875. width: buf.readUIntLE(6, 3) + 1,
  876. height: buf.readUIntLE(9, 3) + 1,
  877. duration: buf.readUIntLE(12, 3),
  878. blend: !(buf[15] & 0b00000010),
  879. dispose: !!(buf[15] & 0b00000001),
  880. };
  881. let keepLooping = true;
  882. let cursor = 16;
  883. while (keepLooping) {
  884. const header = _classPrivateMethodGet(
  885. this,
  886. _readChunkHeader_buf,
  887. _readChunkHeader_buf2,
  888. ).call(this, buf, cursor);
  889. let t;
  890. cursor += 8;
  891. switch (header.fourCC) {
  892. case 'VP8 ':
  893. if (!out.vp8) {
  894. out.type = constants.TYPE_LOSSY;
  895. out.vp8 = _classPrivateMethodGet(
  896. this,
  897. _readChunk_VP8_buf,
  898. _readChunk_VP8_buf2,
  899. ).call(this, buf, header.size, cursor);
  900. }
  901. break;
  902. case 'VP8L':
  903. if (!out.vp8l) {
  904. out.type = constants.TYPE_LOSSLESS;
  905. out.vp8l = _classPrivateMethodGet(
  906. this,
  907. _readChunk_VP8L_buf,
  908. _readChunk_VP8L_buf2,
  909. ).call(this, buf, header.size, cursor);
  910. }
  911. break;
  912. case 'ALPH':
  913. if (out.vp8) {
  914. out.alph = _classPrivateMethodGet(
  915. this,
  916. _readChunk_ALPH_buf,
  917. _readChunk_ALPH_buf2,
  918. ).call(this, buf, header.size, cursor);
  919. out.vp8.alpha = true;
  920. }
  921. break;
  922. case '\x00\x00\x00\x00':
  923. default:
  924. keepLooping = false;
  925. break;
  926. }
  927. cursor += header.size + 1;
  928. if (header.size & 1) {
  929. cursor++;
  930. }
  931. if (cursor >= buf.length) {
  932. keepLooping = false;
  933. }
  934. }
  935. return out;
  936. });
  937. function _readChunk_ANMF2(_x17, _x18) {
  938. return _readChunk_ANMF3.apply(this, arguments);
  939. }
  940. return _readChunk_ANMF2;
  941. })();
  942. const _readChunk_ALPH2 = /* #__PURE__*/ (function() {
  943. const _readChunk_ALPH3 = _asyncToGenerator(function* (fd, size) {
  944. return _classPrivateMethodGet(this, _readChunk_raw, _readChunk_raw2).call(
  945. this,
  946. 'ALPH',
  947. fd,
  948. size,
  949. );
  950. });
  951. function _readChunk_ALPH2(_x19, _x20) {
  952. return _readChunk_ALPH3.apply(this, arguments);
  953. }
  954. return _readChunk_ALPH2;
  955. })();
  956. var _readChunk_ALPH_buf2 = function _readChunk_ALPH_buf2(buf, size, cursor) {
  957. if (cusor >= buf.length) {
  958. throw new Error('Reached end of buffer while reading ALPH chunk');
  959. }
  960. return {
  961. raw: buf.slice(cursor, cursor + size),
  962. };
  963. };
  964. const _readChunk_ICCP2 = /* #__PURE__*/ (function() {
  965. const _readChunk_ICCP3 = _asyncToGenerator(function* (fd, size) {
  966. return _classPrivateMethodGet(this, _readChunk_raw, _readChunk_raw2).call(
  967. this,
  968. 'ICCP',
  969. fd,
  970. size,
  971. );
  972. });
  973. function _readChunk_ICCP2(_x21, _x22) {
  974. return _readChunk_ICCP3.apply(this, arguments);
  975. }
  976. return _readChunk_ICCP2;
  977. })();
  978. const _readChunk_EXIF2 = /* #__PURE__*/ (function() {
  979. const _readChunk_EXIF3 = _asyncToGenerator(function* (fd, size) {
  980. return _classPrivateMethodGet(this, _readChunk_raw, _readChunk_raw2).call(
  981. this,
  982. 'EXIF',
  983. fd,
  984. size,
  985. );
  986. });
  987. function _readChunk_EXIF2(_x23, _x24) {
  988. return _readChunk_EXIF3.apply(this, arguments);
  989. }
  990. return _readChunk_EXIF2;
  991. })();
  992. const _readChunk_XMP2 = /* #__PURE__*/ (function() {
  993. const _readChunk_XMP3 = _asyncToGenerator(function* (fd, size) {
  994. return _classPrivateMethodGet(this, _readChunk_raw, _readChunk_raw2).call(
  995. this,
  996. 'XML',
  997. fd,
  998. size,
  999. );
  1000. });
  1001. function _readChunk_XMP2(_x25, _x26) {
  1002. return _readChunk_XMP3.apply(this, arguments);
  1003. }
  1004. return _readChunk_XMP2;
  1005. })();
  1006. const _readChunk_Skip2 = /* #__PURE__*/ (function() {
  1007. const _readChunk_Skip3 = _asyncToGenerator(function* (fd, size) {
  1008. const buf = Buffer.alloc(size);
  1009. const discard = Buffer.alloc(1);
  1010. const {bytesRead} = yield fs.read(fd, buf, 0, size, undefined);
  1011. if (bytesRead != size) {
  1012. throw new Error('Reached end of file while skipping chunk');
  1013. }
  1014. if (size & 1) {
  1015. yield fs.read(fd, discard, 0, 1, undefined);
  1016. }
  1017. });
  1018. function _readChunk_Skip2(_x27, _x28) {
  1019. return _readChunk_Skip3.apply(this, arguments);
  1020. }
  1021. return _readChunk_Skip2;
  1022. })();
  1023. var _read2 = /* #__PURE__*/ (function() {
  1024. const _read3 = _asyncToGenerator(function* (path) {
  1025. const fd = yield fs.open(path, 'r');
  1026. const out = {};
  1027. let keepLooping = true;
  1028. let first = true;
  1029. const {fileSize} = yield _classPrivateMethodGet(
  1030. this,
  1031. _readHeader,
  1032. _readHeader2,
  1033. ).call(this, fd);
  1034. while (keepLooping) {
  1035. const {fourCC, size} = yield _classPrivateMethodGet(
  1036. this,
  1037. _readChunkHeader,
  1038. _readChunkHeader2,
  1039. ).call(this, fd);
  1040. switch (fourCC) {
  1041. case 'VP8 ':
  1042. if (!out.vp8) {
  1043. out.vp8 = yield _classPrivateMethodGet(
  1044. this,
  1045. _readChunk_VP,
  1046. _readChunk_VP2,
  1047. ).call(this, fd, size);
  1048. } else {
  1049. yield _classPrivateMethodGet(
  1050. this,
  1051. _readChunk_Skip,
  1052. _readChunk_Skip2,
  1053. ).call(this, fd, size);
  1054. }
  1055. if (first) {
  1056. out.type = constants.TYPE_LOSSY;
  1057. keepLooping = false;
  1058. }
  1059. break;
  1060. case 'VP8L':
  1061. if (!out.vp8l) {
  1062. out.vp8l = yield _classPrivateMethodGet(
  1063. this,
  1064. _readChunk_VP8L,
  1065. _readChunk_VP8L2,
  1066. ).call(this, fd, size);
  1067. } else {
  1068. yield _classPrivateMethodGet(
  1069. this,
  1070. _readChunk_Skip,
  1071. _readChunk_Skip2,
  1072. ).call(this, fd, size);
  1073. }
  1074. if (first) {
  1075. out.type = constants.TYPE_LOSSLESS;
  1076. keepLooping = false;
  1077. }
  1078. break;
  1079. case 'VP8X':
  1080. if (!out.extended) {
  1081. out.type = constants.TYPE_EXTENDED;
  1082. out.extended = yield _classPrivateMethodGet(
  1083. this,
  1084. _readChunk_VP8X,
  1085. _readChunk_VP8X2,
  1086. ).call(this, fd, size);
  1087. } else {
  1088. yield _classPrivateMethodGet(
  1089. this,
  1090. _readChunk_Skip,
  1091. _readChunk_Skip2,
  1092. ).call(this, fd, size);
  1093. }
  1094. break;
  1095. case 'ANIM':
  1096. if (!out.anim) {
  1097. const {raw, bgColor, loopCount} = yield _classPrivateMethodGet(
  1098. this,
  1099. _readChunk_ANIM,
  1100. _readChunk_ANIM2,
  1101. ).call(this, fd, size);
  1102. out.anim = {
  1103. backgroundColor: [bgColor[2], bgColor[1], bgColor[0], bgColor[3]],
  1104. loopCount,
  1105. frames: [],
  1106. };
  1107. out.anim.raw = raw;
  1108. } else {
  1109. yield _classPrivateMethodGet(
  1110. this,
  1111. _readChunk_Skip,
  1112. _readChunk_Skip2,
  1113. ).call(this, fd, size);
  1114. }
  1115. break;
  1116. case 'ANMF':
  1117. {
  1118. const f = yield _classPrivateMethodGet(
  1119. this,
  1120. _readChunk_ANMF,
  1121. _readChunk_ANMF2,
  1122. ).call(this, fd, size);
  1123. out.anim.frames.push(f);
  1124. }
  1125. break;
  1126. case 'ALPH':
  1127. if (!out.alph) {
  1128. out.alph = yield _classPrivateMethodGet(
  1129. this,
  1130. _readChunk_ALPH,
  1131. _readChunk_ALPH2,
  1132. ).call(this, fd, size);
  1133. } else {
  1134. yield _classPrivateMethodGet(
  1135. this,
  1136. _readChunk_Skip,
  1137. _readChunk_Skip2,
  1138. ).call(this, fd, size);
  1139. }
  1140. break;
  1141. case 'ICCP':
  1142. if (!out.iccp) {
  1143. out.iccp = yield _classPrivateMethodGet(
  1144. this,
  1145. _readChunk_ICCP,
  1146. _readChunk_ICCP2,
  1147. ).call(this, fd, size);
  1148. } else {
  1149. yield _classPrivateMethodGet(
  1150. this,
  1151. _readChunk_Skip,
  1152. _readChunk_Skip2,
  1153. ).call(this, fd, size);
  1154. }
  1155. break;
  1156. case 'EXIF':
  1157. if (!out.exif) {
  1158. out.exif = yield _classPrivateMethodGet(
  1159. this,
  1160. _readChunk_EXIF,
  1161. _readChunk_EXIF2,
  1162. ).call(this, fd, size);
  1163. } else {
  1164. yield _classPrivateMethodGet(
  1165. this,
  1166. _readChunk_Skip,
  1167. _readChunk_Skip2,
  1168. ).call(this, fd, size);
  1169. }
  1170. break;
  1171. case 'XMP ':
  1172. if (!out.xmp) {
  1173. out.xmp = yield _classPrivateMethodGet(
  1174. this,
  1175. _readChunk_XMP,
  1176. _readChunk_XMP2,
  1177. ).call(this, fd, size);
  1178. } else {
  1179. yield _classPrivateMethodGet(
  1180. this,
  1181. _readChunk_Skip,
  1182. _readChunk_Skip2,
  1183. ).call(this, fd, size);
  1184. }
  1185. break;
  1186. case '\x00\x00\x00\x00':
  1187. keepLooping = false;
  1188. break;
  1189. default:
  1190. yield _classPrivateMethodGet(
  1191. this,
  1192. _readChunk_Skip,
  1193. _readChunk_Skip2,
  1194. ).call(this, fd, size);
  1195. break;
  1196. }
  1197. first = false;
  1198. }
  1199. if (out.type == constants.TYPE_EXTENDED && out.extended.hasAnim) {
  1200. out.anim.frameCount = out.anim.frames.length;
  1201. }
  1202. return out;
  1203. });
  1204. function _read2(_x29) {
  1205. return _read3.apply(this, arguments);
  1206. }
  1207. return _read2;
  1208. })();
  1209. const _default = {
  1210. TYPE_LOSSY: constants.TYPE_LOSSY,
  1211. TYPE_LOSSLESS: constants.TYPE_LOSSLESS,
  1212. TYPE_EXTENDED: constants.TYPE_EXTENDED,
  1213. Image,
  1214. };
  1215. exports.default = _default;