ag-psd 31.0.3 → 32.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/00d0e0b4 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/05135617 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/0cc76730 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/1130885f +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/20729831 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/214a593b +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/226e2801 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/25f8b84a +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/27518289 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/330ef2d9 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/37ff16b8 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/3f72a97c +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/75efccd4 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/762f9305 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/7bcfc50a +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/7ea06cea +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/825e9a05 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/87372817 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/87cf2209 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/891a7c73 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/8b68a3a2 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/932f0770 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/a1d12a93 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/a7e80865 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/ac317c9c +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/b8569d6b +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/b8b073c4 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/bb489c89 +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/c46725e1 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/c794cb34 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/cd4ae980 +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/d02dd6f7 +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/e6735171 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/f5417276 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/f6fd8125 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/f74d3518 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/f886deac +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/fd0a2987 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/fe349423 +0 -0
- package/CHANGELOG.md +29 -0
- package/dist/abr.js +12 -5
- package/dist/abr.js.map +1 -1
- package/dist/additionalInfo.d.ts +2 -0
- package/dist/additionalInfo.js +123 -68
- package/dist/additionalInfo.js.map +1 -1
- package/dist/bundle.js +1365 -632
- package/dist/descriptor.d.ts +15 -2
- package/dist/descriptor.js +329 -100
- package/dist/descriptor.js.map +1 -1
- package/dist/effectsHelpers.js +12 -12
- package/dist/effectsHelpers.js.map +1 -1
- package/dist/engineData.d.ts +3 -1
- package/dist/engineData.js +34 -13
- package/dist/engineData.js.map +1 -1
- package/dist/engineData2.js +50 -21
- package/dist/engineData2.js.map +1 -1
- package/dist/helpers.d.ts +5 -2
- package/dist/helpers.js +18 -4
- package/dist/helpers.js.map +1 -1
- package/dist/imageResources.js +45 -21
- package/dist/imageResources.js.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/jpeg.js +27 -7
- package/dist/jpeg.js.map +1 -1
- package/dist/psd.d.ts +6 -1
- package/dist/psdReader.d.ts +2 -2
- package/dist/psdReader.js +457 -270
- package/dist/psdReader.js.map +1 -1
- package/dist/psdWriter.d.ts +2 -0
- package/dist/psdWriter.js +98 -76
- package/dist/psdWriter.js.map +1 -1
- package/dist/text.js +126 -23
- package/dist/text.js.map +1 -1
- package/dist/utf8.js +36 -15
- package/dist/utf8.js.map +1 -1
- package/dist-es/abr.js +12 -5
- package/dist-es/abr.js.map +1 -1
- package/dist-es/additionalInfo.d.ts +2 -0
- package/dist-es/additionalInfo.js +123 -68
- package/dist-es/additionalInfo.js.map +1 -1
- package/dist-es/descriptor.d.ts +15 -2
- package/dist-es/descriptor.js +329 -100
- package/dist-es/descriptor.js.map +1 -1
- package/dist-es/effectsHelpers.js +12 -12
- package/dist-es/effectsHelpers.js.map +1 -1
- package/dist-es/engineData.d.ts +3 -1
- package/dist-es/engineData.js +34 -13
- package/dist-es/engineData.js.map +1 -1
- package/dist-es/engineData2.js +50 -21
- package/dist-es/engineData2.js.map +1 -1
- package/dist-es/helpers.d.ts +5 -2
- package/dist-es/helpers.js +18 -4
- package/dist-es/helpers.js.map +1 -1
- package/dist-es/imageResources.js +45 -21
- package/dist-es/imageResources.js.map +1 -1
- package/dist-es/index.js +1 -0
- package/dist-es/index.js.map +1 -1
- package/dist-es/jpeg.js +27 -7
- package/dist-es/jpeg.js.map +1 -1
- package/dist-es/psd.d.ts +6 -1
- package/dist-es/psdReader.d.ts +2 -2
- package/dist-es/psdReader.js +457 -270
- package/dist-es/psdReader.js.map +1 -1
- package/dist-es/psdWriter.d.ts +2 -0
- package/dist-es/psdWriter.js +98 -76
- package/dist-es/psdWriter.js.map +1 -1
- package/dist-es/text.js +126 -23
- package/dist-es/text.js.map +1 -1
- package/dist-es/utf8.js +36 -15
- package/dist-es/utf8.js.map +1 -1
- package/package.json +1 -1
- package/src/abr.ts +14 -6
- package/src/additionalInfo.ts +127 -66
- package/src/descriptor.ts +347 -107
- package/src/effectsHelpers.ts +9 -9
- package/src/engineData.ts +36 -13
- package/src/engineData2.ts +468 -432
- package/src/helpers.ts +19 -4
- package/src/imageResources.ts +49 -22
- package/src/index.ts +1 -0
- package/src/jpeg.ts +24 -9
- package/src/psd.ts +3 -1
- package/src/psdReader.ts +477 -260
- package/src/psdWriter.ts +100 -83
- package/src/text.ts +122 -12
- package/src/utf8.ts +35 -17
package/src/helpers.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { deflate as deflateSync } from 'pako';
|
|
2
2
|
import { Layer, BlendMode, LayerColor, PixelData, PixelArray, ChannelID, Compression } from './psd';
|
|
3
3
|
import { decodeJpeg } from './jpeg';
|
|
4
|
+
import { PsdReader } from './psdReader';
|
|
4
5
|
|
|
5
6
|
export const MOCK_HANDLERS = false;
|
|
6
7
|
export const RAW_IMAGE_DATA = false;
|
|
@@ -146,6 +147,15 @@ export function offsetForChannel(channelId: ChannelID, cmyk: boolean) {
|
|
|
146
147
|
}
|
|
147
148
|
}
|
|
148
149
|
|
|
150
|
+
// Lab a/b components are stored in -128..127 range (multiplied by scale), normalized values are in -1..1 range
|
|
151
|
+
export function normalizeLabAB(value: number, scale = 1) {
|
|
152
|
+
return value < 0 ? (value / (128 * scale)) : (value / (127 * scale));
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export function denormalizeLabAB(value: number, scale = 1) {
|
|
156
|
+
return value < 0 ? (value * (128 * scale)) : (value * (127 * scale));
|
|
157
|
+
}
|
|
158
|
+
|
|
149
159
|
export function clamp(value: number, min: number, max: number) {
|
|
150
160
|
return value < min ? min : (value > max ? max : value);
|
|
151
161
|
}
|
|
@@ -236,8 +246,9 @@ export function writeDataRaw(data: PixelData, offset: number, width: number, hei
|
|
|
236
246
|
return array;
|
|
237
247
|
}
|
|
238
248
|
|
|
249
|
+
// returns view into the buffer, the buffer has to fit worst case size (see getRLEChannelBound), throws if it doesn't
|
|
239
250
|
export function writeDataRLE(buffer: Uint8Array, { data, width, height }: PixelData, offsets: number[], large: boolean) {
|
|
240
|
-
if (!width || !height) return
|
|
251
|
+
if (!width || !height) return buffer.subarray(0, 0);
|
|
241
252
|
|
|
242
253
|
const stride = (4 * width) | 0;
|
|
243
254
|
|
|
@@ -320,6 +331,9 @@ export function writeDataRLE(buffer: Uint8Array, { data, width, height }: PixelD
|
|
|
320
331
|
}
|
|
321
332
|
}
|
|
322
333
|
|
|
334
|
+
// writes past the end of typed array are ignored, so it's enough to check the size after each row
|
|
335
|
+
if (o > buffer.length) throw new Error(`RLE buffer too small (${buffer.length})`);
|
|
336
|
+
|
|
323
337
|
const length = o - startOffset;
|
|
324
338
|
|
|
325
339
|
if (large) {
|
|
@@ -332,7 +346,8 @@ export function writeDataRLE(buffer: Uint8Array, { data, width, height }: PixelD
|
|
|
332
346
|
}
|
|
333
347
|
}
|
|
334
348
|
|
|
335
|
-
|
|
349
|
+
// returns view of the buffer, copy the data if the buffer is going to be reused
|
|
350
|
+
return buffer.subarray(0, o);
|
|
336
351
|
}
|
|
337
352
|
|
|
338
353
|
export function writeDataZipWithoutPrediction({ data, width, height }: PixelData, offsets: number[]) {
|
|
@@ -366,7 +381,7 @@ export function writeDataZipWithoutPrediction({ data, width, height }: PixelData
|
|
|
366
381
|
}
|
|
367
382
|
}
|
|
368
383
|
|
|
369
|
-
export function createCanvasFromData(data: Uint8Array): HTMLCanvasElement {
|
|
384
|
+
export function createCanvasFromData(data: Uint8Array, reader: Pick<PsdReader, 'log'>): HTMLCanvasElement {
|
|
370
385
|
const canvas = createCanvas(100, 100);
|
|
371
386
|
|
|
372
387
|
try {
|
|
@@ -376,7 +391,7 @@ export function createCanvasFromData(data: Uint8Array): HTMLCanvasElement {
|
|
|
376
391
|
canvas.height = imageData.height;
|
|
377
392
|
context.putImageData(imageData, 0, 0);
|
|
378
393
|
} catch (e: any) {
|
|
379
|
-
|
|
394
|
+
reader.log('JPEG decompression error', e.message);
|
|
380
395
|
}
|
|
381
396
|
|
|
382
397
|
return canvas;
|
package/src/imageResources.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { PsdReader, readUnicodeString, readUint32, readUint16, readUint8, readFl
|
|
|
4
4
|
import { PsdWriter, writeUnicodeString, writeUint32, writeUint8, writeFloat64, writeUint16, writeBytes, writeInt16, writeFloat32, writeFixedPoint32, writeUnicodeStringWithPadding, writeColor, writeSignature, writeSection, writeInt32, writeAsciiString, } from './psdWriter';
|
|
5
5
|
import { createCanvasFromData, createEnum, MOCK_HANDLERS } from './helpers';
|
|
6
6
|
import { decodeString, encodeString } from './utf8';
|
|
7
|
-
import { ESliceBGColorType, ESliceHorzAlign, ESliceOrigin, ESliceType, ESliceVertAlign, frac, FractionDescriptor, parseTrackList, readVersionAndDescriptor, serializeTrackList, TimelineTrackDescriptor, TimeScopeDescriptor, writeVersionAndDescriptor } from './descriptor';
|
|
7
|
+
import { ESliceBGColorType, ESliceHorzAlign, ESliceOrigin, ESliceType, ESliceVertAlign, frac, FractionDescriptor, parseTrackList, pathSelectionStateToReference, readVersionAndDescriptor, serializeTrackList, TimelineTrackDescriptor, TimeScopeDescriptor, writeVersionAndDescriptor } from './descriptor';
|
|
8
8
|
|
|
9
9
|
export interface InternalImageResources extends ImageResources {
|
|
10
10
|
layersGroup?: number[];
|
|
@@ -57,6 +57,20 @@ function writeUtf8String(writer: PsdWriter, value: string) {
|
|
|
57
57
|
writeBytes(writer, buffer);
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
let gbkDecoder: TextDecoder | null | undefined;
|
|
61
|
+
|
|
62
|
+
function getGbkDecoder() {
|
|
63
|
+
if (gbkDecoder === undefined) {
|
|
64
|
+
try {
|
|
65
|
+
gbkDecoder = new TextDecoder('gbk');
|
|
66
|
+
} catch {
|
|
67
|
+
gbkDecoder = null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return gbkDecoder;
|
|
72
|
+
}
|
|
73
|
+
|
|
60
74
|
function readEncodedString(reader: PsdReader) {
|
|
61
75
|
const length = readUint8(reader);
|
|
62
76
|
const buffer = readBytes(reader, length);
|
|
@@ -70,10 +84,13 @@ function readEncodedString(reader: PsdReader) {
|
|
|
70
84
|
}
|
|
71
85
|
|
|
72
86
|
if (notAscii) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
87
|
+
const decoder = getGbkDecoder();
|
|
88
|
+
|
|
89
|
+
if (decoder) {
|
|
90
|
+
try {
|
|
91
|
+
return decoder.decode(buffer);
|
|
92
|
+
} catch { }
|
|
93
|
+
}
|
|
77
94
|
}
|
|
78
95
|
|
|
79
96
|
return decodeString(buffer);
|
|
@@ -82,10 +99,15 @@ function readEncodedString(reader: PsdReader) {
|
|
|
82
99
|
function writeEncodedString(writer: PsdWriter, value: string) {
|
|
83
100
|
let ascii = '';
|
|
84
101
|
|
|
85
|
-
for (let i = 0
|
|
86
|
-
|
|
102
|
+
for (let i = 0; i < value.length;) {
|
|
103
|
+
const code = value.codePointAt(i)!;
|
|
104
|
+
ascii += code > 0x7f ? '?' : String.fromCharCode(code);
|
|
105
|
+
i += code > 0xffff ? 2 : 1; // skip low surrogate of astral characters
|
|
87
106
|
}
|
|
88
107
|
|
|
108
|
+
// length is stored in a single byte
|
|
109
|
+
if (ascii.length > 255) ascii = ascii.substring(0, 255);
|
|
110
|
+
|
|
89
111
|
const buffer = encodeString(ascii);
|
|
90
112
|
writeUint8(writer, buffer.byteLength);
|
|
91
113
|
writeBytes(writer, buffer);
|
|
@@ -616,7 +638,7 @@ addHandler(
|
|
|
616
638
|
|
|
617
639
|
for (let i = 0; i < count; i++) {
|
|
618
640
|
target.gridAndGuidesInformation.guides!.push({
|
|
619
|
-
location:
|
|
641
|
+
location: readInt32(reader) / 32,
|
|
620
642
|
direction: readUint8(reader) ? 'horizontal' : 'vertical'
|
|
621
643
|
});
|
|
622
644
|
}
|
|
@@ -627,12 +649,12 @@ addHandler(
|
|
|
627
649
|
const guides = info.guides || [];
|
|
628
650
|
|
|
629
651
|
writeUint32(writer, 1);
|
|
630
|
-
writeUint32(writer, grid.horizontal);
|
|
631
|
-
writeUint32(writer, grid.vertical);
|
|
652
|
+
writeUint32(writer, Math.round(grid.horizontal));
|
|
653
|
+
writeUint32(writer, Math.round(grid.vertical));
|
|
632
654
|
writeUint32(writer, guides.length);
|
|
633
655
|
|
|
634
656
|
for (const g of guides) {
|
|
635
|
-
|
|
657
|
+
writeInt32(writer, Math.round(g.location * 32));
|
|
636
658
|
writeUint8(writer, g.direction === 'horizontal' ? 1 : 0);
|
|
637
659
|
}
|
|
638
660
|
},
|
|
@@ -665,10 +687,10 @@ addHandler(
|
|
|
665
687
|
capturedInfo: item.capturedInfo,
|
|
666
688
|
});
|
|
667
689
|
|
|
668
|
-
if (
|
|
690
|
+
if (item.comment !== undefined) target.layerComps.list[target.layerComps.list.length - 1].comment = item.comment;
|
|
669
691
|
}
|
|
670
692
|
|
|
671
|
-
if (
|
|
693
|
+
if (desc.lastAppliedComp !== undefined) target.layerComps.lastApplied = desc.lastAppliedComp;
|
|
672
694
|
},
|
|
673
695
|
(writer, target) => {
|
|
674
696
|
const layerComps = target.layerComps!;
|
|
@@ -678,13 +700,13 @@ addHandler(
|
|
|
678
700
|
const t: LayerCompsDescriptor['list'][0] = {} as any;
|
|
679
701
|
t._classID = 'Comp';
|
|
680
702
|
t['Nm '] = item.name;
|
|
681
|
-
if (
|
|
703
|
+
if (item.comment !== undefined) t.comment = item.comment;
|
|
682
704
|
t.compID = item.id;
|
|
683
705
|
t.capturedInfo = item.capturedInfo;
|
|
684
706
|
desc.list.push(t);
|
|
685
707
|
}
|
|
686
708
|
|
|
687
|
-
if (
|
|
709
|
+
if (layerComps.lastApplied !== undefined) desc.lastAppliedComp = layerComps.lastApplied;
|
|
688
710
|
|
|
689
711
|
// console.log('CompList', require('util').inspect(desc, false, 99, true));
|
|
690
712
|
writeVersionAndDescriptor(writer, '', 'CompList', desc);
|
|
@@ -747,8 +769,8 @@ addHandler(
|
|
|
747
769
|
numBefore: onionSkins.framesBefore,
|
|
748
770
|
numAfter: onionSkins.framesAfter,
|
|
749
771
|
Spcn: onionSkins.frameSpacing,
|
|
750
|
-
minOpacity: (onionSkins.minOpacity * 100)
|
|
751
|
-
maxOpacity: (onionSkins.maxOpacity * 100)
|
|
772
|
+
minOpacity: Math.round(onionSkins.minOpacity * 100),
|
|
773
|
+
maxOpacity: Math.round(onionSkins.maxOpacity * 100),
|
|
752
774
|
BlnM: Math.max(0, onionSkinsBlendModes.indexOf(onionSkins.blendMode)),
|
|
753
775
|
};
|
|
754
776
|
|
|
@@ -855,7 +877,7 @@ addHandler(
|
|
|
855
877
|
LCnt: timeline.repeats,
|
|
856
878
|
globalTrackList: serializeTrackList(timeline.globalTracks),
|
|
857
879
|
audioClipGroupList: {
|
|
858
|
-
audioClipGroupList: timeline.audioClipGroups
|
|
880
|
+
audioClipGroupList: (timeline.audioClipGroups ?? []).map(a => ({
|
|
859
881
|
groupID: a.id,
|
|
860
882
|
muted: a.muted,
|
|
861
883
|
audioClipList: a.audioClips.map<TimelineAudioClipDescriptor>(c => ({
|
|
@@ -1072,8 +1094,13 @@ addHandler(
|
|
|
1072
1094
|
}
|
|
1073
1095
|
if (leftBytes()) {
|
|
1074
1096
|
const desc = readVersionAndDescriptor(reader) as SlicesDesc;
|
|
1097
|
+
const slicesById = new Map<number, typeof slices[0]>();
|
|
1098
|
+
for (const s of slices) {
|
|
1099
|
+
if (!slicesById.has(s.id)) slicesById.set(s.id, s);
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1075
1102
|
desc.slices.forEach(d => {
|
|
1076
|
-
const slice =
|
|
1103
|
+
const slice = slicesById.get(d.sliceID);
|
|
1077
1104
|
if (slice) {
|
|
1078
1105
|
slice.topOutset = d.topOutset;
|
|
1079
1106
|
slice.leftOutset = d.leftOutset;
|
|
@@ -1272,7 +1299,7 @@ addHandler(
|
|
|
1272
1299
|
if (reader.useRawThumbnail) {
|
|
1273
1300
|
target.thumbnailRaw = { width, height, data };
|
|
1274
1301
|
} else if (data.byteLength) {
|
|
1275
|
-
target.thumbnail = createCanvasFromData(data);
|
|
1302
|
+
target.thumbnail = createCanvasFromData(data, reader);
|
|
1276
1303
|
}
|
|
1277
1304
|
},
|
|
1278
1305
|
(writer, target) => {
|
|
@@ -1386,7 +1413,7 @@ addHandler(
|
|
|
1386
1413
|
target.pathSelectionState = desc['null'];
|
|
1387
1414
|
},
|
|
1388
1415
|
(writer, target) => {
|
|
1389
|
-
const desc: Descriptor1088 = { 'null': target.pathSelectionState! };
|
|
1416
|
+
const desc: Descriptor1088 = { 'null': pathSelectionStateToReference(target.pathSelectionState!) };
|
|
1390
1417
|
writeVersionAndDescriptor(writer, '', 'null', desc);
|
|
1391
1418
|
},
|
|
1392
1419
|
);
|
|
@@ -1498,7 +1525,7 @@ addHandler(
|
|
|
1498
1525
|
const frame: AnimationFrameDescriptor = {
|
|
1499
1526
|
FrID: f.id,
|
|
1500
1527
|
} as any;
|
|
1501
|
-
if (f.delay) frame.FrDl = (f.delay * 100)
|
|
1528
|
+
if (f.delay) frame.FrDl = Math.round(f.delay * 100);
|
|
1502
1529
|
frame.FrDs = FrmD.encode(f.dispose);
|
|
1503
1530
|
// if (i === 0) frame.FrGA = 30; // ???
|
|
1504
1531
|
desc.FrIn.push(frame);
|
package/src/index.ts
CHANGED
|
@@ -43,5 +43,6 @@ export function writePsdBuffer(psd: Psd, options?: WriteOptions): Buffer {
|
|
|
43
43
|
throw new Error('Buffer not supported on this platform');
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
// copy, so the buffer doesn't hold on to the unused part of the writer's buffer
|
|
46
47
|
return Buffer.from(writePsdUint8Array(psd, options));
|
|
47
48
|
}
|
package/src/jpeg.ts
CHANGED
|
@@ -88,6 +88,8 @@ const maxMemoryUsageBytes = 64 * 1024 * 1024; // Don't decode if memory footprin
|
|
|
88
88
|
let totalBytesAllocated = 0; // avoid unexpected OOMs from untrusted content.
|
|
89
89
|
|
|
90
90
|
function requestMemoryAllocation(increaseAmount: number) {
|
|
91
|
+
if (!isFinite(increaseAmount) || increaseAmount < 0) throw new Error(`Invalid memory allocation size (${increaseAmount})`);
|
|
92
|
+
|
|
91
93
|
const totalMemoryImpactBytes = totalBytesAllocated + increaseAmount;
|
|
92
94
|
if (totalMemoryImpactBytes > maxMemoryUsageBytes) {
|
|
93
95
|
const exceededAmount = Math.ceil((totalMemoryImpactBytes - maxMemoryUsageBytes) / 1024 / 1024);
|
|
@@ -169,7 +171,9 @@ function decodeScan(
|
|
|
169
171
|
return bitsData >>> 7;
|
|
170
172
|
}
|
|
171
173
|
|
|
172
|
-
function decodeHuffman(tree: number[] | number[][]) {
|
|
174
|
+
function decodeHuffman(tree: number[] | number[][] | undefined) {
|
|
175
|
+
if (!tree) throw new Error('Missing Huffman table');
|
|
176
|
+
|
|
173
177
|
let node: number | number[] | number[][] = tree;
|
|
174
178
|
|
|
175
179
|
while (true) {
|
|
@@ -359,6 +363,8 @@ function decodeScan(
|
|
|
359
363
|
mcuExpected = mcusPerLine * frame.mcusPerColumn;
|
|
360
364
|
}
|
|
361
365
|
|
|
366
|
+
if (!isFinite(mcuExpected) || mcuExpected < 0) throw new Error('Invalid number of MCUs');
|
|
367
|
+
|
|
362
368
|
if (!resetInterval) resetInterval = mcuExpected;
|
|
363
369
|
|
|
364
370
|
let h: number;
|
|
@@ -375,6 +381,9 @@ function decodeScan(
|
|
|
375
381
|
for (let n = 0; n < resetInterval; n++) {
|
|
376
382
|
decodeBlock(component, decodeFn, mcu);
|
|
377
383
|
mcu++;
|
|
384
|
+
|
|
385
|
+
// If we've reached our expected MCU's, stop decoding
|
|
386
|
+
if (mcu === mcuExpected) break;
|
|
378
387
|
}
|
|
379
388
|
} else {
|
|
380
389
|
for (let n = 0; n < resetInterval; n++) {
|
|
@@ -438,7 +447,8 @@ function buildComponentData(component: Component) {
|
|
|
438
447
|
// IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
|
|
439
448
|
// 988-991.
|
|
440
449
|
function quantizeAndInverse(zz: Int32Array, dataOut: Uint8Array, dataIn: Int32Array) {
|
|
441
|
-
const qt = component.quantizationTable
|
|
450
|
+
const qt = component.quantizationTable;
|
|
451
|
+
if (!qt) throw new Error('Missing quantization table');
|
|
442
452
|
const p = dataIn;
|
|
443
453
|
|
|
444
454
|
// dequant
|
|
@@ -823,11 +833,13 @@ function parse(data: Uint8Array) {
|
|
|
823
833
|
}
|
|
824
834
|
|
|
825
835
|
const componentsCount = data[offset++];
|
|
836
|
+
if (!componentsCount) throw new Error('SOF: no components in frame');
|
|
826
837
|
|
|
827
838
|
for (let i = 0; i < componentsCount; i++) {
|
|
828
839
|
const componentId = data[offset];
|
|
829
840
|
const h = data[offset + 1] >> 4;
|
|
830
841
|
const v = data[offset + 1] & 15;
|
|
842
|
+
if (h < 1 || h > 4 || v < 1 || v > 4) throw new Error(`SOF: invalid sampling factors (${h}x${v})`);
|
|
831
843
|
const qId = data[offset + 2];
|
|
832
844
|
frame!.componentsOrder.push(componentId);
|
|
833
845
|
frame!.components[componentId] = {
|
|
@@ -881,11 +893,14 @@ function parse(data: Uint8Array) {
|
|
|
881
893
|
readUint16() // Ignore this data since it represents the image height
|
|
882
894
|
break;
|
|
883
895
|
case 0xFFDA: { // SOS (Start of Scan)
|
|
896
|
+
if (!frame) throw new Error('SOS: scan before frame header (SOF)');
|
|
884
897
|
readUint16(); // skip data length
|
|
885
898
|
const selectorsCount = data[offset++];
|
|
886
899
|
const components: Component[] = [];
|
|
887
900
|
for (let i = 0; i < selectorsCount; i++) {
|
|
888
|
-
const
|
|
901
|
+
const componentId = data[offset++];
|
|
902
|
+
const component = frame.components[componentId];
|
|
903
|
+
if (!component) throw new Error(`SOS: component ${componentId} not found in frame`);
|
|
889
904
|
const tableSpec = data[offset++];
|
|
890
905
|
component.huffmanTableDC = huffmanTablesDC[tableSpec >> 4];
|
|
891
906
|
component.huffmanTableAC = huffmanTablesAC[tableSpec & 15];
|
|
@@ -895,7 +910,7 @@ function parse(data: Uint8Array) {
|
|
|
895
910
|
const spectralEnd = data[offset++];
|
|
896
911
|
const successiveApproximation = data[offset++];
|
|
897
912
|
const processed = decodeScan(
|
|
898
|
-
data, offset, frame
|
|
913
|
+
data, offset, frame, components, resetInterval, spectralStart, spectralEnd,
|
|
899
914
|
successiveApproximation >> 4, successiveApproximation & 15);
|
|
900
915
|
offset += processed;
|
|
901
916
|
break;
|
|
@@ -938,7 +953,9 @@ function parse(data: Uint8Array) {
|
|
|
938
953
|
for (let i = 0; i < frames.length; i++) {
|
|
939
954
|
const cp = frames[i].components;
|
|
940
955
|
for (let j in cp) { // TODO: don't use `in`
|
|
941
|
-
|
|
956
|
+
const table = quantizationTables[cp[j].quantizationIdx!];
|
|
957
|
+
if (!table) throw new Error(`Missing quantization table ${cp[j].quantizationIdx}`);
|
|
958
|
+
cp[j].quantizationTable = table;
|
|
942
959
|
delete cp[j].quantizationIdx; // TODO: why ???
|
|
943
960
|
}
|
|
944
961
|
}
|
|
@@ -1004,10 +1021,8 @@ function getData(decoded: Decoded) {
|
|
|
1004
1021
|
break;
|
|
1005
1022
|
}
|
|
1006
1023
|
case 3: {
|
|
1007
|
-
// The default transform for three components is true
|
|
1008
|
-
colorTransform = true;
|
|
1009
|
-
// The adobe transform marker overrides any previous setting
|
|
1010
|
-
if (decoded.adobe && decoded.adobe.transformCode) colorTransform = true;
|
|
1024
|
+
// The default transform for three components is true, the adobe transform marker overrides it
|
|
1025
|
+
colorTransform = decoded.adobe ? !!decoded.adobe.transformCode : true;
|
|
1011
1026
|
|
|
1012
1027
|
const component1 = decoded.components[0];
|
|
1013
1028
|
const component2 = decoded.components[1];
|
package/src/psd.ts
CHANGED
|
@@ -411,7 +411,7 @@ export interface TextPath {
|
|
|
411
411
|
textRange: number[];
|
|
412
412
|
rowGutter?: number;
|
|
413
413
|
columnGutter?: number;
|
|
414
|
-
|
|
414
|
+
baselineAlignment?: {
|
|
415
415
|
flag?: number;
|
|
416
416
|
min?: number;
|
|
417
417
|
};
|
|
@@ -1793,6 +1793,8 @@ export interface Psd extends LayerAdditionalInfo {
|
|
|
1793
1793
|
canvas?: HTMLCanvasElement;
|
|
1794
1794
|
imageData?: PixelData;
|
|
1795
1795
|
rawCompositeData?: Uint8Array;
|
|
1796
|
+
/** Information needed to decode `rawCompositeData` (see `getCompositeImageData`) */
|
|
1797
|
+
rawCompositeDataInfo?: { large: boolean; globalAlpha: boolean; };
|
|
1796
1798
|
imageResources?: ImageResources;
|
|
1797
1799
|
linkedFiles?: LinkedFile[]; // used in smart objects
|
|
1798
1800
|
artboards?: {
|