@socketsecurity/cli-with-sentry 0.14.137 → 0.14.139

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/dist/blessed/LICENSE +20 -0
  2. package/dist/blessed/lib/alias.js +519 -0
  3. package/dist/blessed/lib/blessed.js +32 -0
  4. package/dist/blessed/lib/colors.js +490 -0
  5. package/dist/blessed/lib/events.js +195 -0
  6. package/dist/blessed/lib/gpmclient.js +245 -0
  7. package/dist/blessed/lib/helpers.js +170 -0
  8. package/dist/blessed/lib/keys.js +512 -0
  9. package/dist/blessed/lib/program.js +4530 -0
  10. package/dist/blessed/lib/tput.js +3111 -0
  11. package/dist/blessed/lib/unicode.js +912 -0
  12. package/dist/blessed/lib/widget.js +60 -0
  13. package/dist/blessed/lib/widgets/ansiimage.js +173 -0
  14. package/dist/blessed/lib/widgets/bigtext.js +170 -0
  15. package/dist/blessed/lib/widgets/box.js +34 -0
  16. package/dist/blessed/lib/widgets/button.js +62 -0
  17. package/dist/blessed/lib/widgets/checkbox.js +95 -0
  18. package/dist/blessed/lib/widgets/element.js +2871 -0
  19. package/dist/blessed/lib/widgets/filemanager.js +223 -0
  20. package/dist/blessed/lib/widgets/form.js +301 -0
  21. package/dist/blessed/lib/widgets/image.js +71 -0
  22. package/dist/blessed/lib/widgets/input.js +34 -0
  23. package/dist/blessed/lib/widgets/layout.js +249 -0
  24. package/dist/blessed/lib/widgets/line.js +59 -0
  25. package/dist/blessed/lib/widgets/list.js +652 -0
  26. package/dist/blessed/lib/widgets/listbar.js +452 -0
  27. package/dist/blessed/lib/widgets/listtable.js +265 -0
  28. package/dist/blessed/lib/widgets/loading.js +88 -0
  29. package/dist/blessed/lib/widgets/log.js +82 -0
  30. package/dist/blessed/lib/widgets/message.js +145 -0
  31. package/dist/blessed/lib/widgets/node.js +314 -0
  32. package/dist/blessed/lib/widgets/overlayimage.js +794 -0
  33. package/dist/blessed/lib/widgets/progressbar.js +166 -0
  34. package/dist/blessed/lib/widgets/prompt.js +127 -0
  35. package/dist/blessed/lib/widgets/question.js +129 -0
  36. package/dist/blessed/lib/widgets/radiobutton.js +62 -0
  37. package/dist/blessed/lib/widgets/radioset.js +36 -0
  38. package/dist/blessed/lib/widgets/screen.js +2485 -0
  39. package/dist/blessed/lib/widgets/scrollablebox.js +415 -0
  40. package/dist/blessed/lib/widgets/scrollabletext.js +35 -0
  41. package/dist/blessed/lib/widgets/table.js +383 -0
  42. package/dist/blessed/lib/widgets/terminal.js +452 -0
  43. package/dist/blessed/lib/widgets/text.js +35 -0
  44. package/dist/blessed/lib/widgets/textarea.js +376 -0
  45. package/dist/blessed/lib/widgets/textbox.js +79 -0
  46. package/dist/blessed/lib/widgets/video.js +130 -0
  47. package/dist/blessed/usr/fonts/AUTHORS +1 -0
  48. package/dist/blessed/usr/fonts/LICENSE +94 -0
  49. package/dist/blessed/usr/fonts/README +340 -0
  50. package/dist/blessed/usr/fonts/ter-u14b.json +17826 -0
  51. package/dist/blessed/usr/fonts/ter-u14n.json +17826 -0
  52. package/dist/blessed/usr/linux +0 -0
  53. package/dist/blessed/usr/windows-ansi +0 -0
  54. package/dist/blessed/usr/xterm +0 -0
  55. package/dist/blessed/usr/xterm-256color +0 -0
  56. package/dist/blessed/usr/xterm.termcap +243 -0
  57. package/dist/blessed/usr/xterm.terminfo +1977 -0
  58. package/dist/blessed/vendor/tng.js +1876 -0
  59. package/dist/blessed-contrib/LICENSE.md +21 -0
  60. package/dist/blessed-contrib/lib/layout/carousel.js +82 -0
  61. package/dist/blessed-contrib/lib/layout/grid.js +46 -0
  62. package/dist/blessed-contrib/lib/server-utils.js +83 -0
  63. package/dist/blessed-contrib/lib/utils.js +73 -0
  64. package/dist/blessed-contrib/lib/widget/canvas.js +52 -0
  65. package/dist/blessed-contrib/lib/widget/charts/bar.js +99 -0
  66. package/dist/blessed-contrib/lib/widget/charts/line.js +311 -0
  67. package/dist/blessed-contrib/lib/widget/charts/stacked-bar.js +245 -0
  68. package/dist/blessed-contrib/lib/widget/donut.js +183 -0
  69. package/dist/blessed-contrib/lib/widget/gauge-list.js +111 -0
  70. package/dist/blessed-contrib/lib/widget/gauge.js +127 -0
  71. package/dist/blessed-contrib/lib/widget/lcd.js +497 -0
  72. package/dist/blessed-contrib/lib/widget/log.js +32 -0
  73. package/dist/blessed-contrib/lib/widget/map.js +97 -0
  74. package/dist/blessed-contrib/lib/widget/markdown.js +68 -0
  75. package/dist/blessed-contrib/lib/widget/picture.js +61 -0
  76. package/dist/blessed-contrib/lib/widget/sparkline.js +66 -0
  77. package/dist/blessed-contrib/lib/widget/table.js +141 -0
  78. package/dist/blessed-contrib/lib/widget/tree.js +179 -0
  79. package/dist/blessed-contrib/node_modules/ansi-regex/index.js +6 -0
  80. package/dist/blessed-contrib/node_modules/ansi-regex/license +21 -0
  81. package/dist/blessed-contrib/node_modules/ansi-regex/package.json +64 -0
  82. package/dist/blessed-contrib/node_modules/ansi-regex/readme.md +39 -0
  83. package/dist/blessed-contrib/node_modules/ansi-styles/index.js +67 -0
  84. package/dist/blessed-contrib/node_modules/ansi-styles/license +21 -0
  85. package/dist/blessed-contrib/node_modules/ansi-styles/package.json +50 -0
  86. package/dist/blessed-contrib/node_modules/ansi-styles/readme.md +86 -0
  87. package/dist/blessed-contrib/node_modules/chalk/index.js +118 -0
  88. package/dist/blessed-contrib/node_modules/chalk/license +21 -0
  89. package/dist/blessed-contrib/node_modules/chalk/package.json +70 -0
  90. package/dist/blessed-contrib/node_modules/chalk/readme.md +213 -0
  91. package/dist/blessed-contrib/node_modules/escape-string-regexp/index.js +13 -0
  92. package/dist/blessed-contrib/node_modules/escape-string-regexp/license +21 -0
  93. package/dist/blessed-contrib/node_modules/escape-string-regexp/package.json +41 -0
  94. package/dist/blessed-contrib/node_modules/escape-string-regexp/readme.md +27 -0
  95. package/dist/blessed-contrib/node_modules/strip-ansi/index.js +8 -0
  96. package/dist/blessed-contrib/node_modules/strip-ansi/license +21 -0
  97. package/dist/blessed-contrib/node_modules/strip-ansi/package.json +57 -0
  98. package/dist/blessed-contrib/node_modules/strip-ansi/readme.md +33 -0
  99. package/dist/blessed-contrib/node_modules/supports-color/index.js +52 -0
  100. package/dist/blessed-contrib/node_modules/supports-color/license +21 -0
  101. package/dist/blessed-contrib/node_modules/supports-color/package.json +49 -0
  102. package/dist/blessed-contrib/node_modules/supports-color/readme.md +36 -0
  103. package/dist/cli.js +9 -8
  104. package/dist/cli.js.map +1 -1
  105. package/dist/instrument-with-sentry.js +2 -2
  106. package/dist/instrument-with-sentry.js.map +1 -1
  107. package/dist/shadow-npm-inject.js +2 -2
  108. package/dist/shadow-npm-inject.js.map +1 -1
  109. package/package.json +4 -4
