photopea / UPNG.js

Fast and advanced PNG (APNG) decoder and encoder (lossy / lossless)
MIT License
2.1k stars 259 forks source link

Uncaught RangeError: byte length of Uint32Array should be a multiple of 4 #74

Open otary opened 2 years ago

otary commented 2 years ago

I try UPNG.encode with several pictures, all of which reported the following errors

UPNG.js?c2e5:687 Uncaught RangeError: byte length of Uint32Array should be a multiple of 4
    at new Uint32Array (<anonymous>)
    at Function.UPNG.encode.framize (UPNG.js?c2e5:687:1)
    at Function.UPNG.encode.compress (UPNG.js?c2e5:597:1)
    at Object.UPNG.encode (UPNG.js?c2e5:434:1)
    at FileReader.fileReader.onload (image-compress.vue?ff39:40:1)

image

photopea commented 2 years ago

Did you read the documentation properly? The input of UPNG.encode() should be a raw picture in the RGBA format (four bytes per pixel). The length of your input array is not a multiple of 4.

E.g. if your image has one pixel, the input length is 4. If it has 2 pixels, the input length is 8. If the length of your input is 7, it makes no sense (maybe the red value of the second pixel is missing, only you know it).

otary commented 2 years ago

I try this, use toRGBA() first: ` const arrayBuffer = ...; const rgba8Img = UPNG.toRGBA8(UPNG.decode(arrayBuffer ));

const a = UPNG.encode([rgba8Img], 300, 300, 0) `

result: image

How to correctly convert the picture into rgba format (four bytes per pixel)?

photopea commented 2 years ago

In your example, rgba8Img is an array of frames, while [rgba8Img ] is an array with an array of frames. That is not the right input for UPNG.encode()

otary commented 2 years ago

image

I use a 32.8kb image for testing, The compressed image size is 32.4kb, while tinypng can be compressed to 18.4kb. It seems that the compression effect on ordinary PNG images is not obvious?

photopea commented 2 years ago

You should set the "cnum" parameter in UPNG.encode(), to for a lossy compression. E.g. try 256 or 50.