`:quality` option for `Image.write` values for PNG
Closed this issue · 5 comments
The docs for Image.write
state that quality can be a number between 1
and 100
. For PNG, however, passing a quality of 100
produces the following error:
GLib-GObject-CRITICAL **: 10:43:13.875: value "10" of type 'gint' is invalid or out of range for property 'compression' of type 'gint'
I imagine this is because PNG compression is between 1
and 9
. I'm happy to submit a PR but I'm not entirely sure how you would want to handle this. Should there be validation is the output is a PNG or just call it out? I wasn't quite sure but is it the :effort
in the png_write_option()
?
Steps to reproduce:
"some-image.png"
|> Image.open!()
|> Image.write!("some-resaved-image.png", quality: 100)
I'm using the latest version of Image on macos 13.1.
Thanks for the issue. Its tricky to find a common lexicon for image write options that can operate across different image types given the many different options in play.
As you point out, for .png
files, :quality
was a proxy for :compression
(not :effort
which is a separate parameter). :compression
needs to be in the range 1..9
and I wasn't conforming the:quality
parameter - which is in the range 1..100
for all image types - into the range 1..9
correctly for .png
images.
On reflection I think :quality
for .png
files is better expressed as the :Q
(quantisation level) parameter to Vix.Vips.Operation.pngsave/2
so I've pushed a PR that does that. And added the parameter :compression
for .png
files.
Net result:
:quality
for.png
files is now a proxy for:Q
. Like all image types,:quality
is in the range1..100
.:compression
is added as a valid parameter for.png
files.
Feedback is very welcome, and if you've the time a test run running from the main branch on GitHub to validate (or refute) would be great.
I'm now using the main
branch from github and it certainly works for my use-case! I'm actually not concerned about being able to output top-quality PNGs, it's that my image generator's input accepts a :quality
arg and can specify multiple output formats for one image. Testing that is how I cam across this. In reality, only JPGs would ever have a quality of 100
before they are converted to PDFs for printing. That is to say is that I have no business use-cases to test PNG quality. However, in the little test I did do, PNGs output with quality 1
and quality 100
are identical.
iex> image = Image.open!("whale.jpg")
iex> Image.write!(image, "quality-whale.png", quality: 100)
iex> Image.write!(image, "discount-whale.png", quality: 1)
iex> File.read!("quality-whale.png") == File.read!("discount-whale.png")
true
I tried other numbers than just 1
.
On further research its clear that :Q
for a png file is only effective if palletising the image. Which is why it has no effect in your example. I've changed the docs to say that :quality
has no effect for .png
images but the parameter remains valid for the reason you outline: to have consistent parameters for all formats where possible.
I think this resolves the issue, albeit not with total satisfaction. If you agree I'll close the issue.
I agree that it solves the issue albeit not with total general satisfaction; however, it more than solves it for my immediate needs, so by all means close this issue!
I realize that it's not totally true that I don't care about PNG quality as I need transparent fallback images for webp. While I know the default PNG quality is fine, I can certainly play around with it when testing. I had been completely off of image processing after my initial spike while I did several other spikes. I'm on the implementation step for images so hopefully I'll learn a thing or two to help out more.
it's a tricky situation. I think it's helpful to have a consistent set of "save" options that work predictably across different image types. The each type has its own considerations. I'd welcome any ideas and suggestions on how to make this better.
This library I'm treating as very "user requirement driven" so I look forward to your feedback on where there are gaps or issues that can filled or improved.