photopea / UPNG.js

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

16-bit per channel PNG to Uint16Array? #54

Closed mortac8 closed 4 years ago

mortac8 commented 4 years ago

Is it possible to get values from a 16-bit per channel PNG as a Uint16Array?

photopea commented 4 years ago

Hi, sure! The object returned by UPNG.decode() has a property "data" with 16-bit raster data of the image.

If you want to use the same ArrayBuffer, you need to swap pairs of bytes from big endian to a little endian.

See here: https://github.com/photopea/UPNG.js/issues/30

mortac8 commented 4 years ago

Edit: If I do a >> 8 on all my 16-bit values after your endianness code then all the 8-bit values seem right. Maybe I hosed my webgl2 viewer...argh.

I read through the comments on issue #30 but I have a RGBA image I need help with. Can you advise? I think I need to modify the endianness code your provided. Sorry to bother you again.

http://www.schaik.com/pngsuite/basn6a16.png upngHelp

fetch("basn6a16.png")
  .then(function(response) {
    return response.blob();
  })
  .then(function(blob) {
    console.log("here's your blob");
    console.log(blob);
    blob.arrayBuffer()
  .then(function(buffer) {
        console.log("here's your arraybuffer");
        console.log(buffer);
        let img  = UPNG.decode(buffer); // put ArrayBuffer of the PNG file into UPNG.decode
        console.log("UPNG ArrayBuffer");
        console.log(img);
        let area = img.width * img.height *4;
        let nimg = new Uint16Array(area); // or just  nimg = [];
        for(let i=0; i<area; i++) nimg[i] = (img.data[i*2]<<8) | img.data[i*2+1];
        console.log("UPNG modified");
        console.log(nimg);
  });
});
photopea commented 4 years ago

BTW. the domain http://www.schaik.com/ does not work for me :(

I opened the basn6a16.png in Photopea.com (which uses UPNG.js) and it seems to work correctly (as your example on the right).

If you need to open any PNG image as a 8-channel RGBA image, use UPNG.toRGBA8(....).

The images in your screenshot look different. I think it could be because of additional multiplying or dividing the RGB values by alpha value.

mortac8 commented 4 years ago

Your comment was very helpful. It turns out I had to set {premultipliedAlpha: false} on my webgl2 context which fixed the visual differences.