-
Notifications
You must be signed in to change notification settings - Fork 624
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
OpenEXR support desired? #1473
Comments
I think OpenEXR would be a good addition. One of the hard parts would probably be mapping the complexity of the format down onto the simpler abstractions provided by this crate. |
In the worst case, we can decide to support only a small subset of exr images. I'll have a look into the exact abstractions of the image crate to estimate the amount of work for this feature. You will have to specify if the exr library needs some changes. I'm happy to add improvements to the exr library. For example, the exr crate always includes |
First challenge: The current exr implementation needs Would it be possible to get a seekable writer in the image crate? This would probably not be a backwards-compatible change. The only alternative I see, would be to write the exr image to an in-memory vector, which is |
Incidentally, |
The reasons to make it The only disadvantage is losing backwards compatibility. I guess this would be fine, as most people only write to files anyways. But you'll have to decide that in the end. |
I'm a little lost with the details of the implementation. I'm confused about the float pixel story. The Is it possible to store f16 or even f32 data in an image buffer? Will the high-dynamic-range values have to be clamped to the 0-1 range? Could we add true high-dynamic-range float processing to the crate? |
What I would suggest would be first to add a With that you should be able to implement the I think Does this all make sense? |
Sounds good. For image processing, f32 would be enough. We don't need f16 image processing, as f16 must always be converted to f32 anyways for calculations. Nevertheless, it would be nice to have f16 storage internally, to save memory. On the other hand, if you are choosing high quality as a user, you will probably use 32 bit anyways, at least while processing. When writing the file, letting the exr encoder convert the f32 values to f16 might be a nice feature later on. So my plan would be:
Given that this would probably add about 4-8 new variants to the color type enum, I wondered if it might make sense to split up the color type into two fields: Channels (e.g. L, LA, RGB, RGBA) and SampleType (U8, U16, F16, F32, ..). What do you think? |
We used to break up ColorType into two parts, but the vast number of combinations meant that almost all code declared most of them unimplemented. I think it would be good to think through how few additional variants could be added. In my view, a key role of a decoder is to convert the pixel data from the source format into a much smaller list of common encodings even if that conversion is sightly lossy or uses more memory. Thus, F16 types should be unnecessary because the F32 versions should work well enough. I've even been debating whether all four of {R32F, Rg32F, Rgb32F, and Rgba32F} are required so I'd be curious your thoughts on condensing down to a subset of those. We'll also need to clearly define what the floating point values mean. I think the usual meaning for high dynamic-range is that [0,1] is the usual image range and values greater than that are brightness values beyond what low dynamic range can represent. The |
Agree, f32 should be fine. Thinking this further... shouldn't
When only using
Yes, this will require some basic investigation. I think, most software handles in like this: 0 is black and 1 is white, meaning, 1 is the brightest color your non-hdr monitor could output. Defining (1,1,1) to be white could also work for the image crate. By the way, does the image crate convert the file pixels to sRGB or to linear RGB?
Even though an OpenEXR could contain arbitrary channels, I estimate that 95% of the time they will simply contain linear RGBA. The users who work with the remaining 5% of weird images would probably not use a generic image processing crate any ways. I guess the image-rs crate is used in places where you just want to open the damn RGB/RGBA image file already, regardless of the file format, and have a reliably RGB color. Furthermore, I have yet to see a luminance-only exr in real life, even though it may make sense to save memory. And I have never ever seen, or even used, RG images, so I would absolutely not support those with 2 channels right now haha. Therefore, I would suggest one of the following combinations (sorted by complexity, but the more the better I think):
Does someone of you have the time to implement the float precision stuff? I have attempted it but I realized this will take quite some time for me, as I'm not sure in which places changes need to be made. |
I agree. Unfortunately removing it now is a rather large change because it is entangled with a lot of the rest of the library and would also have the potential to break a bunch of downstream users (though we don't actually have a great sense of how many). Hopefully, we'll be able to do it at some point. This is part of the reason I'm hesitant to add more color types than necessary: it is very hard to remove them later...
Currently the crate does no conversion. The output color space in whatever the original file had.
I think either (1) or (2) would be best. I'm not quite sure what you mean by float precision stuff though. Are you talking about converting f16 -> f32? |
Cool. With float precision I mean actually implementing the F32 ColorFormat, which seems rather involved to me. I had the impression that adding F32 would be a lot easier if there was no Bgr variant and the color format was actually two separate enum ... at least that's what I thought on first glance, because then it would be possible to use generics much more abstractly. But I don't know for sure, I hope a contributor with more experience could estimate the workload of adding the F32 color type :) Removing the Bgr color type variant of course wouldn't mean removing the whole Bgr feature. It would probably be great to still have a method called |
Just adding ColorType::Rgba32F and ExtendedColorType::Rgba32F is not very much work. Deeper integration would be more involved, but I'd suggest leaving that for a followup. |
Well.. It depends. In jpeg for example we do CMYK -> sRGB but that is a bug. That issue also demonstrates why doing actual conversion is difficult: One has to parse and understand the exact colorimetric definitions in full, and be able to convert efficiently. Both should at least be optional since doing them in hardware is likely much more efficient. Still, doing normalizations such as I'm not sure if exr has this feature but in some cases a single unit of color values (texel) encodes more than one pixel. A common example is YUV420 where two chroma components are subsampled and apply to blocks of 2×2 pixels. It's slightly questionable if we should expand these because this increases the size, it's not obvious subsampling convention to apply (duplicate or interpolate values) and for read-only textures it is much faster if it's done in hardware later. |
Solid points, for sure.
Yes this can happen when opening an exr file, however the rust implementation does not support that yet
I was able to do exactly these changes on my own, haha. I thought it will also be necessary to adjust the |
Yeah, you can already create an |
Exr supports quite some color space meta data: Maybe these can be used to convert the RGB data to a unified color space that the image crate defines |
Interesting. What are currently the consequences of this mismatch? Will the image processing functions work as expected? |
I'd argue we should add both |
Here is some simplified calculation to convert the exr linear data to RGB. Do you think it would make sense to add at least an opt-in conversion for every image format to CIE XYZ? Otherwise, saving the image data of one format to another format will not produce the same image. Also, if you do any kind of color interpolation, the color space should at least be linear right? Not sRGB |
Clamped XYZ as in your example is surely not a 'universal' color space, and even unclamped only makes a limited amount of sense for that purpose. As even that assumes that we only need to transform between color spaces for a particular human observer and using the same whitepoint, which is quite short sightned imho. Conversion between different whitepoints/viewing conditions can inherently not be completely lossless in a tri-stimulus model, you'll need a vastly more complex model to come even close. And it does not hold in general that any sequence of color space conversion is possible, or reversible. In total, the most future proof interface is one that does not assume this from the start. I think the best we can do is to clearly ensure there is an method that returns an optional conversion interface to CIE XYZ or any particular output color space. Clearly, that implies that we may want to avoid doing that transformation implicitly as this raises some amount of awareness to the necessary complexity and differentiates different failure modes (failure to decode vs. failure to bring to a unified color space). |
Well yeah right. There are existing color conversion crates so that's not something the image crate must include. However as a user of the image library I have probably a lot less knowledge about the particular color space of a specific image format, or color theory in general, than you seem to have. If the point of this library is to provide a uniform interface to the pixels of images, regardless of format, I would expect it to unify the color handling as well. Especially since the RGB colors are all exposed through the same struct This does not mean that all values are converted to a particular color space. Maybe being very explicit about the color space would be enough, maybe having |
Also, does the image processing part of the library simply produce incorrect results if the user does not convert his images to an appropriate color model on their own (depending on the format and meta data in the image)? |
I want to add that |
Sounds nice |
Very fascinating read. I'm still in the middle, of it, so please forgive me if I get something wrong :D Completely different topic: https://docs.rs/cint/0.2.1/cint/ This is a crate that aims to provide a unified interface to colors. No conversion methods, only traits. That way, we could communicate the exact color type of an image without forcing the user to use a specific crate for their color calculations, it's very lightweight. Maybe this would be worth a discussion? |
I'm not sure the interface in that crate is quite right for us. It seems to assume that the color space is known at the type level (or tracked individually for each pixel perhaps?). We could just implement If I understand correctly, the more useful thing for us would be an enum of different possible colorspaces so we could store / communicate that once per image. |
Yeah seems like they don't have dynamic color spaces (yet?) (except a custom color space enum, but that misses the point of standardized interface). |
On the other hand .... Nothing would stop us from defining a precisely crafted enum, for example enum ExrPixels {
LinearRgb(Vec<cint::LinearRGB<f32>>),
YCbCr(Vec<cint::YCbCr<f32>>),
}
type JpegPixels = Vec<cint::sRgb<u8>>;
... Which would be much more concise than a generic single dynamic pixel type for all images types. |
I came here to make this exact suggestion. |
Cool. Frankly, the exr library has to get at least one larger update so we can give it non-sendable read and write objects. Therefore it will be a few days or weeks until we can support this, even on the most basic level. |
In order to not stray too far, I propose we continue parts of the discussion in separate Colorspace and Float Support issues. @fintelia will the master branch receive the float support implementation you linked earlier, or was it only meant to be an example? |
That commit I linked was only meant as an example; I wasn't planning on merging it anywhere. |
Ok, gotcha. I'll probably do a separate PR for float support. Which branch should I chose for this change? |
If you don't need to make any breaking changes, just target master |
I have browsed the issues regarding color spaces and color models and color profiles. It seems to me that there are currently great efforts being made to work out a solid color concept for the whole crate. Is there a single document or issue where the color concept is outlined or discussed? I'm asking because as far as I know, we still have not settled on the meaning of the float colors, right? For adding exr, I'd like to have a clear vision for float colors. |
Initial OpenEXR support was just merged 🎉 It has some limitations. Basically, the format supports only |
Hi! Im the creator of the pure Rust implementation of the OpenEXR format. Would you be interested in having EXR support? I'd be happy to implement that and would create a PR if this is valuable :)
The EXR crate already supports most images. Only one compression method and a few special features are still on the roadmap. Simple RGBA images already have great support, and can be read and written.
OpenEXR is a popular image format, especially in VFX workflows, as it stores real floating-point pixels which can be compressed losslessly or lossy. Pixels can contain any type of channels, for example RGBA, LAB, CMYK, XYZ, or even depth and motion vectors. Arbitrary meta data can be added to any image. Most software already supports exr.
The text was updated successfully, but these errors were encountered: