meltingice / psd.js

A Photoshop PSD file parser for NodeJS and browsers
MIT License
2.73k stars 389 forks source link

toPng collapse when psd include large image #242

Open xty1992a opened 2 years ago

xty1992a commented 2 years ago

Hello

I have some psd file, and I need export some image from it. my code like this

PSD.open(root("data/psd/1/地产20.psd"))
  .then(async (psd) => {
    const tree = psd.tree();
    const children = tree.children();
    const big = children.find((it) => it.name === "313682976"); // some image 5406 * 6235
    console.log(big.layer.image);
    return big.layer.image.saveAsPng(root("output.png")); // collapse
  })
  .then(() => {
    console.log("Finished!");
  })
  .catch((e) => {
    console.log("error", e.message);
  });

and the layder.image be like this

Layder.image ``` LazyExecute { obj: ChannelImage { layer: Layer { file: [File], header: [Header], mask: [Mask], blendingRanges: [Object], adjustments: [Object], channelsInfo: [Array], blendMode: [BlendMode], groupLayer: null, infoKeys: [Array], top: -637, left: -1046, bottom: 5598, right: 4360, channels: 4, height: 6235, rows: 6235, width: 5406, cols: 5406, opacity: 255, visible: true, clipped: false, layerEnd: 36230, legacyName: '313682976', objectEffects: [Function], layerNameSource: [Function], layerId: [Function], blendClippingElements: [Function], blendInteriorElements: [Function], locked: [Function], metadata: [Function], image: [Circular], node: [Layer] }, _width: 5406, _height: 6235, file: File { data: , pos: 52147406 }, header: Header { file: [File], sig: '8BPS', version: 1, channels: 3, rows: 5315, cols: 3543, depth: 8, mode: 3 }, numPixels: 33706410, length: 134825640, channelLength: 33706410, pixelData: [], channelData: [], opacity: 1, hasMask: false, startPos: 16114209, endPos: 150939849, channelsInfo: [ [Object], [Object], [Object], [Object] ], maskData: [] }, file: File { data: , pos: 52147406 }, startPos: 16114209, loaded: false, loadMethod: 'parse', loadArgs: [], passthru: [] } ```

then I got message like this

collapse message ``` <--- Last few GCs ---> [13840:000001FD3F55A360] 6818 ms: Scavenge 1040.1 (1058.2) -> 1031.7 (1061.9) MB, 3.9 / 0.0 ms (average mu = 0.848, current mu = 0.942) allocation failure [13840:000001FD3F55A360] 6826 ms: Scavenge 1043.6 (1061.9) -> 1035.3 (1065.2) MB, 3.8 / 0.0 ms (average mu = 0.848, current mu = 0.942) allocation failure [13840:000001FD3F55A360] 6835 ms: Scavenge 1047.1 (1065.2) -> 1038.9 (1068.7) MB, 4.0 / 0.0 ms (average mu = 0.848, current mu = 0.942) allocation failure <--- JS stacktrace ---> ==== JS stack trace ========================================= 0: ExitFrame [pc: 00007FF71FBDABBD] Security context: 0x0105560c08d1 1: decodeRLEChannel [000001AB9BEC0C81] [D:\work\2c-frontend\psd-parser\node_modules\psd\lib\psd\image_formats\rle.coffee:~28] [pc=00000078057459D3](this=0x009a26e375b9 ) 2: parseChannelData [0000007D70B25A19] [D:\work\2c-frontend\psd-parser\node_modules\psd\lib\psd\image_formats\layer_rle.coffee:13] [bytecode=00... FATAL ERROR: invalid array length Allocation failed - JavaScript heap out of memory 1: 00007FF71EFA180F napi_wrap+119407 2: 00007FF71EF487E6 v8::internal::OrderedHashTable::NextTableOffset+38102 3: 00007FF71EF495E6 node::OnFatalError+438 4: 00007FF71F785A6E v8::Isolate::ReportExternalAllocationLimitReached+94 5: 00007FF71F76DC21 v8::SharedArrayBuffer::Externalize+833 6: 00007FF71F61F3FC v8::internal::Heap::EphemeronKeyWriteBarrierFromCode+1436 7: 00007FF71F63C41B v8::internal::Factory::NewFixedArrayWithFiller+59 8: 00007FF71F63C3D1 v8::internal::Factory::NewFixedArray+65 9: 00007FF71F518E6F v8::debug::Script::GetIsolate+8527 10: 00007FF71F3C6EDA v8::internal::interpreter::JumpTableTargetOffsets::iterator::operator=+162938 11: 00007FF71FBDABBD v8::internal::SetupIsolateDelegate::SetupHeap+546925 12: 00000078057459D3 ```

my device is windows10, 16G ram. and node version is 12.20.0 psd version is 3.2.0

Good day.

MgenGlder commented 2 years ago

Hi @xty1992a, It looks like you may be using Node.js. Have you tried increasing the max memory usage of your node process with --max-old-space-size=<memory in MB>?

xty1992a commented 2 years ago

Hi @xty1992a, It looks like you may be using Node.js. Have you tried increasing the max memory usage of your node process with --max-old-space-size=<memory in MB>?

Yes but still.

I google this that say this flag is useless now

Versions of Node that are >= 12 should not need to use the --optimize_for_size and --max_old_space_size flags because JavaScript heap limit will be based on available memory.

And I had print the process. memoryUsage() before toPng and after.

when I export some image that smaller then the collapse one, It use about 100-200MB memory.

I`ll post the detail later : )

MgenGlder commented 2 years ago

Ahh interesting, in that case the process should use as much available memory as possible. Could either be that there's a leak somewhere in the code or that the file is just that dang large. Either way unfortunately don't have an easy solution to this. I'll take a look at the details if you post them.

xty1992a commented 2 years ago

sorry for waiting...

test code below

PSD.open(root("data/psd/1/地产20.psd"))
  .then(async (psd) => {
    const tree = psd.tree();
    const children = tree.children();
    const big = children.find((it) => it.name === "131369335"); // some image 3543 * 2657
    // const big = children.find((it) => it.name === "313682976"); // some image 5406 * 6235
    console.log(big.layer.image);
    console.log("before", process.memoryUsage());
    const png = big.layer.image.toPng();
    console.log("after", process.memoryUsage());
    return png;
  })
  .then(() => {
    console.log("Finished!");
  })
  .catch((e) => {
    console.log("error", e.message);
  });

the print

before {
  rss: 121024512,
  heapTotal: 26951680,
  heapUsed: 11277496,
  external: 74811088,
  arrayBuffers: 73624113
}
after {
  rss: 1889210368,
  heapTotal: 1790042112,
  heapUsed: 1754777680,
  external: 112403396,
  arrayBuffers: 111216381
}

You can download this psd for test also

MgenGlder commented 2 years ago

Interesting! Thanks for posting more information. I'm a bit locked up this week but I'll try and take a look at this case over the weekend.