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

Support for 1-bit Grayscale #2096

Open
fosskers opened this issue Jan 12, 2024 · 4 comments
Open

Support for 1-bit Grayscale #2096

fosskers opened this issue Jan 12, 2024 · 4 comments

Comments

@fosskers
Copy link

fosskers commented Jan 12, 2024

Thank you for this library, my company uses it for a variety of tasks.

I would like to be able write images that are encoded in 1-bit grayscale. I have such an image on-hand which unfortunately decodes into a Luma8 underneath, effectively 8x-ing the filesize when rewritten.

I discovered this by first noticing that my large image whose dimensions I had vastly shrunk and rewritten actually had increased its file size by 50% (12mb -> 18mb with default settings). I then inspected the input and output images with ImageMagick's identify tool to discover that the input image was 1-bit grayscale while the output's is 8-bit grayscale.

Draft

  • The DynamicImage enum should gain a new variant: ImageLuma1.
  • ColorType would need a new variant: L1
  • Perhaps bool would need to be given an impl of Primitive.
  • Some additional type alias like GrayImage would need to be provided, but wrapping Luma<bool> instead.

Overall this should drastically reduce output image sizes for Grayscale images that don't want to use the full 8-bit channel depth.

@fosskers
Copy link
Author

fosskers commented Jan 12, 2024

In the input image, we see (some fields redacted):

Geometry: 13244x71130+0+0
Channels: 2.0
Channel depth:
    Gray: 1-bit
Channel statistics:
    Pixels: 942045720
Colors: 2
Histogram:
      56641321: (0,0,0) #000000 gray(0)
     885404399: (255,255,255) #FFFFFF gray(255)
Filesize: 11.771MiB

while in the output image (processed by image) we see:

Geometry: 6904x37079+0+0
Channels: 2.0
Channel depth:
    Gray: 8-bit
Channel statistics:
    Pixels: 255993416
Colors: 256
Histogram:
  (many entries)
Filesize: 15.3349MiB

1/4 the number of pixels, yet a larger file size.

@fintelia
Copy link
Contributor

fintelia commented Jan 12, 2024

A bunch of places in this library require that pixels are an integer number of bytes, which would break for ImageLuma1.

However, that doesn't mean we cannot support Luma1 images for limited cases. We already have ExtendedColorType::L1 to describe the color type and the ImageDecoder::original_color_type method to reveal that a conversion is being applied. We've also been wanting to switch the ImageEncoder trait to allow passing any ExtendedColorType when writing image (while still allowing individual format encoders to reject color types they do not support). At that point, we'd be able to start adding Luma1 support to individual encoders

@fintelia
Copy link
Contributor

Update on this: as of the 0.25 release, ImageEncoder::encode now takes an ExtendedColorType. If anyone is interested in adding 1-bit grayscale support to any of our encoders, it should now be possible

@fosskers
Copy link
Author

Thanks for the update!

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