ag-psd 32.0.0 → 34.0.0
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.
- package/.v8-cache/v24.7.0-x64-ef5a0af0/03e19709 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/05135617 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/1130885f +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/226e2801 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/2a19133e +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/4511bacf +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/68416cb2 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/71df9cb3 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/7ea06cea +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/87cf2209 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/932f0770 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/acc36e66 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/b3c2fab7 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/c0b789d2 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/c314aece +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/cfc49f4f +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/cff9434a +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/d13d7610 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/dc86f000 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/e03e2acd +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/e6745c2b +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/e6b99945 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/eeeebdfe +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/f6fd8125 +0 -0
- package/CHANGELOG.md +100 -0
- package/LICENSE +5 -0
- package/README.md +4 -7
- package/README_PSD.md +261 -84
- package/TODO.md +13 -84
- package/dist/abr.d.ts +11 -4
- package/dist/abr.js +362 -230
- package/dist/abr.js.map +1 -1
- package/dist/additionalInfo.d.ts +56 -2
- package/dist/additionalInfo.js +828 -361
- package/dist/additionalInfo.js.map +1 -1
- package/dist/ase.d.ts +6 -1
- package/dist/ase.js +61 -61
- package/dist/ase.js.map +1 -1
- package/dist/bundle.js +3321 -1364
- package/dist/descriptor.d.ts +28 -13
- package/dist/descriptor.js +295 -241
- package/dist/descriptor.js.map +1 -1
- package/dist/helpers.d.ts +7 -1
- package/dist/helpers.js +246 -4
- package/dist/helpers.js.map +1 -1
- package/dist/imageResources.d.ts +15 -3
- package/dist/imageResources.js +586 -144
- package/dist/imageResources.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/jpeg.js +8 -8
- package/dist/jpeg.js.map +1 -1
- package/dist/psd.d.ts +292 -19
- package/dist/psd.js.map +1 -1
- package/dist/psdReader.d.ts +10 -0
- package/dist/psdReader.js +424 -216
- package/dist/psdReader.js.map +1 -1
- package/dist/psdWriter.d.ts +2 -0
- package/dist/psdWriter.js +373 -113
- package/dist/psdWriter.js.map +1 -1
- package/dist/text.d.ts +32 -1
- package/dist/text.js +75 -6
- package/dist/text.js.map +1 -1
- package/dist/utf8.js +0 -3
- package/dist/utf8.js.map +1 -1
- package/dist-es/abr.d.ts +11 -4
- package/dist-es/abr.js +362 -230
- package/dist-es/abr.js.map +1 -1
- package/dist-es/additionalInfo.d.ts +56 -2
- package/dist-es/additionalInfo.js +828 -361
- package/dist-es/additionalInfo.js.map +1 -1
- package/dist-es/ase.d.ts +6 -1
- package/dist-es/ase.js +61 -61
- package/dist-es/ase.js.map +1 -1
- package/dist-es/descriptor.d.ts +28 -13
- package/dist-es/descriptor.js +295 -241
- package/dist-es/descriptor.js.map +1 -1
- package/dist-es/helpers.d.ts +7 -1
- package/dist-es/helpers.js +246 -4
- package/dist-es/helpers.js.map +1 -1
- package/dist-es/imageResources.d.ts +15 -3
- package/dist-es/imageResources.js +586 -144
- package/dist-es/imageResources.js.map +1 -1
- package/dist-es/index.d.ts +1 -0
- package/dist-es/index.js +1 -0
- package/dist-es/index.js.map +1 -1
- package/dist-es/jpeg.js +8 -8
- package/dist-es/jpeg.js.map +1 -1
- package/dist-es/psd.d.ts +292 -19
- package/dist-es/psd.js.map +1 -1
- package/dist-es/psdReader.d.ts +10 -0
- package/dist-es/psdReader.js +424 -216
- package/dist-es/psdReader.js.map +1 -1
- package/dist-es/psdWriter.d.ts +2 -0
- package/dist-es/psdWriter.js +373 -113
- package/dist-es/psdWriter.js.map +1 -1
- package/dist-es/text.d.ts +32 -1
- package/dist-es/text.js +75 -6
- package/dist-es/text.js.map +1 -1
- package/dist-es/utf8.js +0 -3
- package/dist-es/utf8.js.map +1 -1
- package/package.json +2 -2
- package/perf.js +312 -9
- package/src/abr.ts +382 -235
- package/src/additionalInfo.ts +1071 -482
- package/src/ase.ts +66 -61
- package/src/descriptor.ts +291 -242
- package/src/helpers.ts +266 -3
- package/src/imageResources.ts +736 -169
- package/src/index.ts +1 -0
- package/src/jpeg.ts +8 -8
- package/src/psd.ts +271 -32
- package/src/psdReader.ts +440 -221
- package/src/psdWriter.ts +402 -110
- package/src/text.ts +93 -7
- package/src/utf8.ts +0 -4
package/src/helpers.ts
CHANGED
|
@@ -4,7 +4,6 @@ import { decodeJpeg } from './jpeg';
|
|
|
4
4
|
import { PsdReader } from './psdReader';
|
|
5
5
|
|
|
6
6
|
export const MOCK_HANDLERS = false;
|
|
7
|
-
export const RAW_IMAGE_DATA = false;
|
|
8
7
|
|
|
9
8
|
export const fromBlendMode: { [key: string]: string } = {};
|
|
10
9
|
export const toBlendMode: { [key: string]: BlendMode } = {
|
|
@@ -41,14 +40,18 @@ export const toBlendMode: { [key: string]: BlendMode } = {
|
|
|
41
40
|
Object.keys(toBlendMode).forEach(key => fromBlendMode[toBlendMode[key]] = key);
|
|
42
41
|
|
|
43
42
|
export const layerColors: LayerColor[] = [
|
|
44
|
-
'none', 'red', 'orange', 'yellow', 'green', 'blue', 'violet', 'gray'
|
|
43
|
+
'none', 'red', 'orange', 'yellow', 'green', 'blue', 'violet', 'gray', 'seafoam', 'indigo', 'magenta', 'fuchsia',
|
|
45
44
|
];
|
|
46
45
|
|
|
46
|
+
// keys not listed in documentation that Photoshop writes with 64bit length in PSB files (with 8B64 signature)
|
|
47
|
+
export const largeAdditionalInfoKeysObserved = ['lnk3', 'lnkE', 'pths', 'extd', 'extn', 'FELS', 'artd'];
|
|
48
|
+
|
|
47
49
|
export const largeAdditionalInfoKeys = [
|
|
48
50
|
// from documentation
|
|
49
51
|
'LMsk', 'Lr16', 'Lr32', 'Layr', 'Mt16', 'Mt32', 'Mtrn', 'Alph', 'FMsk', 'lnk2', 'FEid', 'FXid', 'PxSD',
|
|
50
52
|
// from guessing
|
|
51
53
|
'cinf',
|
|
54
|
+
...largeAdditionalInfoKeysObserved,
|
|
52
55
|
];
|
|
53
56
|
|
|
54
57
|
export interface Dict {
|
|
@@ -162,9 +165,10 @@ export function clamp(value: number, min: number, max: number) {
|
|
|
162
165
|
|
|
163
166
|
export function hasAlpha(data: PixelData) {
|
|
164
167
|
const size = data.width * data.height * 4;
|
|
168
|
+
const max = data.data instanceof Float32Array ? 1 : (data.data instanceof Uint16Array ? 0xffff : 0xff);
|
|
165
169
|
|
|
166
170
|
for (let i = 3; i < size; i += 4) {
|
|
167
|
-
if (data.data[i] !==
|
|
171
|
+
if (data.data[i] !== max) {
|
|
168
172
|
return true;
|
|
169
173
|
}
|
|
170
174
|
}
|
|
@@ -172,6 +176,154 @@ export function hasAlpha(data: PixelData) {
|
|
|
172
176
|
return false;
|
|
173
177
|
}
|
|
174
178
|
|
|
179
|
+
// Polynomial approximation of U.S. Web Coated (SWOP) v2 CMYK to RGB conversion (default CMYK profile of Photoshop).
|
|
180
|
+
// Coefficients are taken from pdf.js (DeviceCmykCS in src/core/colorspace.js, https://github.com/mozilla/pdf.js),
|
|
181
|
+
// Copyright 2012 Mozilla Foundation, licensed under the Apache License, Version 2.0
|
|
182
|
+
// (http://www.apache.org/licenses/LICENSE-2.0)
|
|
183
|
+
// c, m, y, k - ink values (0 - 1), output - RGB values (0 - 255, not rounded or clamped)
|
|
184
|
+
export function cmykToRgbValues(c: number, m: number, y: number, k: number, out: number[]) {
|
|
185
|
+
out[0] = 255 +
|
|
186
|
+
c * (-4.387332384609988 * c + 54.48615194189176 * m + 18.82290502165302 * y + 212.25662451639585 * k - 285.2331026137004) +
|
|
187
|
+
m * (1.7149763477362134 * m - 5.6096736904047315 * y - 17.873870861415444 * k - 5.497006427196366) +
|
|
188
|
+
y * (-2.5217340131683033 * y - 21.248923337353073 * k + 17.5119270841813) +
|
|
189
|
+
k * (-21.86122147463605 * k - 189.48180835922747);
|
|
190
|
+
out[1] = 255 +
|
|
191
|
+
c * (8.841041422036149 * c + 60.118027045597366 * m + 6.871425592049007 * y + 31.159100130055922 * k - 79.2970844816548) +
|
|
192
|
+
m * (-15.310361306967817 * m + 17.575251261109482 * y + 131.35250912493976 * k - 190.9453302588951) +
|
|
193
|
+
y * (4.444339102852739 * y + 9.8632861493405 * k - 24.86741582555878) +
|
|
194
|
+
k * (-20.737325471181034 * k - 187.80453709719578);
|
|
195
|
+
out[2] = 255 +
|
|
196
|
+
c * (0.8842522430003296 * c + 8.078677503112928 * m + 30.89978309703729 * y - 0.23883238689178934 * k - 14.183576799673286) +
|
|
197
|
+
m * (10.49593273432072 * m + 63.02378494754052 * y + 50.606957656360734 * k - 112.23884253719248) +
|
|
198
|
+
y * (0.03296041114873217 * y + 115.60384449646641 * k - 193.58209356861505) +
|
|
199
|
+
k * (-22.33816807309886 * k - 180.12613974708367);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const clamp01 = (v: number) => v < 0 ? 0 : (v > 1 ? 1 : v);
|
|
203
|
+
|
|
204
|
+
// finds c, m, y (with fixed k) for given RGB color using Gauss-Newton method, returns squared error
|
|
205
|
+
function solveCmy(r: number, g: number, b: number, k: number, x: number[]) {
|
|
206
|
+
const f = [0, 0, 0], f2 = [0, 0, 0], e = [0, 0, 0];
|
|
207
|
+
const J = [[0, 0, 0], [0, 0, 0], [0, 0, 0]];
|
|
208
|
+
const h = 1e-4;
|
|
209
|
+
|
|
210
|
+
for (let iteration = 0; iteration < 20; iteration++) {
|
|
211
|
+
cmykToRgbValues(x[0], x[1], x[2], k, f);
|
|
212
|
+
e[0] = f[0] - r; e[1] = f[1] - g; e[2] = f[2] - b;
|
|
213
|
+
if ((e[0] * e[0] + e[1] * e[1] + e[2] * e[2]) < 1e-6) break;
|
|
214
|
+
|
|
215
|
+
for (let j = 0; j < 3; j++) {
|
|
216
|
+
const s = x[j];
|
|
217
|
+
x[j] = s + h;
|
|
218
|
+
cmykToRgbValues(x[0], x[1], x[2], k, f2);
|
|
219
|
+
x[j] = s;
|
|
220
|
+
for (let i = 0; i < 3; i++) J[i][j] = (f2[i] - f[i]) / h;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const [[a, b_, c], [d, e_, f_], [g_, h_, i_]] = J;
|
|
224
|
+
const det = a * (e_ * i_ - f_ * h_) - b_ * (d * i_ - f_ * g_) + c * (d * h_ - e_ * g_);
|
|
225
|
+
if (Math.abs(det) < 1e-12) break;
|
|
226
|
+
|
|
227
|
+
const inverse = [
|
|
228
|
+
[(e_ * i_ - f_ * h_), (c * h_ - b_ * i_), (b_ * f_ - c * e_)],
|
|
229
|
+
[(f_ * g_ - d * i_), (a * i_ - c * g_), (c * d - a * f_)],
|
|
230
|
+
[(d * h_ - e_ * g_), (b_ * g_ - a * h_), (a * e_ - b_ * d)],
|
|
231
|
+
];
|
|
232
|
+
|
|
233
|
+
let changed = 0;
|
|
234
|
+
|
|
235
|
+
for (let j = 0; j < 3; j++) {
|
|
236
|
+
const delta = -(inverse[j][0] * e[0] + inverse[j][1] * e[1] + inverse[j][2] * e[2]) / det;
|
|
237
|
+
const value = clamp01(x[j] + delta);
|
|
238
|
+
changed += Math.abs(value - x[j]);
|
|
239
|
+
x[j] = value;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if (changed < 1e-9) break;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
cmykToRgbValues(x[0], x[1], x[2], k, f);
|
|
246
|
+
return (f[0] - r) * (f[0] - r) + (f[1] - g) * (f[1] - g) + (f[2] - b) * (f[2] - b);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// finds CMYK ink values (0 - 1) for RGB color (0 - 255), out of gamut colors are approximated
|
|
250
|
+
function rgbToCmykExact(r: number, g: number, b: number, out: number[]) {
|
|
251
|
+
const max = Math.max(r, g, b) / 255;
|
|
252
|
+
const blackGeneration = Math.pow(clamp01((1 - max - 0.2) / 0.8), 1.3);
|
|
253
|
+
const x = [0, 0, 0];
|
|
254
|
+
let bestScore = Infinity, bestError = Infinity;
|
|
255
|
+
|
|
256
|
+
const tryBlack = (k: number) => {
|
|
257
|
+
x[0] = clamp01(1 - r / 255 - k);
|
|
258
|
+
x[1] = clamp01(1 - g / 255 - k);
|
|
259
|
+
x[2] = clamp01(1 - b / 255 - k);
|
|
260
|
+
const error = solveCmy(r, g, b, k, x);
|
|
261
|
+
// prefer solutions close to black generation value if the error is small enough
|
|
262
|
+
const score = Math.max(error, 0.1) + Math.abs(k - blackGeneration) * 0.01;
|
|
263
|
+
|
|
264
|
+
if (score < bestScore) {
|
|
265
|
+
bestScore = score;
|
|
266
|
+
bestError = error;
|
|
267
|
+
out[0] = x[0]; out[1] = x[1]; out[2] = x[2]; out[3] = k;
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
tryBlack(blackGeneration);
|
|
272
|
+
|
|
273
|
+
if (bestError > 0.1) {
|
|
274
|
+
for (let i = 0; i <= 10; i++) tryBlack(i / 10);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (bestError > 0.1) {
|
|
278
|
+
const k = out[3];
|
|
279
|
+
for (let i = -5; i <= 5; i++) tryBlack(clamp01(k + i / 100));
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const cmykLutSize = 33;
|
|
284
|
+
let cmykLut: Float32Array | undefined;
|
|
285
|
+
|
|
286
|
+
function getCmykLut() {
|
|
287
|
+
if (!cmykLut) {
|
|
288
|
+
const n = cmykLutSize;
|
|
289
|
+
const lut = new Float32Array(n * n * n * 4);
|
|
290
|
+
const out = [0, 0, 0, 0];
|
|
291
|
+
|
|
292
|
+
for (let r = 0, o = 0; r < n; r++) {
|
|
293
|
+
for (let g = 0; g < n; g++) {
|
|
294
|
+
for (let b = 0; b < n; b++, o += 4) {
|
|
295
|
+
rgbToCmykExact(r * 255 / (n - 1), g * 255 / (n - 1), b * 255 / (n - 1), out);
|
|
296
|
+
lut[o] = out[0]; lut[o + 1] = out[1]; lut[o + 2] = out[2]; lut[o + 3] = out[3];
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
cmykLut = lut;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
return cmykLut;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// inverse of cmykToRgbValues, r, g, b - RGB values (0 - 1), output - CMYK ink values (0 - 1)
|
|
308
|
+
export function rgbToCmykValues(r: number, g: number, b: number, out: number[]) {
|
|
309
|
+
const lut = getCmykLut();
|
|
310
|
+
const n1 = cmykLutSize - 1;
|
|
311
|
+
const fr = clamp01(r) * n1, fg = clamp01(g) * n1, fb = clamp01(b) * n1;
|
|
312
|
+
const r0 = Math.min(n1 - 1, Math.floor(fr)), g0 = Math.min(n1 - 1, Math.floor(fg)), b0 = Math.min(n1 - 1, Math.floor(fb));
|
|
313
|
+
const dr = fr - r0, dg = fg - g0, db = fb - b0;
|
|
314
|
+
out[0] = out[1] = out[2] = out[3] = 0;
|
|
315
|
+
|
|
316
|
+
for (let i = 0; i < 8; i++) {
|
|
317
|
+
const ir = i >> 2, ig = (i >> 1) & 1, ib = i & 1;
|
|
318
|
+
const w = (ir ? dr : 1 - dr) * (ig ? dg : 1 - dg) * (ib ? db : 1 - db);
|
|
319
|
+
const o = (((r0 + ir) * cmykLutSize + g0 + ig) * cmykLutSize + b0 + ib) * 4;
|
|
320
|
+
out[0] += w * lut[o];
|
|
321
|
+
out[1] += w * lut[o + 1];
|
|
322
|
+
out[2] += w * lut[o + 2];
|
|
323
|
+
out[3] += w * lut[o + 3];
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
175
327
|
export function resetImageData({ data }: PixelData) {
|
|
176
328
|
const alpha = (data instanceof Float32Array) ? 1.0 : ((data instanceof Uint16Array) ? 0xffff : 0xff);
|
|
177
329
|
|
|
@@ -350,6 +502,117 @@ export function writeDataRLE(buffer: Uint8Array, { data, width, height }: PixelD
|
|
|
350
502
|
return buffer.subarray(0, o);
|
|
351
503
|
}
|
|
352
504
|
|
|
505
|
+
// single channel of image data (8bit, 16bit or 32bit values)
|
|
506
|
+
export type PlanarData = Uint8Array | Uint16Array | Float32Array;
|
|
507
|
+
|
|
508
|
+
// converts channel values to big-endian bytes
|
|
509
|
+
export function planarToBytes(values: PlanarData): Uint8Array {
|
|
510
|
+
if (values instanceof Uint8Array) return values;
|
|
511
|
+
|
|
512
|
+
const bytes = new Uint8Array(values.byteLength);
|
|
513
|
+
const view = new DataView(bytes.buffer);
|
|
514
|
+
|
|
515
|
+
if (values instanceof Uint16Array) {
|
|
516
|
+
for (let i = 0; i < values.length; i++) view.setUint16(i * 2, values[i], false);
|
|
517
|
+
} else {
|
|
518
|
+
for (let i = 0; i < values.length; i++) view.setFloat32(i * 4, values[i], false);
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
return bytes;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// RLE (PackBits) compression of rows of bytes, prefixed with byte counts of each row
|
|
525
|
+
export function writeDataRLEBytes(bytes: Uint8Array, rowBytes: number, height: number, large: boolean) {
|
|
526
|
+
const countSize = large ? 4 : 2;
|
|
527
|
+
const buffer = new Uint8Array(height * (countSize + rowBytes + Math.ceil(rowBytes / 128)));
|
|
528
|
+
let o = countSize * height;
|
|
529
|
+
|
|
530
|
+
for (let y = 0; y < height; y++) {
|
|
531
|
+
const start = o;
|
|
532
|
+
const rowStart = y * rowBytes;
|
|
533
|
+
const rowEnd = rowStart + rowBytes;
|
|
534
|
+
let i = rowStart;
|
|
535
|
+
|
|
536
|
+
while (i < rowEnd) {
|
|
537
|
+
let run = 1;
|
|
538
|
+
while (i + run < rowEnd && run < 128 && bytes[i + run] === bytes[i]) run++;
|
|
539
|
+
|
|
540
|
+
if (run > 1) {
|
|
541
|
+
buffer[o++] = 257 - run;
|
|
542
|
+
buffer[o++] = bytes[i];
|
|
543
|
+
i += run;
|
|
544
|
+
} else {
|
|
545
|
+
// literal bytes until a run of at least 3 equal bytes
|
|
546
|
+
const countIndex = o++;
|
|
547
|
+
let count = 0;
|
|
548
|
+
|
|
549
|
+
while (i < rowEnd && count < 128) {
|
|
550
|
+
if (i + 2 < rowEnd && bytes[i] === bytes[i + 1] && bytes[i] === bytes[i + 2]) break;
|
|
551
|
+
buffer[o++] = bytes[i++];
|
|
552
|
+
count++;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
buffer[countIndex] = count - 1;
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
const length = o - start;
|
|
560
|
+
|
|
561
|
+
for (let j = 0; j < countSize; j++) {
|
|
562
|
+
buffer[y * countSize + j] = (length >>> ((countSize - j - 1) * 8)) & 0xff;
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
return buffer.subarray(0, o);
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
// zip compression with prediction (values are delta encoded per row, 32bit values are split into byte planes first)
|
|
570
|
+
export function writeDataZipWithPrediction(values: PlanarData, width: number, height: number) {
|
|
571
|
+
let bytes: Uint8Array;
|
|
572
|
+
|
|
573
|
+
if (values instanceof Uint8Array) {
|
|
574
|
+
bytes = new Uint8Array(width * height);
|
|
575
|
+
|
|
576
|
+
for (let y = 0, i = 0; y < height; y++) {
|
|
577
|
+
for (let x = 0, prev = 0; x < width; x++, i++) {
|
|
578
|
+
bytes[i] = values[i] - prev; // Uint8Array wraps values on assignment
|
|
579
|
+
prev = values[i];
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
} else if (values instanceof Uint16Array) {
|
|
583
|
+
bytes = new Uint8Array(width * height * 2);
|
|
584
|
+
|
|
585
|
+
for (let y = 0, i = 0; y < height; y++) {
|
|
586
|
+
for (let x = 0, prev = 0; x < width; x++, i++) {
|
|
587
|
+
const delta = (values[i] - prev) & 0xffff;
|
|
588
|
+
bytes[i * 2] = delta >> 8;
|
|
589
|
+
bytes[i * 2 + 1] = delta & 0xff;
|
|
590
|
+
prev = values[i];
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
} else {
|
|
594
|
+
const rowBytes = width * 4;
|
|
595
|
+
const source = planarToBytes(values);
|
|
596
|
+
bytes = new Uint8Array(rowBytes * height);
|
|
597
|
+
|
|
598
|
+
for (let y = 0; y < height; y++) {
|
|
599
|
+
const row = y * rowBytes;
|
|
600
|
+
|
|
601
|
+
for (let x = 0; x < width; x++) {
|
|
602
|
+
for (let b = 0; b < 4; b++) {
|
|
603
|
+
bytes[row + b * width + x] = source[row + x * 4 + b];
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
for (let x = rowBytes - 1; x > 0; x--) {
|
|
608
|
+
bytes[row + x] -= bytes[row + x - 1];
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
return deflateSync(bytes);
|
|
614
|
+
}
|
|
615
|
+
|
|
353
616
|
export function writeDataZipWithoutPrediction({ data, width, height }: PixelData, offsets: number[]) {
|
|
354
617
|
const size = width * height;
|
|
355
618
|
const channel = new Uint8Array(size);
|