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
How to work with 16bit Gray Scale #30
Comments
Hi Klaus, your image is a 16-bit image and UPNG.js parses it correctly. The .data array is Uint8Array Typed Array, but it contains the correct 16-bit data (correct bits). The length of .data is 131328 Bytes, and with the area of 256x256 pixels, it corresponds to 2 bytes (16 bits) per pixel. You can convert it into an array of values between 0 and 65535, by reading pairs of bytes and connecting them together (PNG uses Big Endian). You can create a Uint16Array over the same ArrayBuffer, but JS uses Little Endian, so you have to reorder bytes in each pair. How else can I help you? |
I was about to create an issue for this but found this one. To me, it would make sense if UPNG handled this correctly. If it sees an image is 16 bits, it should provide Uint16Array instead of Uint8Array and handle the byte order internally. Please re-open this issue for discussion. |
The number 2,077,201 is 2,076,480 + 721 (height). Each row of pixels in PNG contains an extra byte with filtering method. UPNG "unfilters" data, but we keep it in the same Typed Array, to avoid allocating a new array (if your decompressed image was 3 GB big, allocating extra 3 GB would be a waste of memory). The property "data" contains the image data. It is accessible as bytes (octets), as it is the usual way of storing digital information in computers. It has nothing to do with color values of pixels - a color information of one pixel can have between 1 bit and 64 bits (8 bytes). PNG format supports not only 16 bits per sample, but also 1 bit, 2 bits, 4 bits, and 8 bits per sample. There can also be 1, 2, 3 or 4 samples per pixel (combinations of gray and RGB, with and without transparency). If we made 20 special functions, that would return an array of values between 0-1, 0-3, 0-15, 0-255, 0-65535, it would make UPNG quite messy. That is why we provide only UPNG.toRGBA8(), which converts any PNG into RGBA image, 8 bits per sample. If toRGBA8() is not appropriate for your use case, you can convert it into another structure yourself. Let me know if you need help with it. |
I'd definitely appreciate a bit of help. That makes sense. Is the extra byte (for filtering method) stored at the end or the beginning of each row? As you said, it would be messy to have lots of functions, but perhaps using a DataView would solve this issue? You could store the data once but allow accessing it in many ways. |
Filtering data is removed and the last 721 bytes of "data" are nonsense. So the first Width*Height*2 bytes are what you need. You can convert it to Uint16Array this way:
|
Is it basically the same solution if I want to get 16-bits per channel for my RGBA PNGs? I'm looking for a Uint16Array with indexes containing 16-bit values r,g,b,a,r,g,b,a, ... This line of code is blowing my mind: |
@mortac8 It is just converting big endian 16-bit integers into little-endian. |
Hi Photopea Thanks for this solution. It has helped me a lot so far! Unfortunately i'm stuck with the conversion to 16 bit. The resulting image contains only 0's. The 8 bit array before converting does not contain only 0's though. I've tried with several different images and they all result to being 0's. Would you mind pointing me in the right direction to solve this? |
@RalphCodesTheInternet What do you mean by a "conversion"? UPNG.js can not convert between 8 and 16 bit data. |
So basically I get a 16 bit PNG compressed image. The image was compressed by opencv and is sent to my JS side in base64 encoding. To decode base64 I did the following:
I removed the header and finally used UPNG to decode the PNG like this:
This essentially yields an 8 bit image like you mentioned before. I tried to convert it to 16 bits like you showed above, but the image then just contains 0 values.
|
UPNG.decode() should contain a 16-bit data in a Uint8Array buffer. If you need 8-bit RGBA data (e.g. to display it in a HTML5 canvas), use UPNG.toRGBA8(), as described in our manual. |
I do not need to display it in a canvas, I only require the raw 16 bit values of each pixel. Oh yes, and this is a gray scale image, so there is only one channel. I just cant figure out why all the values are 0 if the array returned by UPNG contains actual values. First console log is UPNG return, second log is the method you described to convert to 16 bit image. |
There are values [18,81,18,81 ... ], these values can not be converted to 0 if yo use my for loop.
|
Hi,
I am very interested in using the UPNG lib to handle 16BIT (grayscale) images such as this:
http://cosmin.users.sourceforge.net/testing/lena_16g_lin.png
When using the lib, I saw that data is is array is 8bit. As I need to do some transformation in the 16BIt space, is there anyway to access the 16bit data?
Klaus
The text was updated successfully, but these errors were encountered: