-
-
Notifications
You must be signed in to change notification settings - Fork 295
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
Lossless encoding/decoding of 10bit grayscale image stored as 16 bit pngs #562
Comments
Hi, The lossless round trip is possible, but requires bit shifting both before encoding AND after decoding. Below a Python POC, which makes use of pillow_heif: import numpy as np
import pillow_heif
# Create HEIF file from image in NDArray (dtype=uint16), and shift bits to MSB
out_file = pillow_heif.from_bytes(
mode="I;16",
size=(image.shape[1], image.shape[0]),
data=np.left_shift(image, 4 if pillow_heif.options.SAVE_HDR_TO_12_BIT else 6).tobytes()
)
# Lossless econding
out_file.save("image.heif", format="HEIF", quality=-1)
# Lossless decoding
in_file = pillow_heif.open_heif("image.heif", convert_hdr_to_8bit=False)
# Shift back to LSB
decoded_image = np.right_shift(
np.asarray(in_file, dtype=np.uint16)[:, :, 0], # Even if monochrome, pillow_heif returns a 3-channel image
4 if pillow_heif.options.SAVE_HDR_TO_12_BIT else 6
)
# Verify input and decoded arrays are equal
is_lossless = np.array_equal(image, decoded_image) |
@dr-eme just curious - is this code for and in which format |
Yes, I used pillow-heif 0.10.1 for this. The |
Last version(0.12.0) of |
this probably can be closed, as provided examples even they are on python - works. |
Hello,
Apologies if this is not the right place to ask questions but I couldn't find a forum or a Discussions tab.
I am trying to encode 10 bit grayscale images losslessly in heic. The images are stored as 16 bit png files (but only use the lest significant 10 bits).
If I simply use
the resulting heic image looks completely dark (using Preview.app on macos 12.0.1) so I guess
heif-enc
does not only use the 10 least significant bits. If I scale / bitshift or left replicate the original intensities in the input png, the generated heic file looks ok on preview.app but I can't get back the original values.If I simply use
the resulting png is an 8 bit rgb file. Using imagemagick seems to help there as I can generate 16bit images with
However, the result is not lossless. Is there a way to do such a lossless round-trip with libheif command-line tools?
To ease replicating my issue, below if a simple python script that generates the 10bit image on the fly:
Note that my question is very similar to that I have about doing this with ffmpeg:
https://stackoverflow.com/q/69739665/17261462
In the case of ffmpeg, achieving a lossless roundrip with HEVC is at least possible by using temporary rawvideo file:
https://stackoverflow.com/a/69874453/17261462
For ease of use, I am also attaching some sample pngs generated from teh python commands above.
LSB version:
![gradient10bit-lsb](https://user-images.githubusercontent.com/1614505/140723904-128087e8-6669-4f0b-9f88-74a875b37bda.png)
MSB version:
![gradient10bit-msb](https://user-images.githubusercontent.com/1614505/140724076-b441c463-1270-44ea-b164-7df94534062d.png)
LBR version:
![gradient10bit-leftbitreplication](https://user-images.githubusercontent.com/1614505/140724105-0eaf5709-6030-422c-8492-92976b13918f.png)
The text was updated successfully, but these errors were encountered: