Jump to page: 1 2
Thread overview
colour lib
Aug 31, 2016
Manu
Aug 31, 2016
rikki cattermole
Aug 31, 2016
Manu
Aug 31, 2016
Chris Wright
Aug 31, 2016
Manu
Aug 31, 2016
Andrea Fontana
Aug 31, 2016
Andrea Fontana
Aug 31, 2016
Manu
Aug 31, 2016
Manu
Aug 31, 2016
Andrea Fontana
Aug 31, 2016
Ethan Watson
Aug 31, 2016
Chris Wright
August 31, 2016
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.
August 31, 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?
August 31, 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.
August 31, 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?
August 31, 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
August 31, 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:
>> 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

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)

Andrea


August 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)
>
> Andrea

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.

August 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:
>>
>> 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
>
>
> 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.


> 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).

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.
August 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.
August 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:
>> 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:
>>>>
>>>> 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
>>
>>
>> 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.
>
>
>> 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).
>
> 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.

So maybe I miss (more than) something reading source code. You should write a readme to explain how it works :)
« First   ‹ Prev
1 2