节点画布 getImageData() 内存不足

问题描述

我有一个转换图像的 nodejs 应用程序。 我在 pm2 中使用 32gb 内存运行我的应用程序。 尝试获取图像的图像数据时,出现此错误。 我尝试使用 --max-old-space-size 增加节点 js 内存限制 尝试将其增加到 8192 和 32678,但我仍然收到错误消息。

 m[9161:0x41069d0]    18179 ms: Mark-sweep 22.3 (29.2) -> 22.0 (25.2) MB,23.0 / 0.0 ms  (+ 1.5 ms in 5 steps since start of marking,biggest step 0.8 ms,walltime since start of marking 55 ms) (average mu = 0.998,current mu = 0.963) finalize incremental m[9161:0x41069d0]    27013 ms: Mark-sweep 23.2 (25.2) -> 22.2 (25.2) MB,3.8 / 0.0 ms  (+ 0.1 ms in 2 steps since start of marking,biggest step 0.1 ms,walltime since start of marking 168 ms) (average mu = 0.999,current mu = 1.000) finalize incremental m

<--- JS stacktrace --->

==== JS stack trace =========================================

Security context: 0x21639e1c08d1 <JSObject>
    0: builtin exit frame: getimageData(this=0x0529133cc801 <CanvasRenderingContext2D map = 0x381c66f8e359>,32150,22958,0x0529133cc801 <CanvasRenderingContext2D map = 0x381c66f8e359>)

    1: getPoints [0x324589ad9b31] [/var/apps/print-export-worker/getPoints.js:11] [bytecode=0x340f496a0d29 offset=86](this=0x2d04988cd319 <JSGlobal Object>,0x0529133cc801 <CanvasRenderingContext2D map = 0x381c...

Fatal error: v8::ArrayBuffer::New Allocation Failed - process out of memory
 1: 0xa09830 node::Abort() [node]
 2: 0xa09c55 node::OnFatalError(char const*,char const*) [node]
 3: 0xb7d71e v8::Utils::ReportOOMFailure(v8::internal::Isolate*,char const*,bool) [node]
 4: 0xb7da99 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*,bool) [node]
 5: 0xb7db7b  [node]
 6: 0xb9b93e  [node]
 7: 0x7f7f87de455f Context2d::GetimageData(Nan::FunctionCallbackInfo<v8::Value> const&) [/var/apps/print-export-worker/node_modules/canvas/build/Release/canvas.node]
 8: 0x7f7f87dd91f9  [/var/apps/print-export-worker/node_modules/canvas/build/Release/canvas.node]
 9: 0xbe96a9  [node]
10: 0xbeb497 v8::internal::Builtin_HandleApiCall(int,unsigned long*,v8::internal::Isolate*) [node]
11: 0x13c5c79  [node]
Aborted

解决方法

事实证明,我需要做的就是将我的节点版本升级到 14Lts。版本 12 有一些限制。

,

另一种不使用节点画布从图像中获取图像数据的方法是使用像这样的sharp。

sharp(canvas.toBuffer(),{ limitInputPixels: false })
  .raw()
  .ensureAlpha()
  .toBuffer()
  .then((img) => {
    let imageData = new Uint8ClampedArray(img)
    return imageData
  })
  .catch(err => {
    console.log('ERROR IN SHARP',err)
    reject(err)
  })

如果您正在处理大图像,它必须使用 limitInputPixels 为 false。