Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

error: maxMemoryUsageInMB limit exceeded when resizing large jpeg textures #344

Closed
bennlich opened this issue Aug 26, 2021 · 9 comments
Closed
Labels
bug Something isn't working package:functions

Comments

@bennlich
Copy link

bennlich commented Aug 26, 2021

Describe the bug
Resizing large jpeg textures fails with error: maxMemoryUsageInMB limit exceeded.

To Reproduce
Run gltf-transform resize --width 512 --height 512 on a model with an 8192x8192 jpeg texture.

Additional context
This seems to be an upstream bug in the scijs/get-pixels dependency. I opened an issue here: scijs/get-pixels#57.

@bennlich bennlich added the bug Something isn't working label Aug 26, 2021
@donmccurdy donmccurdy added this to the Backlog milestone Aug 26, 2021
@donmccurdy
Copy link
Owner

Hm, I suppose it has that limitation to avoid DoS attacks... but surprised it needs that much memory for an 8K texture, I would think that would be closer to 250 MB...

I've "wrapped" the get-pixels dependency already (https://github.com/donmccurdy/ndarray-pixels/) to provide web browser support, maybe there's some workaround there if theget-pixels maintainer doesn't have other suggestions.

Are you able to successfully run the script below for your model at https://gltf.report/? Pretty big memory ask for a web browser but worth a try... in this case it relies on Canvas 2D instead of get-pixels (which is Node.js-only).

import { textureResize } from '@gltf-transform/functions';
await document.transform(textureResize({size: [16, 16]}));

@donmccurdy
Copy link
Owner

Unfortunately there doesn't seem to be much to be done about this; it may be necessary to resize these images separately with a project like sharp. I'll keep an eye on the upstream bug on get-pixels.

@donmccurdy
Copy link
Owner

Related: #358

@proto-ziii
Copy link

Hi @donmccurdy, I'm still encountering this issue (8k texture, memory exceeded) with the 2.1.5 release.
I wonder if the @squoosh/lib integration should have fixed this? Also, I tried to run texture resize on gltf-Report with the same file and it worked just fine. Can you give me some hints here?

@donmccurdy
Copy link
Owner

Hi @proto-ziii! No changes have been made here, the summary is:

  1. node.js has limited memory
  2. the current resizing tool, ndarray-lanczos, is less memory-efficient than some alternatives in order to support both node.js and browser environments

I can't control the memory limits in browsers or node.js, so https://gltf.report/ may be able to access more memory than your node.js environment, or may have a lower memory footprint for other reasons.

More efficient resizers include squoosh/lib or sharp.js, and either could be used for custom versions of the textureResize() function. I'll likely switch to squoosh/lib for resizing only if a web build is published (GoogleChromeLabs/squoosh#1084).

@proto-ziii
Copy link

I see. Will try to impliment the sharp.js. Thanks for the details and this awesome project!

@hybridherbst
Copy link

Just wanted to chime in that I've also ran into this now, found this issue, and hoping for squoosh/lib integration at some point :)

@donmccurdy
Copy link
Owner

/cc #647

For folks running into this issue, the manual workaround for glTF files hitting this error would be to unpack the textures (if they aren't already separate) and resize large textures manually.

gltf-transform cp input.glb output.gltf

The number of textures and size of textures both contribute to memory limits, with ≤4K being generally recommended. Aim for powers of two on each side, like 512px, 1024px, or 2048px. The textures do not need to be square.

@timhc22
Copy link

timhc22 commented Aug 2, 2022

Yes this worked for me, thanks for the response on Stack Overflow @donmccurdy, what I did, for anyone else interested, was:

  1. Use blender to save a HUGE gltf as a 'separate' file (so the texture is separate).
  2. Use Photoshop/Gimp to resize the texture.
  3. Re-import into blender
  4. Export again as an embedded gltf
  5. Run npx gltfjsx ./myfile.gltf --types --shadows --transform --aggressive --draco https://www.gstatic.com/draco/versioned/decoders/1.4.1/ to squish it into a nicely sized glb file

When you do 5., the tsx generated might include a . in the file name, so either rename them in blender in step 3., or write typescript like so in the generated tsx:

type GLTFResult = GLTF & {
  nodes: {
    Mesh_0001: THREE.Mesh
  }
  materials: {
    'material_0.001': THREE.MeshBasicMaterial
  }
}

<mesh castShadow receiveShadow geometry={nodes.Mesh_0001.geometry} material={materials['material_0.001']} />

https://blender.stackexchange.com/questions/270593/how-to-use-blender-to-get-model-to-a-state-where-it-can-be-shrank-with-gltfjsx?noredirect=1#comment464073_270593

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working package:functions
Projects
None yet
Development

No branches or pull requests

5 participants