Automattic / node-canvas

Node canvas is a Cairo backed Canvas implementation for NodeJS.
10.21k stars 1.17k forks source link

canvas.loadImage(src) got exception "Out of memory" #1735

Open VIIGstar opened 3 years ago

VIIGstar commented 3 years ago

Issue or Feature

Hi, I had trouble with load image by canvas that always got out of memory exception. My device still can load image has size larger than 80MB without any problem except this image (16.8MB) https://pbimg.btdmp.com/pbase/shop-id/10117363/artworks/2141699b41cb8b5b454ffbd0380e247b.png

Steps to Reproduce

const _canvas = require('canvas')

_canvas.loadImage('https://pbimg.btdmp.com/pbase/shop-id/10117363/artworks/2141699b41cb8b5b454ffbd0380e247b.png')
    .catch((e) => {
      console.log(e)
  })

Exception:

Error: out of memory
    at setSource (/home/beeketing/code/front/print-2d-render/node_modules/canvas/lib/image.js:91:13)
    at get.concat (/home/beeketing/code/front/print-2d-render/node_modules/canvas/lib/image.js:59:11)
    at concat (/home/beeketing/code/front/print-2d-render/node_modules/simple-get/index.js:89:7)
    at IncomingMessage.<anonymous> (/home/beeketing/code/front/print-2d-render/node_modules/simple-concat/index.js:8:13)
    at Object.onceWrapper (events.js:273:13)
    at IncomingMessage.emit (events.js:187:15)
    at endReadableNT (_stream_readable.js:1094:12)
    at process._tickCallback (internal/process/next_tick.js:63:19)

Your Environment

goldenjayr commented 3 years ago

also getting the same problem

zbjornson commented 3 years ago

I can't reproduce this issue. The image loads successfully for me, with about 33,661,225 bytes of ArrayBuffers allocated. Can you provide more info please?

VIIGstar commented 3 years ago

Just run the above function then my app still crashed

also getting the same problem

He got the same problem.

@zbjornson what kind of information do you want more?

viktor-silakov commented 3 years ago

I also have the same problem, the code is very simple:

const {loadImage} = require('canvas')
loadImage('605cccb8b4745c1f0d1a79c4.png').then((image) => {
})

The Image: 605cccb8b4745c1f0d1a79c4

I reproduced this 100% both on Mac and Linux, at the same time - images with greater size (more than 10Mb) processing without problems, the problems are only with such certain images.

Stacktrace:

(node:88422) UnhandledPromiseRejectionWarning: Error: out of memory
    at setSource (/Users/vsilakou/Projects/Syngrisi/syngrisi-app/node_modules/canvas/lib/image.js:91:13)
    at Image.set (/Users/vsilakou/Projects/Syngrisi/syngrisi-app/node_modules/canvas/lib/image.js:62:9)
    at /Users/vsilakou/Projects/Syngrisi/syngrisi-app/node_modules/canvas/index.js:34:15
    at new Promise (<anonymous>)
    at loadImage (/Users/vsilakou/Projects/Syngrisi/syngrisi-app/node_modules/canvas/index.js:23:10)
    at Object.<anonymous> (/Users/vsilakou/Projects/Syngrisi/syngrisi-app/debug2.js:2:1)
    at Module._compile (internal/modules/cjs/loader.js:1063:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
    at Module.load (internal/modules/cjs/loader.js:928:32)
    at Function.Module._load (internal/modules/cjs/loader.js:769:14)
ghost commented 3 years ago
  panel.body = await loadImage(process.cwd() + "/src/img/none/body.png");
  panel.banner = {};
  panel.banner.front = await loadImage(process.cwd() + "/src/img/none/banner-front.png");
  panel.banner.back = await loadImage(process.cwd() + "/src/img/none/banner-back.png");
  panel.avatar = {};
  panel.avatar.front = await loadImage(process.cwd() + "/src/img/none/avatar-front.png");
  panel.avatar.back = await loadImage(process.cwd() + "/src/img/none/avatar-back.png");

  const wallpaper = await loadImage(process.cwd() + "/src/img/blurple.png");
  const avatar = await loadImage(process.cwd() + "/src/img/blurple.png");

got this..

(node:6584) UnhandledPromiseRejectionWarning: Error: out of memory
    at setSource (C:\Users\Asus-Lapiz\Desktop\Canvas\node_modules\canvas\lib\image.js:91:13)
    at Image.set (C:\Users\Asus-Lapiz\Desktop\Canvas\node_modules\canvas\lib\image.js:62:9)
    at C:\Users\Asus-Lapiz\Desktop\Canvas\node_modules\canvas\index.js:34:15
    at new Promise (<anonymous>)
    at loadImage (C:\Users\Asus-Lapiz\Desktop\Canvas\node_modules\canvas\index.js:23:10)
    at C:\Users\Asus-Lapiz\Desktop\Canvas\src\app.js:43:22
    at Layer.handle [as handle_request] (C:\Users\Asus-Lapiz\Desktop\Canvas\node_modules\express\lib\router\layer.js:95:5)
    at next (C:\Users\Asus-Lapiz\Desktop\Canvas\node_modules\express\lib\router\route.js:137:13)
    at Route.dispatch (C:\Users\Asus-Lapiz\Desktop\Canvas\node_modules\express\lib\router\route.js:112:3)
    at Layer.handle [as handle_request] (C:\Users\Asus-Lapiz\Desktop\Canvas\node_modules\express\lib\router\layer.js:95:5)
thsking commented 1 year ago

I'm aware it woudln't help for every case. But after looking for a solution for so many time. I finally find a work around ... Use .jpg image instead of a png.

miroljub1995 commented 3 months ago

@zbjornson We have the same issue with version 2.11.2. Here is a minimal repro, where I have two images with the same pixels, but one is with, other without metadata. The one without metadata works fine, I guess it's something with metadata size:

import { loadImage } from "canvas";

loadImage(
  "https://drive.usercontent.google.com/uc?id=1W06MmK-FCYGr1OLdH5ydH1huaFJRL1q0&export=download",
).then(console.log);

loadImage(
  "https://drive.usercontent.google.com/uc?id=1QJAt2l3xozu2XUntQLIdZM_CSSBOKDiE&export=download",
).then(console.log);