-
Notifications
You must be signed in to change notification settings - Fork 3
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
Extract out Color
module into a separate crate?
#57
Comments
I could use these color definitions in the |
Revive https://github.com/image-rs/image-core with this, sure. Developing the The non-exhaustive nature shouldn't be a conceptual problem; while the current conversion code isn't fallible in the API, it really should be for instance for certain invalid encodings. With regards to the conversion implementation, I'm not so sure whether it's a good idea to use it for the pixel types. Indeed, the 'path' (as per definition in the documentation) between two color variants is far from unique. The optimal method for conversion depends a lot on the environment: whether it be SIMD availability or lookup-table caches you may have read from disk first or even offloading / gpu / apu accelleration, there may be multiple bit-for-bit equivalent solutions to that numerical problem. The type conversion however doesn't lend itself well for the opaque environment parameters you'd need to solve this decision problem efficiently and transparently, though. That's at least my thought process on avoiding some mistakes you can observe in practice in C's locale design conflicts, it seems quite analogous. Not that it needs to stop us from extracting the types, there are re-uses enabled by this which would benefit without running into such design troubles. |
Thanks for the insight, I'd imagine if there were multiple types of conversions we could make a trait per conversion type such as: I don't have any permissions in the Perhaps the name |
I've tried to tackle the conversion problem generically in the Definitely agree that there are common pairs of formats that should have SIMD. Handling the superset of all color formats unfortunately brings in a century worth of dead analog TV signals that have been immortalized in H.26x and AV1. |
I think I've got an idea for both type-level pixel conversion and enum-value-based pixel conversion in a single interface: trait HasColorSpace {
type ColorSpace;
}
trait IntoXyz: HasColorSpace {
fn into_xyz(self, color_space: Self::ColorSpace);
}
trait FromXyz: HasColorSpace {
fn from_xyz(self, color_space: Self::ColorSpace);
}
impl<T, U> ColorConvert for T
where
T: IntoXyz,
U: FromXyz,
{
fn convert(self, source_colorspace: T::ColorSpace, destination_colorspace: U::ColorSpace) -> U;
}
// Strongly-typed pixel using a type-level implementation:
pub struct Srbg(rgb::Rgb);
impl HasColorSpace for Srgb {
// it needs no extra run-time color space information
type ColorSpace = ();
}
// Impl for a Weakly-typed enum-based pixel:
pub struct RgbColorSpace {
primary: Primaries,
transfer: Transfer,
whitepoint: Whitepoint,
luminance: Luminance,
}
impl HasColorSpace for rgb::Rgb {
// this type requires run-time colorspace information
type ColorSpace = RgbColorSpace;
}
// Maybe even a generic-based Rgb type:
pub struct GenericRgb<Primary, Transfer, Whitepoint, Lumniance> {
inner: rgb::Rgb,
primary: PhantomData,
transfer: PhantomData,
whitepoint: PhantomData,
lumniance: PhantomData,
};
impl HasColorSpace for GenericRgb {
// it still needs no extra run-time color space information
type ColorSpace = ();
}
// and so on and so forth... We could even provide specialized conversions that skip Would this work as a unified interface for both type-level and enum-level pixel colorspaced types? |
How does this interface handle preparation of lookup tables? Some conversions are computationally expensive. Some like gamma change are simple lookups, and some multi-dimensional changes only have LUTs for part of the calculation. For better SIMDification, conversion could take slices. There's also YUV to RGB conversion that involves chroma subsampling and chroma sample position, which is painful to design API for. YUV may be planar with a padding between the lines. |
That's a good point, there's also the possible optimization for large enum-based color-space conversions when doing bulk amounts of the same run-time color space conversion that you don't want to keep running the match statements for each color-space parameter (like Perhaps for these scenarios such a preperation based API could also be provided that allows things like lookup tables to be implemented also? Something like: trait HasColorSpace {
type ColorSpace;
}
trait FromPixel<T>: HasColorSpace {
fn convert(pixel: T, source_colorspace: T::ColorSpace, destination_colorspace: Self::ColorSpace) -> Self;
fn get_converter(source_colorspace: T::ColorSpace, destination_colorspace: Self::ColorSpace) -> impl FnMut(pixel: T) -> Self;
} So for this trait |
It may be best to separate color definition enums from color conversion implementations, because the implementations can be pretty messy. |
Great points. Perhaps then the conversion traits should work on an image-level rather than a pixel-level which would allow using the full trait HasColorSpace {
type ColorSpace;
}
type Image<P> = Vec<P>;
trait ImagePixelConvert<P>: HasColorSpace
where P: HasColorSpace
{
fn convert(image: Image<P>, source_colorspace: P::ColorSpace, destination_colorspace: Self::ColorSpace) -> Image<Self>;
}
impl ImagePixelConvert<Rgb> for Yuv {
fn convert(..) -> Image<Self> {
//simd voodoo magic
}
} |
I really like the value-based color space information you've got here with the
Color
enum and all the types it is made up of. I'd like to use/contribute to that type and the related color types but I'm not such that I need theCanvas
type and related behavior. Would you be open to splitting the crate into two crates, one for the color-related things, and one for theTexel
/storage layout things?One of the main things I'd like to add is a method of converting between any two pixel types using this
Color
enum as we have discussed previously in theimage
crate. If all goes well I can imagine it could be quite useful for theimage
crate also.The text was updated successfully, but these errors were encountered: