photopea / UPNG.js

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

Is it possible to reverse PNG compression? #33

Closed dannyrb closed 5 years ago

dannyrb commented 5 years ago

👋 Hi! First and foremost, thanks for creating and sharing this library. It's the only high quality PNG web encoder/decoder I've been able to find, and it's enabling us (and I'm sure many others) to do great things ^_^

Where I'm at

I have an input image that, uncompressed, decodes with the following information: ~140kb

{
    ctype: 0,
    data: Uint8Array [],
    depth: 16,
    frames: [],
    height: 512,
    tabs: {tEXt: {…}},
    width: 512,
}

And I'm able to follow the steps you've laid out in this thread to convert the original image's data to a Uint16Array[]. Which I then use in cornerstonejs to display and manipulate medical images (it supports Uint8Array[] and Uint16Array[] pixel data for it's WebGL implementation; using individual pixel values as intensities to render)

The problem

When I run it through http://upng.photopea.com/, at the highest quality (lossless), it decodes with: ~3.8kb

{
    ctype: 3,
    data: Uint8Array [],
    depth: 2,
    frames: [],
    height: 512,
    tabs: {PLTE: Array(12)},
    width: 512,
}

So the compression works great! When we're talking over a few petabytes of data, and many, many thousands of images, that really adds up for us. What I'm having trouble figuring out is how to reverse the compression, or use the decoded information from the compressed image, to provide a Uint8Array[] or Uint16Array[] the library I'm using can work with.

I'm not sure why the color type changed, or how it impacts things. When attempting to use the same logic that worked for the original image with the decoded image, I see it rendered as "repeating" 8 times. I assume this is related to the change in depth.

I will continue to play around, and I'll post my findings here. Any/all help is appreciated. If you feel that this is not the appropriate place for issues of this nature, please feel free to close my question.

dannyrb commented 5 years ago

After reading up on the PLTE chunk, and how color type 3 uses color palletes, I don't believe, despite selecting highest quality that the compressed image is "lossless" in the sense that the original pixel values can be found; but rather "lossless" in that the rendered image will look the same as the input image.

dannyrb commented 5 years ago

Thanks for letting me flood your comments! I'll continue to use this library as a decoder where PNG is the more efficient format for storing lossless image data. If you have any additional thoughts, I'd love to hear them, but I think it's safe to close this issue :+1:

photopea commented 5 years ago

Hi Danny, please, read the main site to learn how to Decode PNG images.

var img  = UPNG.decode(buff);        // put ArrayBuffer of the PNG file into UPNG.decode
var rgba = UPNG.toRGBA8(img)[0];     // UPNG.toRGBA8 returns array of frames, size: width * height * 4 bytes.

the "rgba" will be an ArrayBuffer. You can view it by creating an ArrayBufferViewer, e.g. var data = new Uint8Array(rgba); .

Is there anything else I can help you with?