Skip to content
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 for the non-primary image #308

Open
bigcat88 opened this issue Nov 6, 2024 Discussed in #307 · 3 comments
Open

Lossless encoding for the non-primary image #308

bigcat88 opened this issue Nov 6, 2024 Discussed in #307 · 3 comments

Comments

@bigcat88
Copy link
Owner

bigcat88 commented Nov 6, 2024

Discussed in #307

Originally posted by Foxify52 November 5, 2024
The following is an encoder i wrote to take advantage of the multi layer support avif has. Normally when using this code to encode data by itself in the first layer, it can encode and decode perfectly without any issue. as soon as you try and encode data and place it in a layer, it seems to ignore the lossless encoding i specified for those layers. I dont think its an issue with the package as much as a user error but it is one of those edge cases that might now have been accounted for. Any help would be appreciated.

Encoder:

import numpy as np
from PIL import Image
import pillow_heif
import zlib

pillow_heif.register_avif_opener()


def encode_to_image(data):
    binary_data = zlib.compress(data)
    side_length = int(np.ceil(np.sqrt((len(binary_data) + 3) // 4)))
    binary_array = np.pad(
        np.frombuffer(binary_data, dtype=np.uint8),
        (0, side_length**2 * 4 - len(binary_data)),
        mode="constant",
    ).reshape((side_length, side_length, 4))
    return Image.fromarray(binary_array, "RGBA")


base = Image.open("base.jpg")
encoded_images = [encode_to_image(b"Some binary data to encode")]
# Save the image
base.save(
    "output.avif",
    format="AVIF",
    save_all=True,
    primary_index=0,
    append_images=encoded_images,
    quality=-1,  # Required for lossless compression
    chroma=444,  # Required for correct color subsampling
    matrix_coefficients=0,  # Required to convert to RGB color space
)

Decoder:

import zlib

import numpy as np
import pillow_heif
from PIL import Image, ImageSequence

pillow_heif.register_avif_opener()

img = Image.open("output.avif")
bin_data = ImageSequence.Iterator(img)[1].copy()
reshaped_binary_array = np.array(bin_data)
flattened_binary_array = reshaped_binary_array.flatten()
binary_data_with_padding = flattened_binary_array.tobytes()
binary_data_without_padding = zlib.decompress(binary_data_with_padding.rstrip(b"\x00"))
original_binary_data = b"Some binary data to encode"
print(f"Original binary data: {original_binary_data}")
print(f"Decoded binary data: {binary_data_without_padding}")
print(
    f"Does the decoded data match the original data? {binary_data_without_padding == original_binary_data}"
)
@bigcat88 bigcat88 added bug Something isn't working enhancement New feature or request labels Nov 6, 2024
@bigcat88
Copy link
Owner Author

bigcat88 commented Nov 6, 2024

REMOVED, too tired, wrote a mess

@bigcat88 bigcat88 removed bug Something isn't working enhancement New feature or request labels Nov 6, 2024
@Foxify52
Copy link

Foxify52 commented Nov 6, 2024

I'm not sure if it would be a big inconvenience but could information about this be added into the documentations for future references? I don't believe there's much on configuration for non primary images.

@bigcat88
Copy link
Owner Author

bigcat88 commented Nov 6, 2024

I'll do a PR with implementation on the weekend and add it to the documentation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants