AcademySoftwareFoundation / OpenImageIO

Reading, writing, and processing images in a wide variety of file formats, using a format-agnostic API, aimed at VFX applications.
https://openimageio.readthedocs.org
Apache License 2.0
1.95k stars 586 forks source link

[FEATURE REQUEST] ImageOutput.supports("quality") #3859

Open devernay opened 1 year ago

devernay commented 1 year ago

Is your feature request related to a problem? Please describe. There is no way to check if an output format supports a quality setting, other than scrubbing the code for uses of decode_compression_metadata(). This is an issue for programs that want to expose quality in the GUI, especially when new formats are being added to OIIO.

Describe the solution you'd like Add a "quality" feature for output formats Of course that wouldn't always work with formats that support different compression methods (eg TIFF or EXR), but those are rather limited.

Describe alternatives you've considered Testing for the format name manually and using prior knowledge about the format or scrubbing the OIIO source code.

lgritz commented 1 year ago

So you just want to add this one additional query that allows you to ask if any quality setting is available?

What if the format supports several compression methods, and some allow a quality setting but others do not? And what about if different formats and/or compression methods have different quality scales, like jpeg wants a 1-100 scale with smaller numbers being more aggressive compression, deflate compression wants a 1-9 (but actually it's a size/time tradeoff and all levels are lossless), and OpenEXR's dwaa compression has an unbounded scale with larger numbers meaning more aggressive compression and lower quality?

I think that this starts to touch on a really interesting problem, which is that the interface of

bool supports (string featurename)

is pretty narrow in its expressiveness. I mean, it was fine for "can it write tiled images" or "can it write arbitrary metadata", and it was also easy to implement because most of the formats supported only a few of the possible features (many of them supported none). But that interface it's not well suited for more complicated queries we might wish to make.

How should we grow to allow a more flexible set of queries? And there are two axes to potentially grow:

(a) Accepting more than a fixed set of "feature strings". For example, maybe something like supports("channels:4") would be asking "can I use this format to write a 4-channel image?" or supports("resolution:80000x100000") might mean "can you output this particular resolution, or is it too large?" But then, ick, that means that on the output format side, the implementation of supports() is not enough to just have the small list of fixed feature names that it answers "true" -- now we're talking about having to parse the queries in more complex ways.

(b) Returning more than a true/false answer. Examples: it might be handy to ask for the list of compression types that a file format supports, or the list of data types acceptable for pixels, etc. How general should we get in the kinds of data we can ask for?

I think this whole set of problems would be a great one for one or more people to investigate, consider the tradeoffs (between richness of queries for the "client", and complexity burden on the authors of format I/O modules to be able to correctly answer all of the possible queries), and make a proposal to the group for how we might grow the OIIO APIs to accommodate what we'd like to accomplish.

devernay commented 1 year ago

Most image formats either support a quality setting or do not, because they are tied to a single "codec. TIFF and EXR are container formats that support many compression codecs. They are the only exception for now, and I hope it will stay that way.

I was making this suggestion, because I wrote some code a while ago that exposed a "quality" parameter from 0 to 100 for JPEG, but then oiio started supporting webp, heic and avif, and my code couldn't detect that they also had a "quality" parameter. All these support values in the 0-100 range.

DWA is different, but previously it was handled using the openexr:dwaCompressionLevel attribute, which is not supported anymore because it is overwritten here.

ZIP is really not a quality anyway: zlib calls it "level". And it's not an image format.

So I wouldn't be terribly upset if supports("quality") returned false for EXR and TIFF, and returned true for jpeg, webp, heic, avif...

However, maybe there's a better solution which is to query the "compression" itself. so maybe something like ImageOutput.getCompressionQualityRange("dwaa") would return (0,INT_MAX, LOWER_IS_BETTER)?