@@ -0,0 +1,1876 @@
1
+ /**
2
+ * tng.js - png reader
3
+ * Copyright (c) 2015, Christopher Jeffrey (MIT License).
4
+ * https://github.com/chjj/tng
5
+ */
6
+
7
+ const fs = require('node:fs'),
8
+ util = require('node:util'),
9
+ path = require('node:path'),
10
+ zlib = require('node:zlib'),
11
+ assert = require('node:assert'),
12
+ cp = require('node:child_process'),
13
+ exec = cp.execFileSync
14
+
15
+ /**
16
+ * PNG
17
+ */
18
+
19
+ function PNG(file, options) {
20
+ let buf, chunks, idat, pixels
21
+
22
+ if (!(this instanceof PNG)) {
23
+ return new PNG(file, options)
24
+ }
25
+
26
+ if (!file) {
27
+ throw new Error('no file')
28
+ }
29
+
30
+ this.options = options || {}
31
+ this.colors = options.colors || require('blessed/lib/colors')
32
+ this.optimization = this.options.optimization || 'mem'
33
+ this.speed = this.options.speed || 1
34
+
35
+ if (Buffer.isBuffer(file)) {
36
+ this.file = this.options.filename || null
37
+ buf = file
38
+ } else {
39
+ this.options.filename = file
40
+ this.file = path.resolve(process.cwd(), file)
41
+ buf = fs.readFileSync(this.file)
42
+ }
43
+
44
+ this.format =
45
+ buf.readUInt32BE(0) === 0x89504e47
46
+ ? 'png'
47
+ : buf.slice(0, 3).toString('ascii') === 'GIF'
48
+ ? 'gif'
49
+ : buf.readUInt16BE(0) === 0xffd8
50
+ ? 'jpg'
51
+ : path.extname(this.file).slice(1).toLowerCase() || 'png'
52
+
53
+ if (this.format !== 'png') {
54
+ return this.toPNG(buf)
55
+ }
56
+
57
+ chunks = this.parseRaw(buf)
58
+ idat = this.parseChunks(chunks)
59
+ pixels = this.parseLines(idat)
60
+
61
+ this.bmp = this.createBitmap(pixels)
62
+ this.cellmap = this.createCellmap(this.bmp)
63
+ this.frames = this.compileFrames(this.frames)
64
+ }
65
+
66
+ PNG.prototype.parseRaw = function (buf) {
67
+ let chunks = [],
68
+ index = 0,
69
+ i = 0,
70
+ len,
71
+ type,
72
+ name,
73
+ data,
74
+ crc,
75
+ check,
76
+ critical,
77
+ public_,
78
+ conforming,
79
+ copysafe,
80
+ pos
81
+
82
+ this._debug(this.file)
83
+
84
+ if (
85
+ buf.readUInt32BE(0) !== 0x89504e47 ||
86
+ buf.readUInt32BE(4) !== 0x0d0a1a0a
87
+ ) {
88
+ throw new Error('bad header')
89
+ }
90
+
91
+ i += 8
92
+
93
+ while (i < buf.length) {
94
+ try {
95
+ len = buf.readUInt32BE(i)
96
+ i += 4
97
+ pos = i
98
+ type = buf.slice(i, i + 4)
99
+ name = type.toString('ascii')
100
+ i += 4
101
+ data = buf.slice(i, i + len)
102
+ i += len
103
+ check = this.crc32(buf.slice(pos, i))
104
+ crc = buf.readInt32BE(i)
105
+ i += 4
106
+ critical = !!(~type[0] & 32)
107
+ public_ = !!(~type[1] & 32)
108
+ conforming = !!(~type[2] & 32)
109
+ copysafe = !!(~type[3] & 32)
110
+ if (crc !== check) {
111
+ throw new Error(name + ': bad crc')
112
+ }
113
+ } catch (e) {
114
+ if (this.options.debug) {
115
+ throw e
116
+ }
117
+ break
118
+ }
119
+ chunks.push({
120
+ index: index++,
121
+ id: name.toLowerCase(),
122
+ len: len,
123
+ pos: pos,
124
+ end: i,
125
+ type: type,
126
+ name: name,
127
+ data: data,
128
+ crc: crc,
129
+ check: check,
130
+ raw: buf.slice(pos, i),
131
+ flags: {
132
+ critical: critical,
133
+ public_: public_,
134
+ conforming: conforming,
135
+ copysafe: copysafe
136
+ }
137
+ })
138
+ }
139
+
140
+ return chunks
141
+ }
142
+
143
+ PNG.prototype.parseChunks = function (chunks) {
144
+ let i, chunk, name, data, p, idat, info
145
+
146
+ for (i = 0; i < chunks.length; i++) {
147
+ chunk = chunks[i]
148
+ name = chunk.id
149
+ data = chunk.data
150
+ info = {}
151
+ switch (name) {
152
+ case 'ihdr': {
153
+ this.width = info.width = data.readUInt32BE(0)
154
+ this.height = info.height = data.readUInt32BE(4)
155
+ this.bitDepth = info.bitDepth = data.readUInt8(8)
156
+ this.colorType = info.colorType = data.readUInt8(9)
157
+ this.compression = info.compression = data.readUInt8(10)
158
+ this.filter = info.filter = data.readUInt8(11)
159
+ this.interlace = info.interlace = data.readUInt8(12)
160
+ switch (this.bitDepth) {
161
+ case 1:
162
+ case 2:
163
+ case 4:
164
+ case 8:
165
+ case 16:
166
+ case 24:
167
+ case 32:
168
+ break
169
+ default:
170
+ throw new Error('bad bit depth: ' + this.bitDepth)
171
+ }
172
+ switch (this.colorType) {
173
+ case 0:
174
+ case 2:
175
+ case 3:
176
+ case 4:
177
+ case 6:
178
+ break
179
+ default:
180
+ throw new Error('bad color: ' + this.colorType)
181
+ }
182
+ switch (this.compression) {
183
+ case 0:
184
+ break
185
+ default:
186
+ throw new Error('bad compression: ' + this.compression)
187
+ }
188
+ switch (this.filter) {
189
+ case 0:
190
+ case 1:
191
+ case 2:
192
+ case 3:
193
+ case 4:
194
+ break
195
+ default:
196
+ throw new Error('bad filter: ' + this.filter)
197
+ }
198
+ switch (this.interlace) {
199
+ case 0:
200
+ case 1:
201
+ break
202
+ default:
203
+ throw new Error('bad interlace: ' + this.interlace)
204
+ }
205
+ break
206
+ }
207
+ case 'plte': {
208
+ this.palette = info.palette = []
209
+ for (p = 0; p < data.length; p += 3) {
210
+ this.palette.push({
211
+ r: data[p + 0],
212
+ g: data[p + 1],
213
+ b: data[p + 2],
214
+ a: 255
215
+ })
216
+ }
217
+ break
218
+ }
219
+ case 'idat': {
220
+ this.size = this.size || 0
221
+ this.size += data.length
222
+ this.idat = this.idat || []
223
+ this.idat.push(data)
224
+ info.size = data.length
225
+ break
226
+ }
227
+ case 'iend': {
228
+ this.end = true
229
+ break
230
+ }
231
+ case 'trns': {
232
+ this.alpha = info.alpha = Array.prototype.slice.call(data)
233
+ if (this.palette) {
234
+ for (p = 0; p < data.length; p++) {
235
+ if (!this.palette[p]) {
236
+ break
237
+ }
238
+ this.palette[p].a = data[p]
239
+ }
240
+ }
241
+ break
242
+ }
243
+ // https://wiki.mozilla.org/APNG_Specification
244
+ case 'actl': {
245
+ this.actl = info = {}
246
+ this.frames = []
247
+ this.actl.numFrames = data.readUInt32BE(0)
248
+ this.actl.numPlays = data.readUInt32BE(4)
249
+ break
250
+ }
251
+ case 'fctl': {
252
+ // IDAT is the first frame depending on the order:
253
+ // IDAT is a frame: acTL->fcTL->IDAT->[fcTL]->fdAT
254
+ // IDAT is not a frame: acTL->IDAT->[fcTL]->fdAT
255
+ if (!this.idat) {
256
+ this.idat = []
257
+ this.frames.push({
258
+ idat: true,
259
+ fctl: info,
260
+ fdat: this.idat
261
+ })
262
+ } else {
263
+ this.frames.push({
264
+ fctl: info,
265
+ fdat: []
266
+ })
267
+ }
268
+ info.sequenceNumber = data.readUInt32BE(0)
269
+ info.width = data.readUInt32BE(4)
270
+ info.height = data.readUInt32BE(8)
271
+ info.xOffset = data.readUInt32BE(12)
272
+ info.yOffset = data.readUInt32BE(16)
273
+ info.delayNum = data.readUInt16BE(20)
274
+ info.delayDen = data.readUInt16BE(22)
275
+ info.disposeOp = data.readUInt8(24)
276
+ info.blendOp = data.readUInt8(25)
277
+ break
278
+ }
279
+ case 'fdat': {
280
+ info.sequenceNumber = data.readUInt32BE(0)
281
+ info.data = data.slice(4)
282
+ this.frames[this.frames.length - 1].fdat.push(info.data)
283
+ break
284
+ }
285
+ }
286
+ chunk.info = info
287
+ }
288
+
289
+ this._debug(chunks)
290
+
291
+ if (this.frames) {
292
+ this.frames = this.frames.map(function (frame, i) {
293
+ frame.fdat = this.decompress(frame.fdat)
294
+ if (!frame.fdat.length) {
295
+ throw new Error('no data')
296
+ }
297
+ return frame
298
+ }, this)
299
+ }
300
+
301
+ idat = this.decompress(this.idat)
302
+ if (!idat.length) {
303
+ throw new Error('no data')
304
+ }
305
+
306
+ return idat
307
+ }
308
+
309
+ PNG.prototype.parseLines = function (data) {
310
+ let pixels = [],
311
+ x,
312
+ p,
313
+ prior,
314
+ line,
315
+ filter,
316
+ samples,
317
+ pendingSamples,
318
+ ch,
319
+ shiftStart,
320
+ i,
321
+ toShift,
322
+ sample
323
+
324
+ this.sampleDepth =
325
+ this.colorType === 0
326
+ ? 1
327
+ : this.colorType === 2
328
+ ? 3
329
+ : this.colorType === 3
330
+ ? 1
331
+ : this.colorType === 4
332
+ ? 2
333
+ : this.colorType === 6
334
+ ? 4
335
+ : 1
336
+ this.bitsPerPixel = this.bitDepth * this.sampleDepth
337
+ this.bytesPerPixel = Math.ceil(this.bitsPerPixel / 8)
338
+ this.wastedBits =
339
+ (this.width * this.bitsPerPixel) / 8 -
340
+ (((this.width * this.bitsPerPixel) / 8) | 0)
341
+ this.byteWidth = Math.ceil(this.width * (this.bitsPerPixel / 8))
342
+
343
+ this.shiftStart =
344
+ (this.bitDepth + (8 / this.bitDepth - this.bitDepth) - 1) | 0
345
+ this.shiftMult = this.bitDepth >= 8 ? 0 : this.bitDepth
346
+ this.mask = this.bitDepth === 32 ? 0xffffffff : (1 << this.bitDepth) - 1
347
+
348
+ if (this.interlace === 1) {
349
+ samples = this.sampleInterlacedLines(data)
350
+ for (i = 0; i < samples.length; i += this.sampleDepth) {
351
+ pixels.push(samples.slice(i, i + this.sampleDepth))
352
+ }
353
+ return pixels
354
+ }
355
+
356
+ for (p = 0; p < data.length; p += this.byteWidth) {
357
+ prior = line || []
358
+ filter = data[p++]
359
+ line = data.slice(p, p + this.byteWidth)
360
+ line = this.unfilterLine(filter, line, prior)
361
+ samples = this.sampleLine(line)
362
+ for (i = 0; i < samples.length; i += this.sampleDepth) {
363
+ pixels.push(samples.slice(i, i + this.sampleDepth))
364
+ }
365
+ }
366
+
367
+ return pixels
368
+ }
369
+
370
+ PNG.prototype.unfilterLine = function (filter, line, prior) {
371
+ for (let x = 0; x < line.length; x++) {
372
+ if (filter === 0) {
373
+ break
374
+ } else if (filter === 1) {
375
+ line[x] = this.filters.sub(x, line, prior, this.bytesPerPixel)
376
+ } else if (filter === 2) {
377
+ line[x] = this.filters.up(x, line, prior, this.bytesPerPixel)
378
+ } else if (filter === 3) {
379
+ line[x] = this.filters.average(x, line, prior, this.bytesPerPixel)
380
+ } else if (filter === 4) {
381
+ line[x] = this.filters.paeth(x, line, prior, this.bytesPerPixel)
382
+ }
383
+ }
384
+ return line
385
+ }
386
+
387
+ PNG.prototype.sampleLine = function (line, width) {
388
+ let samples = [],
389
+ x = 0,
390
+ pendingSamples,
391
+ ch,
392
+ i,
393
+ sample,
394
+ shiftStart,
395
+ toShift
396
+
397
+ while (x < line.length) {
398
+ pendingSamples = this.sampleDepth
399
+ while (pendingSamples--) {
400
+ ch = line[x]
401
+ if (this.bitDepth === 16) {
402
+ ch = (ch << 8) | line[++x]
403
+ } else if (this.bitDepth === 24) {
404
+ ch = (ch << 16) | (line[++x] << 8) | line[++x]
405
+ } else if (this.bitDepth === 32) {
406
+ ch = (ch << 24) | (line[++x] << 16) | (line[++x] << 8) | line[++x]
407
+ } else if (this.bitDepth > 32) {
408
+ throw new Error('bitDepth ' + this.bitDepth + ' unsupported.')
409
+ }
410
+ shiftStart = this.shiftStart
411
+ toShift = shiftStart - (x === line.length - 1 ? this.wastedBits : 0)
412
+ for (i = 0; i <= toShift; i++) {
413
+ sample = (ch >> (this.shiftMult * shiftStart)) & this.mask
414
+ if (this.colorType !== 3) {
415
+ if (this.bitDepth < 8) {
416
+ // <= 8 would work too, doesn't matter
417
+ // sample = sample * (0xff / this.mask) | 0; // would work too
418
+ sample *= 0xff / this.mask
419
+ sample |= 0
420
+ } else if (this.bitDepth > 8) {
421
+ sample = ((sample / this.mask) * 255) | 0
422
+ }
423
+ }
424
+ samples.push(sample)
425
+ shiftStart--
426
+ }
427
+ x++
428
+ }
429
+ }
430
+
431
+ // Needed for deinterlacing?
432
+ if (width != null) {
433
+ samples = samples.slice(0, width * this.sampleDepth)
434
+ }
435
+
436
+ return samples
437
+ }
438
+
439
+ // http://www.w3.org/TR/PNG-Filters.html
440
+ PNG.prototype.filters = {
441
+ sub: function Sub(x, line, prior, bpp) {
442
+ if (x < bpp) {
443
+ return line[x]
444
+ }
445
+ return (line[x] + line[x - bpp]) % 256
446
+ },
447
+ up: function Up(x, line, prior, bpp) {
448
+ return (line[x] + (prior[x] || 0)) % 256
449
+ },
450
+ average: function Average(x, line, prior, bpp) {
451
+ if (x < bpp) {
452
+ return Math.floor((prior[x] || 0) / 2)
453
+ }
454
+ // if (x < bpp) return (prior[x] || 0) >> 1;
455
+ return (
456
+ (line[x] + Math.floor((line[x - bpp] + prior[x]) / 2)) %
457
+ // + ((line[x - bpp] + prior[x]) >> 1)
458
+ 256
459
+ )
460
+ },
461
+ paeth: function Paeth(x, line, prior, bpp) {
462
+ if (x < bpp) {
463
+ return prior[x] || 0
464
+ }
465
+ return (
466
+ (line[x] +
467
+ this._predictor(line[x - bpp], prior[x] || 0, prior[x - bpp] || 0)) %
468
+ 256
469
+ )
470
+ },
471
+ _predictor: function PaethPredictor(a, b, c) {
472
+ // a = left, b = above, c = upper left
473
+ const p = a + b - c,
474
+ pa = Math.abs(p - a),
475
+ pb = Math.abs(p - b),
476
+ pc = Math.abs(p - c)
477
+ if (pa <= pb && pa <= pc) {
478
+ return a
479
+ }
480
+ if (pb <= pc) {
481
+ return b
482
+ }
483
+ return c
484
+ }
485
+ }
486
+
487
+ /**
488
+ * Adam7 deinterlacing ported to javascript from PyPNG:
489
+ * pypng - Pure Python library for PNG image encoding/decoding
490
+ * Copyright (c) 2009-2015, David Jones (MIT License).
491
+ * https://github.com/drj11/pypng
492
+ *
493
+ * Permission is hereby granted, free of charge, to any person
494
+ * obtaining a copy of this software and associated documentation files
495
+ * (the "Software"), to deal in the Software without restriction,
496
+ * including without limitation the rights to use, copy, modify, merge,
497
+ * publish, distribute, sublicense, and/or sell copies of the Software,
498
+ * and to permit persons to whom the Software is furnished to do so,
499
+ * subject to the following conditions:
500
+ *
501
+ * The above copyright notice and this permission notice shall be
502
+ * included in all copies or substantial portions of the Software.
503
+ *
504
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
505
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
506
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
507
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
508
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
509
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
510
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
511
+ * SOFTWARE.
512
+ */
513
+
514
+ PNG.prototype.sampleInterlacedLines = function (raw) {
515
+ let psize,
516
+ vpr,
517
+ samples,
518
+ source_offset,
519
+ i,
520
+ pass,
521
+ xstart,
522
+ ystart,
523
+ xstep,
524
+ ystep,
525
+ recon,
526
+ ppr,
527
+ row_size,
528
+ y,
529
+ filter_type,
530
+ scanline,
531
+ flat,
532
+ offset,
533
+ end_offset,
534
+ skip,
535
+ j,
536
+ k,
537
+ f
538
+
539
+ const adam7 = [
540
+ [0, 0, 8, 8],
541
+ [4, 0, 8, 8],
542
+ [0, 4, 4, 8],
543
+ [2, 0, 4, 4],
544
+ [0, 2, 2, 4],
545
+ [1, 0, 2, 2],
546
+ [0, 1, 1, 2]
547
+ ]
548
+
549
+ // Fractional bytes per pixel
550
+ psize = (this.bitDepth / 8) * this.sampleDepth
551
+
552
+ // Values per row (of the target image)
553
+ vpr = this.width * this.sampleDepth
554
+
555
+ // Make a result array, and make it big enough. Interleaving
556
+ // writes to the output array randomly (well, not quite), so the
557
+ // entire output array must be in memory.
558
+ samples = new Buffer(vpr * this.height)
559
+ samples.fill(0)
560
+
561
+ source_offset = 0
562
+
563
+ for (i = 0; i < adam7.length; i++) {
564
+ pass = adam7[i]
565
+ xstart = pass[0]
566
+ ystart = pass[1]
567
+ xstep = pass[2]
568
+ ystep = pass[3]
569
+ if (xstart >= this.width) {
570
+ continue
571
+ }
572
+ // The previous (reconstructed) scanline. Empty array at the
573
+ // beginning of a pass to indicate that there is no previous
574
+ // line.
575
+ recon = []
576
+ // Pixels per row (reduced pass image)
577
+ ppr = Math.ceil((this.width - xstart) / xstep)
578
+ // Row size in bytes for this pass.
579
+ row_size = Math.ceil(psize * ppr)
580
+ for (y = ystart; y < this.height; y += ystep) {
581
+ filter_type = raw[source_offset]
582
+ source_offset += 1
583
+ scanline = raw.slice(source_offset, source_offset + row_size)
584
+ source_offset += row_size
585
+ recon = this.unfilterLine(filter_type, scanline, recon)
586
+ // Convert so that there is one element per pixel value
587
+ flat = this.sampleLine(recon, ppr)
588
+ if (xstep === 1) {
589
+ assert.equal(xstart, 0)
590
+ offset = y * vpr
591
+ for (k = offset, f = 0; k < offset + vpr; k++, f++) {
592
+ samples[k] = flat[f]
593
+ }
594
+ } else {
595
+ offset = y * vpr + xstart * this.sampleDepth
596
+ end_offset = (y + 1) * vpr
597
+ skip = this.sampleDepth * xstep
598
+ for (j = 0; j < this.sampleDepth; j++) {
599
+ for (
600
+ k = offset + j, f = j;
601
+ k < end_offset;
602
+ k += skip, f += this.sampleDepth
603
+ ) {
604
+ samples[k] = flat[f]
605
+ }
606
+ }
607
+ }
608
+ }
609
+ }
610
+
611
+ return samples
612
+ }
613
+
614
+ PNG.prototype.createBitmap = function (pixels) {
615
+ let bmp = [],
616
+ i
617
+
618
+ if (this.colorType === 0) {
619
+ pixels = pixels.map(function (sample) {
620
+ return { r: sample[0], g: sample[0], b: sample[0], a: 255 }
621
+ })
622
+ } else if (this.colorType === 2) {
623
+ pixels = pixels.map(function (sample) {
624
+ return { r: sample[0], g: sample[1], b: sample[2], a: 255 }
625
+ })
626
+ } else if (this.colorType === 3) {
627
+ pixels = pixels.map(function (sample) {
628
+ if (!this.palette[sample[0]]) {
629
+ throw new Error('bad palette index')
630
+ }
631
+ return this.palette[sample[0]]
632
+ }, this)
633
+ } else if (this.colorType === 4) {
634
+ pixels = pixels.map(function (sample) {
635
+ return { r: sample[0], g: sample[0], b: sample[0], a: sample[1] }
636
+ })
637
+ } else if (this.colorType === 6) {
638
+ pixels = pixels.map(function (sample) {
639
+ return { r: sample[0], g: sample[1], b: sample[2], a: sample[3] }
640
+ })
641
+ }
642
+
643
+ for (i = 0; i < pixels.length; i += this.width) {
644
+ bmp.push(pixels.slice(i, i + this.width))
645
+ }
646
+
647
+ return bmp
648
+ }
649
+
650
+ PNG.prototype.createCellmap = function (bmp, options) {
651
+ bmp = bmp || this.bmp
652
+ options = options || this.options
653
+ let cellmap = [],
654
+ scale = options.scale || 0.2,
655
+ height = bmp.length,
656
+ width = bmp[0].length,
657
+ cmwidth = options.width,
658
+ cmheight = options.height,
659
+ line,
660
+ x,
661
+ y,
662
+ xx,
663
+ yy,
664
+ xs,
665
+ ys
666
+
667
+ if (cmwidth) {
668
+ scale = cmwidth / width
669
+ } else if (cmheight) {
670
+ scale = cmheight / height
671
+ }
672
+
673
+ if (!cmheight) {
674
+ cmheight = Math.round(height * scale)
675
+ }
676
+
677
+ if (!cmwidth) {
678
+ cmwidth = Math.round(width * scale)
679
+ }
680
+
681
+ ys = height / cmheight
682
+ xs = width / cmwidth
683
+
684
+ for (y = 0; y < bmp.length; y += ys) {
685
+ line = []
686
+ yy = Math.round(y)
687
+ if (!bmp[yy]) {
688
+ break
689
+ }
690
+ for (x = 0; x < bmp[yy].length; x += xs) {
691
+ xx = Math.round(x)
692
+ if (!bmp[yy][xx]) {
693
+ break
694
+ }
695
+ line.push(bmp[yy][xx])
696
+ }
697
+ cellmap.push(line)
698
+ }
699
+
700
+ return cellmap
701
+ }
702
+
703
+ PNG.prototype.renderANSI = function (bmp) {
704
+ let self = this,
705
+ out = ''
706
+
707
+ bmp.forEach(function (line, y) {
708
+ line.forEach(function (pixel, x) {
709
+ const outch = self.getOutch(x, y, line, pixel)
710
+ out += self.pixelToSGR(pixel, outch)
711
+ })
712
+ out += '\n'
713
+ })
714
+
715
+ return out
716
+ }
717
+
718
+ PNG.prototype.renderContent = function (bmp, el) {
719
+ let self = this,
720
+ out = ''
721
+
722
+ bmp.forEach(function (line, y) {
723
+ line.forEach(function (pixel, x) {
724
+ const outch = self.getOutch(x, y, line, pixel)
725
+ out += self.pixelToTags(pixel, outch)
726
+ })
727
+ out += '\n'
728
+ })
729
+
730
+ el.setContent(out)
731
+
732
+ return out
733
+ }
734
+
735
+ PNG.prototype.renderScreen = function (bmp, screen, xi, xl, yi, yl) {
736
+ let self = this,
737
+ lines = screen.lines,
738
+ cellLines,
739
+ y,
740
+ yy,
741
+ x,
742
+ xx,
743
+ alpha,
744
+ attr,
745
+ ch
746
+
747
+ cellLines = bmp.reduce(function (cellLines, line, y) {
748
+ const cellLine = []
749
+ line.forEach(function (pixel, x) {
750
+ const outch = self.getOutch(x, y, line, pixel),
751
+ cell = self.pixelToCell(pixel, outch)
752
+ cellLine.push(cell)
753
+ })
754
+ cellLines.push(cellLine)
755
+ return cellLines
756
+ }, [])
757
+
758
+ for (y = yi; y < yl; y++) {
759
+ yy = y - yi
760
+ for (x = xi; x < xl; x++) {
761
+ xx = x - xi
762
+ if (lines[y] && lines[y][x] && cellLines[yy] && cellLines[yy][xx]) {
763
+ alpha = cellLines[yy][xx].pop()
764
+ // completely transparent
765
+ if (alpha === 0.0) {
766
+ continue
767
+ }
768
+ // translucency / blending
769
+ if (alpha < 1.0) {
770
+ attr = cellLines[yy][xx][0]
771
+ ch = cellLines[yy][xx][1]
772
+ lines[y][x][0] = this.colors.blend(lines[y][x][0], attr, alpha)
773
+ if (ch !== ' ') {
774
+ lines[y][x][1] = ch
775
+ }
776
+ lines[y].dirty = true
777
+ continue
778
+ }
779
+ // completely opaque
780
+ lines[y][x] = cellLines[yy][xx]
781
+ lines[y].dirty = true
782
+ }
783
+ }
784
+ }
785
+ }
786
+
787
+ PNG.prototype.renderElement = function (bmp, el) {
788
+ const xi = el.aleft + el.ileft,
789
+ xl = el.aleft + el.width - el.iright,
790
+ yi = el.atop + el.itop,
791
+ yl = el.atop + el.height - el.ibottom
792
+
793
+ return this.renderScreen(bmp, el.screen, xi, xl, yi, yl)
794
+ }
795
+
796
+ PNG.prototype.pixelToSGR = function (pixel, ch) {
797
+ let bga = 1.0,
798
+ fga = 0.5,
799
+ a = pixel.a / 255,
800
+ bg,
801
+ fg
802
+
803
+ bg = this.colors.match(
804
+ (pixel.r * a * bga) | 0,
805
+ (pixel.g * a * bga) | 0,
806
+ (pixel.b * a * bga) | 0
807
+ )
808
+
809
+ if (ch && this.options.ascii) {
810
+ fg = this.colors.match(
811
+ (pixel.r * a * fga) | 0,
812
+ (pixel.g * a * fga) | 0,
813
+ (pixel.b * a * fga) | 0
814
+ )
815
+ if (a === 0) {
816
+ return '\x1b[38;5;' + fg + 'm' + ch + '\x1b[m'
817
+ }
818
+ return '\x1b[38;5;' + fg + 'm\x1b[48;5;' + bg + 'm' + ch + '\x1b[m'
819
+ }
820
+
821
+ if (a === 0) {
822
+ return ' '
823
+ }
824
+
825
+ return '\x1b[48;5;' + bg + 'm \x1b[m'
826
+ }
827
+
828
+ PNG.prototype.pixelToTags = function (pixel, ch) {
829
+ let bga = 1.0,
830
+ fga = 0.5,
831
+ a = pixel.a / 255,
832
+ bg,
833
+ fg
834
+
835
+ bg = this.colors.RGBtoHex(
836
+ (pixel.r * a * bga) | 0,
837
+ (pixel.g * a * bga) | 0,
838
+ (pixel.b * a * bga) | 0
839
+ )
840
+
841
+ if (ch && this.options.ascii) {
842
+ fg = this.colors.RGBtoHex(
843
+ (pixel.r * a * fga) | 0,
844
+ (pixel.g * a * fga) | 0,
845
+ (pixel.b * a * fga) | 0
846
+ )
847
+ if (a === 0) {
848
+ return '{' + fg + '-fg}' + ch + '{/}'
849
+ }
850
+ return '{' + fg + '-fg}{' + bg + '-bg}' + ch + '{/}'
851
+ }
852
+
853
+ if (a === 0) {
854
+ return ' '
855
+ }
856
+
857
+ return '{' + bg + '-bg} {/' + bg + '-bg}'
858
+ }
859
+
860
+ PNG.prototype.pixelToCell = function (pixel, ch) {
861
+ let bga = 1.0,
862
+ fga = 0.5,
863
+ a = pixel.a / 255,
864
+ bg,
865
+ fg
866
+
867
+ bg = this.colors.match(
868
+ (pixel.r * bga) | 0,
869
+ (pixel.g * bga) | 0,
870
+ (pixel.b * bga) | 0
871
+ )
872
+
873
+ if (ch && this.options.ascii) {
874
+ fg = this.colors.match(
875
+ (pixel.r * fga) | 0,
876
+ (pixel.g * fga) | 0,
877
+ (pixel.b * fga) | 0
878
+ )
879
+ } else {
880
+ fg = 0x1ff
881
+ ch = null
882
+ }
883
+
884
+ // if (a === 0) bg = 0x1ff;
885
+
886
+ return [(0 << 18) | (fg << 9) | (bg << 0), ch || ' ', a]
887
+ }
888
+
889
+ // Taken from libcaca:
890
+ PNG.prototype.getOutch = (function () {
891
+ const dchars = "????8@8@#8@8##8#MKXWwz$&%x><\\/xo;+=|^-:i'.`, `. "
892
+
893
+ const luminance = function (pixel) {
894
+ const a = pixel.a / 255,
895
+ r = pixel.r * a,
896
+ g = pixel.g * a,
897
+ b = pixel.b * a,
898
+ l = 0.2126 * r + 0.7152 * g + 0.0722 * b
899
+
900
+ return l / 255
901
+ }
902
+
903
+ return function (x, y, line, pixel) {
904
+ const lumi = luminance(pixel),
905
+ outch = dchars[(lumi * (dchars.length - 1)) | 0]
906
+
907
+ return outch
908
+ }
909
+ })()
910
+
911
+ PNG.prototype.compileFrames = function (frames) {
912
+ return this.optimization === 'mem'
913
+ ? this.compileFrames_lomem(frames)
914
+ : this.compileFrames_locpu(frames)
915
+ }
916
+
917
+ PNG.prototype.compileFrames_lomem = function (frames) {
918
+ if (!this.actl) {
919
+ return
920
+ }
921
+ return frames.map(function (frame, i) {
922
+ this.width = frame.fctl.width
923
+ this.height = frame.fctl.height
924
+
925
+ const pixels = frame._pixels || this.parseLines(frame.fdat),
926
+ bmp = frame._bmp || this.createBitmap(pixels),
927
+ fc = frame.fctl
928
+
929
+ return {
930
+ actl: this.actl,
931
+ fctl: frame.fctl,
932
+ delay: ((fc.delayNum / (fc.delayDen || 100)) * 1000) | 0,
933
+ bmp: bmp
934
+ }
935
+ }, this)
936
+ }
937
+
938
+ PNG.prototype.compileFrames_locpu = function (frames) {
939
+ if (!this.actl) {
940
+ return
941
+ }
942
+
943
+ this._curBmp = null
944
+ this._lastBmp = null
945
+
946
+ return frames.map(function (frame, i) {
947
+ this.width = frame.fctl.width
948
+ this.height = frame.fctl.height
949
+
950
+ const pixels = frame._pixels || this.parseLines(frame.fdat),
951
+ bmp = frame._bmp || this.createBitmap(pixels),
952
+ renderBmp = this.renderFrame(bmp, frame, i),
953
+ cellmap = this.createCellmap(renderBmp),
954
+ fc = frame.fctl
955
+
956
+ return {
957
+ actl: this.actl,
958
+ fctl: frame.fctl,
959
+ delay: ((fc.delayNum / (fc.delayDen || 100)) * 1000) | 0,
960
+ bmp: renderBmp,
961
+ cellmap: cellmap
962
+ }
963
+ }, this)
964
+ }
965
+
966
+ PNG.prototype.renderFrame = function (bmp, frame, i) {
967
+ let first = this.frames[0],
968
+ last = this.frames[i - 1],
969
+ fc = frame.fctl,
970
+ xo = fc.xOffset,
971
+ yo = fc.yOffset,
972
+ lxo,
973
+ lyo,
974
+ x,
975
+ y,
976
+ line,
977
+ p
978
+
979
+ if (!this._curBmp) {
980
+ this._curBmp = []
981
+ for (y = 0; y < first.fctl.height; y++) {
982
+ line = []
983
+ for (x = 0; x < first.fctl.width; x++) {
984
+ p = bmp[y][x]
985
+ line.push({ r: p.r, g: p.g, b: p.b, a: p.a })
986
+ }
987
+ this._curBmp.push(line)
988
+ }
989
+ }
990
+
991
+ if (last && last.fctl.disposeOp !== 0) {
992
+ lxo = last.fctl.xOffset
993
+ lyo = last.fctl.yOffset
994
+ for (y = 0; y < last.fctl.height; y++) {
995
+ for (x = 0; x < last.fctl.width; x++) {
996
+ if (last.fctl.disposeOp === 0) {
997
+ // none / keep
998
+ } else if (last.fctl.disposeOp === 1) {
999
+ // background / clear
1000
+ this._curBmp[lyo + y][lxo + x] = { r: 0, g: 0, b: 0, a: 0 }
1001
+ } else if (last.fctl.disposeOp === 2) {
1002
+ // previous / restore
1003
+ p = this._lastBmp[y][x]
1004
+ this._curBmp[lyo + y][lxo + x] = { r: p.r, g: p.g, b: p.b, a: p.a }
1005
+ }
1006
+ }
1007
+ }
1008
+ }
1009
+
1010
+ if (frame.fctl.disposeOp === 2) {
1011
+ this._lastBmp = []
1012
+ for (y = 0; y < frame.fctl.height; y++) {
1013
+ line = []
1014
+ for (x = 0; x < frame.fctl.width; x++) {
1015
+ p = this._curBmp[yo + y][xo + x]
1016
+ line.push({ r: p.r, g: p.g, b: p.b, a: p.a })
1017
+ }
1018
+ this._lastBmp.push(line)
1019
+ }
1020
+ } else {
1021
+ this._lastBmp = null
1022
+ }
1023
+
1024
+ for (y = 0; y < frame.fctl.height; y++) {
1025
+ for (x = 0; x < frame.fctl.width; x++) {
1026
+ p = bmp[y][x]
1027
+ if (fc.blendOp === 0) {
1028
+ // source
1029
+ this._curBmp[yo + y][xo + x] = { r: p.r, g: p.g, b: p.b, a: p.a }
1030
+ } else if (fc.blendOp === 1) {
1031
+ // over
1032
+ if (p.a !== 0) {
1033
+ this._curBmp[yo + y][xo + x] = { r: p.r, g: p.g, b: p.b, a: p.a }
1034
+ }
1035
+ }
1036
+ }
1037
+ }
1038
+
1039
+ return this._curBmp
1040
+ }
1041
+
1042
+ PNG.prototype._animate = function (callback) {
1043
+ if (!this.frames) {
1044
+ return callback(this.bmp, this.cellmap)
1045
+ }
1046
+
1047
+ let self = this,
1048
+ numPlays = this.actl.numPlays || Infinity,
1049
+ running = 0,
1050
+ i = -1
1051
+
1052
+ this._curBmp = null
1053
+ this._lastBmp = null
1054
+
1055
+ const next_lomem = function () {
1056
+ if (!running) {
1057
+ return
1058
+ }
1059
+
1060
+ const frame = self.frames[++i]
1061
+ if (!frame) {
1062
+ if (!--numPlays) {
1063
+ return callback()
1064
+ }
1065
+ i = -1
1066
+ // XXX may be able to optimize by only setting the self._curBmp once???
1067
+ self._curBmp = null
1068
+ self._lastBmp = null
1069
+ return setImmediate(next)
1070
+ }
1071
+
1072
+ const bmp = frame.bmp,
1073
+ renderBmp = self.renderFrame(bmp, frame, i),
1074
+ cellmap = self.createCellmap(renderBmp)
1075
+
1076
+ callback(renderBmp, cellmap)
1077
+ return setTimeout(next, (frame.delay / self.speed) | 0)
1078
+ }
1079
+
1080
+ const next_locpu = function () {
1081
+ if (!running) {
1082
+ return
1083
+ }
1084
+ const frame = self.frames[++i]
1085
+ if (!frame) {
1086
+ if (!--numPlays) {
1087
+ return callback()
1088
+ }
1089
+ i = -1
1090
+ return setImmediate(next)
1091
+ }
1092
+ callback(frame.bmp, frame.cellmap)
1093
+ return setTimeout(next, (frame.delay / self.speed) | 0)
1094
+ }
1095
+
1096
+ const next = this.optimization === 'mem' ? next_lomem : next_locpu
1097
+
1098
+ this._control = function (state) {
1099
+ if (state === -1) {
1100
+ i = -1
1101
+ self._curBmp = null
1102
+ self._lastBmp = null
1103
+ running = 0
1104
+ callback(
1105
+ self.frames[0].bmp,
1106
+ self.frames[0].cellmap || self.createCellmap(self.frames[0].bmp)
1107
+ )
1108
+ return
1109
+ }
1110
+ if (state === running) {
1111
+ return
1112
+ }
1113
+ running = state
1114
+ return next()
1115
+ }
1116
+
1117
+ this._control(1)
1118
+ }
1119
+
1120
+ PNG.prototype.play = function (callback) {
1121
+ if (!this._control || callback) {
1122
+ this.stop()
1123
+ return this._animate(callback)
1124
+ }
1125
+ this._control(1)
1126
+ }
1127
+
1128
+ PNG.prototype.pause = function () {
1129
+ if (!this._control) {
1130
+ return
1131
+ }
1132
+ this._control(0)
1133
+ }
1134
+
1135
+ PNG.prototype.stop = function () {
1136
+ if (!this._control) {
1137
+ return
1138
+ }
1139
+ this._control(-1)
1140
+ }
1141
+
1142
+ PNG.prototype.toPNG = function (input) {
1143
+ let options = this.options,
1144
+ file = this.file,
1145
+ format = this.format,
1146
+ buf,
1147
+ img,
1148
+ gif,
1149
+ i,
1150
+ control,
1151
+ disposeOp
1152
+
1153
+ if (format !== 'gif') {
1154
+ buf = exec('convert', [format + ':-', 'png:-'], {
1155
+ stdio: ['pipe', 'pipe', 'ignore'],
1156
+ input: input
1157
+ })
1158
+ img = PNG(buf, options)
1159
+ img.file = file
1160
+ return img
1161
+ }
1162
+
1163
+ gif = GIF(input, options)
1164
+
1165
+ this.width = gif.width
1166
+ this.height = gif.height
1167
+ this.frames = []
1168
+
1169
+ for (i = 0; i < gif.images.length; i++) {
1170
+ img = gif.images[i]
1171
+ // Convert from gif disposal to png disposal. See:
1172
+ // http://www.w3.org/Graphics/GIF/spec-gif89a.txt
1173
+ control = img.control || gif
1174
+ disposeOp = Math.max(0, (control.disposeMethod || 0) - 1)
1175
+ if (disposeOp > 2) {
1176
+ disposeOp = 0
1177
+ }
1178
+ this.frames.push({
1179
+ fctl: {
1180
+ sequenceNumber: i,
1181
+ width: img.width,
1182
+ height: img.height,
1183
+ xOffset: img.left,
1184
+ yOffset: img.top,
1185
+ delayNum: control.delay,
1186
+ delayDen: 100,
1187
+ disposeOp: disposeOp,
1188
+ blendOp: 1
1189
+ },
1190
+ fdat: [],
1191
+ _pixels: [],
1192
+ _bmp: img.bmp
1193
+ })
1194
+ }
1195
+
1196
+ this.bmp = this.frames[0]._bmp
1197
+ this.cellmap = this.createCellmap(this.bmp)
1198
+
1199
+ if (this.frames.length > 1) {
1200
+ this.actl = { numFrames: gif.images.length, numPlays: gif.numPlays || 0 }
1201
+ this.frames = this.compileFrames(this.frames)
1202
+ } else {
1203
+ this.frames = undefined
1204
+ }
1205
+
1206
+ return this
1207
+ }
1208
+
1209
+ // Convert a gif to an apng using imagemagick. Unfortunately imagemagick
1210
+ // doesn't support apngs, so we coalesce the gif frames into one image and then
1211
+ // slice them into frames.
1212
+ PNG.prototype.gifMagick = function (input) {
1213
+ let options = this.options,
1214
+ file = this.file,
1215
+ format = this.format,
1216
+ buf,
1217
+ fmt,
1218
+ img,
1219
+ frames,
1220
+ frame,
1221
+ width,
1222
+ height,
1223
+ iwidth,
1224
+ twidth,
1225
+ i,
1226
+ lines,
1227
+ line,
1228
+ x,
1229
+ y
1230
+
1231
+ buf = exec('convert', [format + ':-', '-coalesce', '+append', 'png:-'], {
1232
+ stdio: ['pipe', 'pipe', 'ignore'],
1233
+ input: input
1234
+ })
1235
+
1236
+ fmt = '{"W":%W,"H":%H,"w":%w,"h":%h,"d":%T,"x":"%X","y":"%Y"},'
1237
+ frames = exec('identify', ['-format', fmt, format + ':-'], {
1238
+ encoding: 'utf8',
1239
+ stdio: ['pipe', 'pipe', 'ignore'],
1240
+ input: input
1241
+ })
1242
+ frames = JSON.parse('[' + frames.trim().slice(0, -1) + ']')
1243
+
1244
+ img = PNG(buf, options)
1245
+ img.file = file
1246
+ Object.keys(img).forEach(function (key) {
1247
+ this[key] = img[key]
1248
+ }, this)
1249
+
1250
+ width = frames[0].W
1251
+ height = frames[0].H
1252
+ iwidth = 0
1253
+ twidth = 0
1254
+
1255
+ this.width = width
1256
+ this.height = height
1257
+
1258
+ this.frames = []
1259
+
1260
+ for (i = 0; i < frames.length; i++) {
1261
+ frame = frames[i]
1262
+ frame.x = +frame.x
1263
+ frame.y = +frame.y
1264
+
1265
+ iwidth = twidth
1266
+ twidth += width
1267
+
1268
+ lines = []
1269
+ for (y = frame.y; y < height; y++) {
1270
+ line = []
1271
+ for (x = iwidth + frame.x; x < twidth; x++) {
1272
+ line.push(img.bmp[y][x])
1273
+ }
1274
+ lines.push(line)
1275
+ }
1276
+
1277
+ this.frames.push({
1278
+ fctl: {
1279
+ sequenceNumber: i,
1280
+ width: frame.w,
1281
+ height: frame.h,
1282
+ xOffset: frame.x,
1283
+ yOffset: frame.y,
1284
+ delayNum: frame.d,
1285
+ delayDen: 100,
1286
+ disposeOp: 0,
1287
+ blendOp: 0
1288
+ },
1289
+ fdat: [],
1290
+ _pixels: [],
1291
+ _bmp: lines
1292
+ })
1293
+ }
1294
+
1295
+ this.bmp = this.frames[0]._bmp
1296
+ this.cellmap = this.createCellmap(this.bmp)
1297
+
1298
+ if (this.frames.length > 1) {
1299
+ this.actl = { numFrames: frames.length, numPlays: 0 }
1300
+ this.frames = this.compileFrames(this.frames)
1301
+ } else {
1302
+ this.frames = undefined
1303
+ }
1304
+
1305
+ return this
1306
+ }
1307
+
1308
+ PNG.prototype.decompress = function (buffers) {
1309
+ return zlib.inflateSync(
1310
+ new Buffer(
1311
+ buffers.reduce(function (out, data) {
1312
+ return out.concat(Array.prototype.slice.call(data))
1313
+ }, [])
1314
+ )
1315
+ )
1316
+ }
1317
+
1318
+ /**
1319
+ * node-crc
1320
+ * https://github.com/alexgorbatchev/node-crc
1321
+ * https://github.com/alexgorbatchev/node-crc/blob/master/LICENSE
1322
+ *
1323
+ * The MIT License (MIT)
1324
+ *
1325
+ * Copyright 2014 Alex Gorbatchev
1326
+ *
1327
+ * Permission is hereby granted, free of charge, to any person obtaining
1328
+ * a copy of this software and associated documentation files (the
1329
+ * "Software"), to deal in the Software without restriction, including
1330
+ * without limitation the rights to use, copy, modify, merge, publish,
1331
+ * distribute, sublicense, and/or sell copies of the Software, and to
1332
+ * permit persons to whom the Software is furnished to do so, subject to
1333
+ * the following conditions:
1334
+ *
1335
+ * The above copyright notice and this permission notice shall be
1336
+ * included in all copies or substantial portions of the Software.
1337
+ *
1338
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1339
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1340
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1341
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
1342
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
1343
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
1344
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1345
+ */
1346
+
1347
+ PNG.prototype.crc32 = (function () {
1348
+ const crcTable = [
1349
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
1350
+ 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
1351
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
1352
+ 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
1353
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
1354
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
1355
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
1356
+ 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
1357
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
1358
+ 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
1359
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
1360
+ 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
1361
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
1362
+ 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
1363
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
1364
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
1365
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
1366
+ 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
1367
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
1368
+ 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
1369
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
1370
+ 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
1371
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
1372
+ 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
1373
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
1374
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
1375
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
1376
+ 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
1377
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
1378
+ 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
1379
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
1380
+ 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
1381
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
1382
+ 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
1383
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
1384
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
1385
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
1386
+ 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
1387
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
1388
+ 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
1389
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
1390
+ 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
1391
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
1392
+ ]
1393
+
1394
+ return function crc32(buf) {
1395
+ //var crc = previous === 0 ? 0 : ~~previous ^ -1;
1396
+ let crc = -1
1397
+ for (let i = 0, len = buf.length; i < len; i++) {
1398
+ crc = crcTable[(crc ^ buf[i]) & 0xff] ^ (crc >>> 8)
1399
+ }
1400
+ return crc ^ -1
1401
+ }
1402
+ })()
1403
+
1404
+ PNG.prototype._debug = function () {
1405
+ if (!this.options.log) {
1406
+ return
1407
+ }
1408
+ return this.options.log.apply(null, arguments)
1409
+ }
1410
+
1411
+ /**
1412
+ * GIF
1413
+ */
1414
+
1415
+ function GIF(file, options) {
1416
+ const self = this
1417
+
1418
+ if (!(this instanceof GIF)) {
1419
+ return new GIF(file, options)
1420
+ }
1421
+
1422
+ let info = {},
1423
+ p = 0,
1424
+ buf,
1425
+ i,
1426
+ total,
1427
+ sig,
1428
+ desc,
1429
+ img,
1430
+ ext,
1431
+ label,
1432
+ size
1433
+
1434
+ if (!file) {
1435
+ throw new Error('no file')
1436
+ }
1437
+
1438
+ options = options || {}
1439
+
1440
+ this.options = options
1441
+
1442
+ // XXX If the gif is not optimized enough
1443
+ // it may OOM the process with too many frames.
1444
+ // TODO: Implement in PNG reader.
1445
+ this.pixelLimit = this.options.pixelLimit || 7622550
1446
+ this.totalPixels = 0
1447
+
1448
+ if (Buffer.isBuffer(file)) {
1449
+ buf = file
1450
+ file = null
1451
+ } else {
1452
+ file = path.resolve(process.cwd(), file)
1453
+ buf = fs.readFileSync(file)
1454
+ }
1455
+
1456
+ sig = buf.slice(0, 6).toString('ascii')
1457
+ if (sig !== 'GIF87a' && sig !== 'GIF89a') {
1458
+ throw new Error('bad header: ' + sig)
1459
+ }
1460
+
1461
+ this.width = buf.readUInt16LE(6)
1462
+ this.height = buf.readUInt16LE(8)
1463
+
1464
+ this.flags = buf.readUInt8(10)
1465
+ this.gct = !!(this.flags & 0x80)
1466
+ this.gctsize = (this.flags & 0x07) + 1
1467
+
1468
+ this.bgIndex = buf.readUInt8(11)
1469
+ this.aspect = buf.readUInt8(12)
1470
+ p += 13
1471
+
1472
+ if (this.gct) {
1473
+ this.colors = []
1474
+ total = 1 << this.gctsize
1475
+ for (i = 0; i < total; i++, p += 3) {
1476
+ this.colors.push([buf[p], buf[p + 1], buf[p + 2], 255])
1477
+ }
1478
+ }
1479
+
1480
+ this.images = []
1481
+ this.extensions = []
1482
+
1483
+ try {
1484
+ while (p < buf.length) {
1485
+ desc = buf.readUInt8(p)
1486
+ p += 1
1487
+ if (desc === 0x2c) {
1488
+ img = {}
1489
+
1490
+ img.left = buf.readUInt16LE(p)
1491
+ p += 2
1492
+ img.top = buf.readUInt16LE(p)
1493
+ p += 2
1494
+
1495
+ img.width = buf.readUInt16LE(p)
1496
+ p += 2
1497
+ img.height = buf.readUInt16LE(p)
1498
+ p += 2
1499
+
1500
+ img.flags = buf.readUInt8(p)
1501
+ p += 1
1502
+
1503
+ img.lct = !!(img.flags & 0x80)
1504
+ img.ilace = !!(img.flags & 0x40)
1505
+ img.lctsize = (img.flags & 0x07) + 1
1506
+
1507
+ if (img.lct) {
1508
+ img.lcolors = []
1509
+ total = 1 << img.lctsize
1510
+ for (i = 0; i < total; i++, p += 3) {
1511
+ img.lcolors.push([buf[p], buf[p + 1], buf[p + 2], 255])
1512
+ }
1513
+ }
1514
+
1515
+ img.codeSize = buf.readUInt8(p)
1516
+ p += 1
1517
+
1518
+ img.size = buf.readUInt8(p)
1519
+ p += 1
1520
+
1521
+ img.lzw = [buf.slice(p, p + img.size)]
1522
+ p += img.size
1523
+
1524
+ while (buf[p] !== 0x00) {
1525
+ // Some gifs screw up their size.
1526
+ // XXX Same for all subblocks?
1527
+ if (buf[p] === 0x3b && p === buf.length - 1) {
1528
+ p--
1529
+ break
1530
+ }
1531
+ size = buf.readUInt8(p)
1532
+ p += 1
1533
+ img.lzw.push(buf.slice(p, p + size))
1534
+ p += size
1535
+ }
1536
+
1537
+ assert.equal(buf.readUInt8(p), 0x00)
1538
+ p += 1
1539
+
1540
+ if (ext && ext.label === 0xf9) {
1541
+ img.control = ext
1542
+ }
1543
+
1544
+ this.totalPixels += img.width * img.height
1545
+
1546
+ this.images.push(img)
1547
+
1548
+ if (this.totalPixels >= this.pixelLimit) {
1549
+ break
1550
+ }
1551
+ } else if (desc === 0x21) {
1552
+ // Extensions:
1553
+ // http://www.w3.org/Graphics/GIF/spec-gif89a.txt
1554
+ ext = {}
1555
+ label = buf.readUInt8(p)
1556
+ p += 1
1557
+ ext.label = label
1558
+ if (label === 0xf9) {
1559
+ size = buf.readUInt8(p)
1560
+ assert.equal(size, 0x04)
1561
+ p += 1
1562
+ ext.fields = buf.readUInt8(p)
1563
+ ext.disposeMethod = (ext.fields >> 2) & 0x07
1564
+ ext.useTransparent = !!(ext.fields & 0x01)
1565
+ p += 1
1566
+ ext.delay = buf.readUInt16LE(p)
1567
+ p += 2
1568
+ ext.transparentColor = buf.readUInt8(p)
1569
+ p += 1
1570
+ while (buf[p] !== 0x00) {
1571
+ size = buf.readUInt8(p)
1572
+ p += 1
1573
+ p += size
1574
+ }
1575
+ assert.equal(buf.readUInt8(p), 0x00)
1576
+ p += 1
1577
+ this.delay = ext.delay
1578
+ this.transparentColor = ext.transparentColor
1579
+ this.disposeMethod = ext.disposeMethod
1580
+ this.useTransparent = ext.useTransparent
1581
+ } else if (label === 0xff) {
1582
+ // https://wiki.whatwg.org/wiki/GIF#Specifications
1583
+ size = buf.readUInt8(p)
1584
+ p += 1
1585
+ ext.id = buf.slice(p, p + 8).toString('ascii')
1586
+ p += 8
1587
+ ext.auth = buf.slice(p, p + 3).toString('ascii')
1588
+ p += 3
1589
+ ext.data = []
1590
+ while (buf[p] !== 0x00) {
1591
+ size = buf.readUInt8(p)
1592
+ p += 1
1593
+ ext.data.push(buf.slice(p, p + size))
1594
+ p += size
1595
+ }
1596
+ ext.data = new Buffer(
1597
+ ext.data.reduce(function (out, data) {
1598
+ return out.concat(Array.prototype.slice.call(data))
1599
+ }, [])
1600
+ )
1601
+ // AnimExts looping extension (identical to netscape)
1602
+ if (ext.id === 'ANIMEXTS' && ext.auth === '1.0') {
1603
+ ext.id = 'NETSCAPE'
1604
+ ext.auth = '2.0'
1605
+ ext.animexts = true
1606
+ }
1607
+ // Netscape extensions
1608
+ if (ext.id === 'NETSCAPE' && ext.auth === '2.0') {
1609
+ if (ext.data.readUInt8(0) === 0x01) {
1610
+ // Netscape looping extension
1611
+ // http://graphcomp.com/info/specs/ani_gif.html
1612
+ ext.numPlays = ext.data.readUInt16LE(1)
1613
+ this.numPlays = ext.numPlays
1614
+ } else if (ext.data.readUInt8(0) === 0x02) {
1615
+ // Netscape buffering extension
1616
+ this.minBuffer = ext.data
1617
+ }
1618
+ }
1619
+ // Adobe XMP extension
1620
+ if (ext.id === 'XMP Data' && ext.auth === 'XMP') {
1621
+ ext.xmp = ext.data.toString('utf8')
1622
+ this.xmp = ext.xmp
1623
+ }
1624
+ // ICC extension
1625
+ if (ext.id === 'ICCRGBG1' && ext.auth === '012') {
1626
+ // NOTE: Says size is 4 bytes, not 1? Maybe just buffer size?
1627
+ this.icc = ext.data
1628
+ }
1629
+ // fractint extension
1630
+ if (ext.id === 'fractint' && /^00[1-7]$/.test(ext.auth)) {
1631
+ // NOTE: Says size is 4 bytes, not 1? Maybe just buffer size?
1632
+ // Size: '!\377\013' == [0x00, 0x15, 0xff, 0x0b]
1633
+ this.fractint = ext.data
1634
+ }
1635
+ assert.equal(buf.readUInt8(p), 0x00)
1636
+ p += 1
1637
+ } else {
1638
+ ext.data = []
1639
+ while (buf[p] !== 0x00) {
1640
+ size = buf.readUInt8(p)
1641
+ p += 1
1642
+ ext.data.push(buf.slice(p, p + size))
1643
+ p += size
1644
+ }
1645
+ assert.equal(buf.readUInt8(p), 0x00)
1646
+ p += 1
1647
+ }
1648
+ this.extensions.push(ext)
1649
+ } else if (desc === 0x3b) {
1650
+ break
1651
+ } else if (p === buf.length - 1) {
1652
+ // } else if (desc === 0x00 && p === buf.length - 1) {
1653
+ break
1654
+ } else {
1655
+ throw new Error('unknown block')
1656
+ }
1657
+ }
1658
+ } catch (e) {
1659
+ if (options.debug) {
1660
+ throw e
1661
+ }
1662
+ }
1663
+
1664
+ this.images = this.images
1665
+ .map(function (img, imageIndex) {
1666
+ const control = img.control || this
1667
+
1668
+ img.lzw = new Buffer(
1669
+ img.lzw.reduce(function (out, data) {
1670
+ return out.concat(Array.prototype.slice.call(data))
1671
+ }, [])
1672
+ )
1673
+
1674
+ try {
1675
+ img.data = this.decompress(img.lzw, img.codeSize)
1676
+ } catch (e) {
1677
+ if (options.debug) {
1678
+ throw e
1679
+ }
1680
+ return
1681
+ }
1682
+
1683
+ const interlacing = [
1684
+ [0, 8],
1685
+ [4, 8],
1686
+ [2, 4],
1687
+ [1, 2],
1688
+ [0, 0]
1689
+ ]
1690
+
1691
+ let table = img.lcolors || this.colors,
1692
+ row = 0,
1693
+ col = 0,
1694
+ ilp = 0,
1695
+ p = 0,
1696
+ b,
1697
+ idx,
1698
+ i,
1699
+ y,
1700
+ x,
1701
+ line,
1702
+ pixel
1703
+
1704
+ img.samples = []
1705
+ // Rewritten version of:
1706
+ // https://github.com/lbv/ka-cs-programs/blob/master/lib/gif-reader.js
1707
+ for (;;) {
1708
+ b = img.data[p++]
1709
+ if (b == null) {
1710
+ break
1711
+ }
1712
+ idx = (row * img.width + col) * 4
1713
+ if (!table[b]) {
1714
+ if (options.debug) {
1715
+ throw new Error('bad samples')
1716
+ }
1717
+ table[b] = [0, 0, 0, 0]
1718
+ }
1719
+ img.samples[idx] = table[b][0]
1720
+ img.samples[idx + 1] = table[b][1]
1721
+ img.samples[idx + 2] = table[b][2]
1722
+ img.samples[idx + 3] = table[b][3]
1723
+ if (control.useTransparent && b === control.transparentColor) {
1724
+ img.samples[idx + 3] = 0
1725
+ }
1726
+ if (++col >= img.width) {
1727
+ col = 0
1728
+ if (img.ilace) {
1729
+ row += interlacing[ilp][1]
1730
+ if (row >= img.height) {
1731
+ row = interlacing[++ilp][0]
1732
+ }
1733
+ } else {
1734
+ row++
1735
+ }
1736
+ }
1737
+ }
1738
+
1739
+ img.pixels = []
1740
+ for (i = 0; i < img.samples.length; i += 4) {
1741
+ img.pixels.push(img.samples.slice(i, i + 4))
1742
+ }
1743
+
1744
+ img.bmp = []
1745
+ for (y = 0, p = 0; y < img.height; y++) {
1746
+ line = []
1747
+ for (x = 0; x < img.width; x++) {
1748
+ pixel = img.pixels[p++]
1749
+ if (!pixel) {
1750
+ if (options.debug) {
1751
+ throw new Error('no pixel')
1752
+ }
1753
+ line.push({ r: 0, g: 0, b: 0, a: 0 })
1754
+ continue
1755
+ }
1756
+ line.push({ r: pixel[0], g: pixel[1], b: pixel[2], a: pixel[3] })
1757
+ }
1758
+ img.bmp.push(line)
1759
+ }
1760
+
1761
+ return img
1762
+ }, this)
1763
+ .filter(Boolean)
1764
+
1765
+ if (!this.images.length) {
1766
+ throw new Error('no image data or bad decompress')
1767
+ }
1768
+ }
1769
+
1770
+ // Rewritten version of:
1771
+ // https://github.com/lbv/ka-cs-programs/blob/master/lib/gif-reader.js
1772
+ GIF.prototype.decompress = function (input, codeSize) {
1773
+ let bitDepth = codeSize + 1,
1774
+ CC = 1 << codeSize,
1775
+ EOI = CC + 1,
1776
+ stack = [],
1777
+ table = [],
1778
+ ntable = 0,
1779
+ oldCode = null,
1780
+ buffer = 0,
1781
+ nbuffer = 0,
1782
+ p = 0,
1783
+ buf = [],
1784
+ bits,
1785
+ read,
1786
+ ans,
1787
+ n,
1788
+ code,
1789
+ i,
1790
+ K,
1791
+ b,
1792
+ maxElem
1793
+
1794
+ for (;;) {
1795
+ if (stack.length === 0) {
1796
+ bits = bitDepth
1797
+ read = 0
1798
+ ans = 0
1799
+ while (read < bits) {
1800
+ if (nbuffer === 0) {
1801
+ if (p >= input.length) {
1802
+ return buf
1803
+ }
1804
+ buffer = input[p++]
1805
+ nbuffer = 8
1806
+ }
1807
+ n = Math.min(bits - read, nbuffer)
1808
+ ans |= (buffer & ((1 << n) - 1)) << read
1809
+ read += n
1810
+ nbuffer -= n
1811
+ buffer >>= n
1812
+ }
1813
+ code = ans
1814
+
1815
+ if (code === EOI) {
1816
+ break
1817
+ }
1818
+
1819
+ if (code === CC) {
1820
+ table = []
1821
+ for (i = 0; i < CC; ++i) {
1822
+ table[i] = [i, -1, i]
1823
+ }
1824
+ bitDepth = codeSize + 1
1825
+ maxElem = 1 << bitDepth
1826
+ ntable = CC + 2
1827
+ oldCode = null
1828
+ continue
1829
+ }
1830
+
1831
+ if (oldCode === null) {
1832
+ oldCode = code
1833
+ buf.push(table[code][0])
1834
+ continue
1835
+ }
1836
+
1837
+ if (code < ntable) {
1838
+ for (i = code; i >= 0; i = table[i][1]) {
1839
+ stack.push(table[i][0])
1840
+ }
1841
+ table[ntable++] = [table[code][2], oldCode, table[oldCode][2]]
1842
+ } else {
1843
+ K = table[oldCode][2]
1844
+ table[ntable++] = [K, oldCode, K]
1845
+ for (i = code; i >= 0; i = table[i][1]) {
1846
+ stack.push(table[i][0])
1847
+ }
1848
+ }
1849
+
1850
+ oldCode = code
1851
+ if (ntable === maxElem) {
1852
+ maxElem = 1 << ++bitDepth
1853
+ if (bitDepth > 12) {
1854
+ bitDepth = 12
1855
+ }
1856
+ }
1857
+ }
1858
+ b = stack.pop()
1859
+ if (b == null) {
1860
+ break
1861
+ }
1862
+ buf.push(b)
1863
+ }
1864
+
1865
+ return buf
1866
+ }
1867
+
1868
+ /**
1869
+ * Expose
1870
+ */
1871
+
1872
+ exports = PNG
1873
+ exports.png = PNG
1874
+ exports.gif = GIF
1875
+
1876
+ module.exports = exports