digitalmars.D - colour lib
- Manu via Digitalmars-d (57/57) Aug 30 2016 I'm blowing the dust off my colour proposal implementation.
- rikki cattermole (10/10) Aug 30 2016 So I'm replying without your post, so I will put my thoughts here:
- Manu via Digitalmars-d (13/19) Aug 30 2016 Sure. I use it in my own image library all the time.
- Chris Wright (4/4) Aug 30 2016 The color models I'm aware of are HSV, HSL, RGB[A], CMYK, Lab, Pantone,
- Manu via Digitalmars-d (5/9) Aug 30 2016 I'll initially support, XYZ/xyY, RGB (which is a gigantic set), HSx, Lab...
- Andrea Fontana (15/25) Aug 31 2016 I always think the perfect colour library should work using a
- Andrea Fontana (7/21) Aug 31 2016 I forgot that in this way it's quite easy to wrap external
- Manu via Digitalmars-d (3/8) Aug 31 2016 It's done.
- Manu via Digitalmars-d (24/60) Aug 31 2016 Yeah... that would be wickedly slow.
- Andrea Fontana (3/76) Aug 31 2016 So maybe I miss (more than) something reading source code. You
- Ethan Watson (4/6) Aug 31 2016 I can probably chip in and help here at some point (both with
- Chris Wright (10/17) Aug 31 2016 That depends on how often you incur the conversion cost. If you're
I'm blowing the dust off my colour proposal implementation. I want to get it into a state where it may be accepted into std.experimental, but I'm having trouble deciding on the scope of the initial offering. Some people are arguing for 'complete', and I tend to argue for minimal/un-contentious. It can grow in the future as desired. There is a slightly blurry line separating a colour lib from an image lib, and I want to focus the boundaries. My design propositions are this: 1. Colour type definitely belongs in the std library; - Colour types and conversions are hard to implement, non-experts almost always get it wrong. - Implementation is more-or-less un-contentious, I don't think there's much room for debate in terms of API design. - It's an enabler for a lot of further library work. 2. Image processing probably doesn't belong in the std library, at least, not right now; - There are so many ways the API could look, no particular one is objectively 'correct'. - We need time for conventions to proliferate before API decisions for the std lib can reasonably be decided. 3. I am kinda drawing the line between 'colour' and 'image' at the point you find yourself working with buffers of data. Ie, 'colour' is strictly nogc. So, I guess that means this clearly encompasses colour types, primitive operations, and then typical functions like interpolation, and conversion. I think that's the scope, and I'm happy with that definition, but it raises some questions... Colour defined this way without buffered enhancements will be inefficient; performing single-colour operations in series is not cool. Image operations tend to want support for simd, loop unrolling, etc, for efficient image library implementations. I don't really feel it's the place for an image library to re-define these efficient array versions of colour operations... so, should they be in the base colour library? This problem actually extends beyond colours... D positions ranges as a core language mechanic, and I've often struggled with this problem that defining an element type and how it behaves and using it in a range is frequently not an efficient implementation. It's the classic OOP design fail, but dressed up differently. What is the current wisdom with respect to implementing efficient batch implementations for various element types? I'm feeling like I should not attempt to address this problem in the initial colour library and just leave it as simple as possible; just the colour type. It can be used for inefficient purposes for now (and produce *correct* results) and we can worry about efficient batch processing in a follow up, or when an image library comes along? I have another question too; some of the operations are algorithmic in nature. Take lerp for example. Interpolation may appear in an algorithm, which means we should have a standard API for interpolation for all possible types, and modules just provide implementations for the types they introduce. There should be default implementations in phobos for builtin types. Where does this belong? (I haven't found one to already exist) I feel like `lerp(T, F)(T a, T b, F t) { return a*(1-t) + b*t; }` belongs kinda near min/max... but std.algorithm.comparison doesn't feel right. I think a small suite of functions like this exists.
Aug 30 2016
So I'm replying without your post, so I will put my thoughts here: 1. Trust your gut on this one, your the expert in the problem domain, we're not. 2. As part of your argument I personally would prefer that it is at least tested in the context of an image library. We don't want any hidden problems there even if that is not your goal to implement the best image library. 3. Assuming pragma(inline, true) does in fact work, as long as the different operations are made simple I see no reason why it would be any less efficient, after all surely e.g. gdc/ldc can optimize and vectorize it?
Aug 30 2016
On 31 August 2016 at 15:01, rikki cattermole via Digitalmars-d <digitalmars-d puremagic.com> wrote:2. As part of your argument I personally would prefer that it is at least tested in the context of an image library. We don't want any hidden problems there even if that is not your goal to implement the best image library.Sure. I use it in my own image library all the time. I'm confident the basic implementation will work perfectly in the context of an image library, my concern is it won't be very efficient. It will however offer a 'correct' reference implementation for optimised image library development to work against, so I guess it's an important first offering however you look at it.3. Assuming pragma(inline, true) does in fact work, as long as the different operations are made simple I see no reason why it would be any less efficient, after all surely e.g. gdc/ldc can optimize and vectorize it?Batch functions are so radically different than single operations, if an optimiser/vectoriser is able to even start to approach an efficient batch implementation, I'll be astonished. It'll need to be hand written at some stage, but we don't really have mechanisms for this sort of thing among D's existing range patterns.
Aug 30 2016
The color models I'm aware of are HSV, HSL, RGB[A], CMYK, Lab, Pantone, and the Open Colour Standard. I'm not sure what common operations they have. Perhaps you could provide a link to your existing library?
Aug 30 2016
On 31 August 2016 at 16:01, Chris Wright via Digitalmars-d <digitalmars-d puremagic.com> wrote:The color models I'm aware of are HSV, HSL, RGB[A], CMYK, Lab, Pantone, and the Open Colour Standard.I'll initially support, XYZ/xyY, RGB (which is a gigantic set), HSx, Lab, Yuv.I'm not sure what common operations they have.All colours can add, subtract, scale luminance.Perhaps you could provide a link to your existing library?https://github.com/TurkeyMan/color
Aug 30 2016
On Wednesday, 31 August 2016 at 06:17:15 UTC, Manu wrote:On 31 August 2016 at 16:01, Chris Wright via Digitalmars-d <digitalmars-d puremagic.com> wrote:I always think the perfect colour library should work using a superset of all colour spaces, for example cie xyz (is it a superset, isn't it?). isColour(T) then IMO should check if x,y,z properties exists (or toXYZ() method). In this way every algorithm like "blend" or anything else could be implemented just for xyz (and eventually specialized for other colours if we want to avoid conversion overhead). In this way it become easy to do cross-colour operations (for example: apply a rgb mask over another color space) and to implement new or strange color spaces (that automagically will work with all "blend" & co.). To implement a new color spaces you just need to map it to xyz (that should represent all - and more - visible colours: rgb is a subset of visibile colours) AndreaThe color models I'm aware of are HSV, HSL, RGB[A], CMYK, Lab, Pantone, and the Open Colour Standard.I'll initially support, XYZ/xyY, RGB (which is a gigantic set), HSx, Lab, Yuv.I'm not sure what common operations they have.All colours can add, subtract, scale luminance.Perhaps you could provide a link to your existing library?https://github.com/TurkeyMan/color
Aug 31 2016
On Wednesday, 31 August 2016 at 07:58:36 UTC, Andrea Fontana wrote:I always think the perfect colour library should work using a superset of all colour spaces, for example cie xyz (is it a superset, isn't it?). isColour(T) then IMO should check if x,y,z properties exists (or toXYZ() method). In this way every algorithm like "blend" or anything else could be implemented just for xyz (and eventually specialized for other colours if we want to avoid conversion overhead). In this way it become easy to do cross-colour operations (for example: apply a rgb mask over another color space) and to implement new or strange color spaces (that automagically will work with all "blend" & co.). To implement a new color spaces you just need to map it to xyz (that should represent all - and more - visible colours: rgb is a subset of visibile colours) AndreaI forgot that in this way it's quite easy to wrap external class/struct to make them works with library. If we have a custom COLOR class provided by another library we just need to write a toXYZ(COLOR c) method (if it doesnt provide x,y,z properties) and it works.
Aug 31 2016
On 31 August 2016 at 18:04, Andrea Fontana via Digitalmars-d <digitalmars-d puremagic.com> wrote:On Wednesday, 31 August 2016 at 07:58:36 UTC, Andrea Fontana wrote: I forgot that in this way it's quite easy to wrap external class/struct to make them works with library. If we have a custom COLOR class provided by another library we just need to write a toXYZ(COLOR c) method (if it doesnt provide x,y,z properties) and it works.It's done.
Aug 31 2016
On 31 August 2016 at 17:58, Andrea Fontana via Digitalmars-d <digitalmars-d puremagic.com> wrote:On Wednesday, 31 August 2016 at 06:17:15 UTC, Manu wrote:Yeah... that would be wickedly slow.On 31 August 2016 at 16:01, Chris Wright via Digitalmars-d <digitalmars-d puremagic.com> wrote:I always think the perfect colour library should work using a superset of all colour spaces, for example cie xyz (is it a superset, isn't it?). isColour(T) then IMO should check if x,y,z properties exists (or toXYZ() method).The color models I'm aware of are HSV, HSL, RGB[A], CMYK, Lab, Pantone, and the Open Colour Standard.I'll initially support, XYZ/xyY, RGB (which is a gigantic set), HSx, Lab, Yuv.I'm not sure what common operations they have.All colours can add, subtract, scale luminance.Perhaps you could provide a link to your existing library?https://github.com/TurkeyMan/colorIn this way every algorithm like "blend" or anything else could be implemented just for xyz (and eventually specialized for other colours if we want to avoid conversion overhead).Basically the whole point of colour spaces is to do blends in different colour spaces. XYZ is not a great space for blending, xyY is functionally identical for blending as RGB, except that you need to do conversions on either side of the blend. RGB tend to be integer colour spaces, whereas XYZ/xyY are necessarily float colour spaces, which implies a lot of int<->float conversion, etc. RGB is not at all perceptually uniform, which is why colour spaces like Lab were invented; if you use Lab, then your intent is to blend in Lab. Same story for HSx spaces, you use them when you want to blend with a linear hue axis.In this way it become easy to do cross-colour operations (for example: apply a rgb mask over another color space) and to implement new or strange color spaces (that automagically will work with all "blend" & co.). To implement a new color spaces you just need to map it to xyz (that should represent all - and more - visible colours: rgb is a subset of visibile colours)The meat of your idea is already implemented in my code there. The way it works is that you define your own custom colour type, and then add a 'sign post' member, ie, `alias ParentColour = XYZ!float;`, then you need to implement convertColor() for MyCustomColour -> XYZ and vice-versa. With that, your custom colour will be convertible to any other colour format; using a basic path-finding search (using the sign posts) it will find a path from any colour type to any other colour type, and perform the series of conversions required to get there. XYZ is a valid superset, so you can always rely on it as a centerpoint for colour conversions... but this is for conversion, not blending, which is the whole point of defining your own colour space.
Aug 31 2016
On Wednesday, 31 August 2016 at 09:33:24 UTC, Manu wrote:On 31 August 2016 at 17:58, Andrea Fontana via Digitalmars-d <digitalmars-d puremagic.com> wrote:So maybe I miss (more than) something reading source code. You should write a readme to explain how it works :)On Wednesday, 31 August 2016 at 06:17:15 UTC, Manu wrote:Yeah... that would be wickedly slow.On 31 August 2016 at 16:01, Chris Wright via Digitalmars-d <digitalmars-d puremagic.com> wrote:I always think the perfect colour library should work using a superset of all colour spaces, for example cie xyz (is it a superset, isn't it?). isColour(T) then IMO should check if x,y,z properties exists (or toXYZ() method).The color models I'm aware of are HSV, HSL, RGB[A], CMYK, Lab, Pantone, and the Open Colour Standard.I'll initially support, XYZ/xyY, RGB (which is a gigantic set), HSx, Lab, Yuv.I'm not sure what common operations they have.All colours can add, subtract, scale luminance.Perhaps you could provide a link to your existing library?https://github.com/TurkeyMan/colorIn this way every algorithm like "blend" or anything else could be implemented just for xyz (and eventually specialized for other colours if we want to avoid conversion overhead).Basically the whole point of colour spaces is to do blends in different colour spaces. XYZ is not a great space for blending, xyY is functionally identical for blending as RGB, except that you need to do conversions on either side of the blend. RGB tend to be integer colour spaces, whereas XYZ/xyY are necessarily float colour spaces, which implies a lot of int<->float conversion, etc. RGB is not at all perceptually uniform, which is why colour spaces like Lab were invented; if you use Lab, then your intent is to blend in Lab. Same story for HSx spaces, you use them when you want to blend with a linear hue axis.In this way it become easy to do cross-colour operations (for example: apply a rgb mask over another color space) and to implement new or strange color spaces (that automagically will work with all "blend" & co.). To implement a new color spaces you just need to map it to xyz (that should represent all - and more - visible colours: rgb is a subset of visibile colours)The meat of your idea is already implemented in my code there. The way it works is that you define your own custom colour type, and then add a 'sign post' member, ie, `alias ParentColour = XYZ!float;`, then you need to implement convertColor() for MyCustomColour -> XYZ and vice-versa. With that, your custom colour will be convertible to any other colour format; using a basic path-finding search (using the sign posts) it will find a path from any colour type to any other colour type, and perform the series of conversions required to get there. XYZ is a valid superset, so you can always rely on it as a centerpoint for colour conversions... but this is for conversion, not blending, which is the whole point of defining your own colour space.
Aug 31 2016
On Wednesday, 31 August 2016 at 09:37:41 UTC, Andrea Fontana wrote:So maybe I miss (more than) something reading source code. You should write a readme to explain how it works :)I can probably chip in and help here at some point (both with documentation and ensuring the API is intuitive).
Aug 31 2016
On Wed, 31 Aug 2016 19:33:24 +1000, Manu via Digitalmars-d wrote:On 31 August 2016 at 17:58, Andrea Fontana via Digitalmars-dThat depends on how often you incur the conversion cost. If you're storing your whole image in your custom color type and converting to read every pixel, that's not so great. If you have an existing image with one colorspace and a user wants to add text in a color defined in a different colorspace, you only need to convert once, after the user uses the color picker. If you have two images that you want to combine and they're using different colorspaces, you must incur that cost anyway, and the image library should support that. The color library shouldn't put up barriers.I always think the perfect colour library should work using a superset of all colour spaces, for example cie xyz (is it a superset, isn't it?). isColour(T) then IMO should check if x,y,z properties exists (or toXYZ() method).Yeah... that would be wickedly slow.
Aug 31 2016