Skip to content

Conversation

TurkeyMan
Copy link
Contributor

There's talk about adding a std.colour type, here's a starting point for consideration.
Knows about colour space and comprehensive format conversions.
More common colour spaces to come.

@dnadlinger
Copy link
Contributor

As mentioned on the forum discussion, please consider putting this as a library on code.dlang.org first. It's much easier to get feedback this way. Putting it up as an incomplete pull request makes it harder to try out and needlessly uses up auto-tester cycles.

(Also, once the module is ready for the Phobos review process, it should be in std.experimental instead of exp.)


// declare some common colour types...

alias Colour!("rgb", ubyte) RGB;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New-style aliases please? ;P

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point!

@schveiguy
Copy link
Member

Not sure what's wrong with your keyboard, but it seems to have thrown up u's everywhere.

@TurkeyMan
Copy link
Contributor Author

@klickverbot Ah yes, the auto-tester... didn't think of that. I just threw it here because I could do it in 2 seconds, and I didn't look what I need to do to put it on code.dlang.org yet.

@ghost
Copy link

ghost commented Jan 6, 2015

Not sure what's wrong with your keyboard, but it seems to have thrown up u's everywhere.

The simpler the word the harder it is to make spelling mistakes, and those are annoying while coding. So I'd prefer color instead of colour. I don't want to open the gates of hell though.. Should we put this issue up for a simple vote?

@alexrp
Copy link
Contributor

alexrp commented Jan 6, 2015

The core libraries have consistently used American English so far. So unless we want to either change existing names or intentionally introduce inconsistency, I'd say there's no doubt American English should be used here as well.

@schveiguy
Copy link
Member

I was half joking about the u's :) I actually don't care, as I likely will not use it (not my area). It's probably something to ask the forum (what colour should the bikeshed be?)

@quickfur
Copy link
Member

quickfur commented Jan 6, 2015

Ask on the forum?! You know that's gonna result in Yet Another Interminable Thread on the colo(u)r of the bikeshed, right? :-P

@ghost
Copy link

ghost commented Jan 6, 2015

Let's settle this with a good old fashioned google fight.

@TurkeyMan
Copy link
Contributor Author

Bloody hell, I'll change the colour of the bikeshed to color! (such valuable feedback) ;)

Seriously, it's force of habit, and with cut&paste + auto-complete, everyone knows you only ever type any given word once in code... and it doesn't look wrong to me.

@PetarKirov
Copy link
Member

This module may be considered tiny by Phobos standards, but I think it would better if you split it in two (or more) modules:

  • Data representation - A small set of POD definitions and aliases to common data formats that 3rd party libs can use for interoperability. For example one should be able to pass a RGBA16 value returned from a function in lib A to function taking such argument in lib B.
  • Data interpretation - Color space conversions, operations with colors (addition, scalar/vector multiplication, blending, interpolation, etc.),
  • (Optional) list of predefined colors, e.g. like this.

In short: I think tagging that Color type with color space is a great idea just put the conversion stuff in a separate file.

@TurkeyMan
Copy link
Contributor Author

@ZombineDev I'm not sure what you mean by the first point? I don't really want to define some arbitrary set POD's for this. I'd rather everything be an instance of Colour, then you can detect that various different kinds of colours are all infact Colours's. If they were unrelated POD's, then there'd be no obvious relationship

Currently, the conversion functions are all separate. Basically, 'convert' (bad name in retrospect) converts between component types, 'convertColourSpace' converts between colour space, and those have nothing to do with the actual Colour type, so they are general functions anyone can use. Why should I separate that into a separate module? That kinda seems overkill...

I was thinking of pre-defined colours. I think they would need to be enum members of the Colour type, such that they are expressed in the appropriate format+colour space for each instance.
I wasn't sure if I wanted to pollute Colour with a heap of enums for pre-defined colours. I'm happy to do so, if people agree that's a good thing to do...

return To(convert!TyT(a), convert!TyT(b), convert!TyT(c), convert!TyT(src[3]));
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if this is false, don't you need a return here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's impossible, or the constraint would fail.
The static if is only for the is() expressions, so I can give names to the inferred template arguments.
Is there a way I can do that without the static if?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's impossible, or the constraint would fail.

I was more thinking of if the compiler will complain, i.e. when compiling with warnings enabled.

The static if is only for the is() expressions, so I can give names to the inferred template arguments.
Is there a way I can do that without the static if?

I think I understand. You want to be able to access the template parameters declared in the Colour struct? If that's the case, you could add aliases to the struct.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will the compiler complain? I'll check..

I guess I could add aliases... I wonder why I didn't do that.
I guess I just always figured I could get them from the type if I wanted to. I'll add aliases, good idea :)

@jacob-carlborg
Copy link
Contributor

Phobos uses 4 spaces for indentation, not tabs.

@TurkeyMan
Copy link
Contributor Author

Jeezus, I'm loving this bikeshed!
I don't think there's any risk of phobos acceptance any time soon, but design feedback would be nice ;)
I'd like to have other peoples ideas on features that should (and shouldn't) be present.

@justanotheranonymoususer

@jacob-carlborg
Copy link
Contributor

Jeezus, I'm loving this bikeshed!

Someone was about to tell you sooner or later, I thought I just could tell you now and be done with it.

I don't think there's any risk of phobos acceptance any time soon, but design feedback would be nice ;)

  • What's the use case to not declare all components?
  • All the metaprogramming for the components and the constructors seems quite complicated, seems a bit overkill
  • Most of the code in the Colour struct seems to be for sRGB, should that be in the same type as the others?

@TurkeyMan
Copy link
Contributor Author

@jacob-carlborg

  1. The reason to declare components selectively is so you can make one that matches any buffer you happen to have. You don't usually have control over the layout of the incoming data.
  2. I tend to disagree, I think this inflexibility is the main reason that all other colour modules fail. If Colour isn't sufficiently flexible to match the datasets people encounter, then they are forced to add yet another spurious implementation of a colour type. If you aim to support all the common colour formats out there with a suite of struct's, then you'll have a really gigantic list of them.
  3. That's because sRGB is the only one that I've finished. I'll fill in the blanks when I'm settled on API choices. At very least, Lab, YUV and HSV are commonly useful. XYZ is already there. AdobeRGB is also useful for some specific things.
    The other reason that sRGB will be more verbose than others, is because sRGB is the standard; it receives the most use, the most abuse, and has by far the largest number of permutations relating to different common encodings and use cases. If the API supports all the sRGB cases, it is fine for the others, so I wrote it first.

@jacob-carlborg
Copy link
Contributor

Ok, I see.

@TurkeyMan TurkeyMan force-pushed the colour branch 2 times, most recently from 238b044 to 29d0ac2 Compare January 10, 2015 02:32
@TurkeyMan
Copy link
Contributor Author

Fixed all the nitpicks

@TurkeyMan TurkeyMan changed the title Added exp.image.colour.d Added std.experimental.color Jan 10, 2015

alias ComponentType = ComponentType_;
enum string components = components_;
enum ColorSpace colorSpace = colorSpace_;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do these need to be public? I not, I would recommend adding the underscores to these enums/alias instead of the template parameters.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it can hurt for them to be public. People might want to know the colour space, and the component type is definitely interesting. I could probably make components private.
Is there an idiomatic solution to this problem?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't no, I guess it's fine if they're public. It just slightly annoys me that the underscores are needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, believe me, those underscores REALLY upset me too ;)
I found myself wishing for behaviour something like C++'s initialiser lists, where it intelligently just knows which one I'm talking about based on common sense... >_<

@rikkimax
Copy link
Contributor

A few things.

  • You have the private imports and an import at the top. These should be combined. One of those lots might be missed.
  • Those alias's for e.g. RGBA could be wrapped in a struct. e.g. ColorTypes.RGBA

    But that is my opinion. It just feels too polutey if you get my drift.
  • Something along the lines of:
auto concatRawValues(T)(T[] values...)(isColor!T) {
    alias U = typeof(T.r); // example
    U[] ret;

    foreach(value; values) {
        ret ~= value.r; // example
        // "
    }

    return ret;
}

Would be nice.

In other words, design wise, I'm happy. Just nitpicking.

@TurkeyMan
Copy link
Contributor Author

You know you can comment in particular lines of code on github right? (click the little '+' next to the lines you have issues with), makes it easier to have conversation at the offending line.

Why do you think I should namespace the type aliases? Isn't that what module namespacing is for?

Design-wise, I'm actually having second thoughts. I thought it would be best to have a single colour template with an associated colour space, but I'm starting to move towards a different colour type for each colour space... although I can't really articulate why. It just kinda feels like my first instinct might have been wrong.

@rikkimax
Copy link
Contributor

@TurkeyMan Yes I do know.

RGB for example seems a little ubiquitous and could cause trouble. It's not a big deal to put the alias's into e.g. a struct. Since we do have things like selective imports and renames. I'm just anticipating problems in library code.

Lets be honest here. We mostly will be dealing with RGBA as a ubyte. As long as it be swapped easily to it and pass around the reference without it being that format. There won't be any problem.

About the design, even though it is a template I don't think it will cause problems. It would be nice to have all the color spaces be passed around without using templates however.

@TurkeyMan
Copy link
Contributor Author

Yeah, I'm not sold on namespacing either way. I'll worry about that if/when it's reviewed.

So, I'm not sure I understood, was that a vote for distinct types for each colour space?

@TurkeyMan
Copy link
Contributor Author

More tweaks, doco improvements. Added nothrow @nogc version of colorFromString().

@TurkeyMan
Copy link
Contributor Author

@jpf91 Any further thoughts on that CI issue?

Compiler bug. It fails to instantiate the NormalizedInt opEquals template. I'll run dustmite to reduce this.

As a workaround, add this to lab.d:

unittest
{ 
    NormalizedInt!(ushort) a;
}

I did that... CI still fails.

@jpf91
Copy link
Contributor

jpf91 commented Oct 7, 2016

I did that... CI still fails.

According to the build results 1 and 2 the workaround fixed the problem for lab.d but packedrgb.d has the same problem. You'll have to add the workaround code to packedrgb.d as well. Other modules could be affected as well, you'll have to check the test results to know for sure.

@jpf91
Copy link
Contributor

jpf91 commented Oct 12, 2016

Seems to be working 👍 The workaround comment should probably include add a link to the bug report: https://issues.dlang.org/show_bug.cgi?id=16477

@wilzbach
Copy link
Contributor

@TurkeyMan

I'm making it my first point of order (towards restoring my resume) to get this in good shape ;)

So what's the status on this PR? What are the remaining blockers?

@TurkeyMan
Copy link
Contributor Author

So what's the status on this PR? What are the remaining blockers?

I don't really know. There seems to be low enthusiasm for inclusion, which is disappointing. This will enable a lot of further multimedia work, and help to make multimedia API's interoperable.
I don't really know what's remaining, I'm happy with this initial offering. Perhaps examples could be improved, but that shouldn't inhibit review and feedback/criticism?

@rikkimax
Copy link
Contributor

@TurkeyMan I know at this point I'm happy with it, but I don't have write access for the review require check to be completed.
I think its time for the vote. We can improve documentation later.

@TurkeyMan
Copy link
Contributor Author

The trouble with doing extensive documentation and examples, is that it may change with API review.
Also, I don't think the documentation is that bad... if people can flag areas where they feel existing doco is insufficient, that'd be helpful.
I'd love it if there were some examples of use in conjunction with ndslice to do image processing; @9il?
This sort of thing is not really appropriate for API docs though, it's more along the lines of how-to or tutorials.

@9il
Copy link
Member

9il commented Dec 31, 2016

@TurkeyMan @ljubobratovicrelja
My vision of ndslice & color for image processing is following:

  1. Done Implement ndslice variant format optimal for image processing. Current ndslice is not very good because it is only numpy like. https://github.com/libmir/mir-algorithm contains 3 types of ndslices:
    a. contiguous (2D: 2 lengths, pointer),
    b. canonical (2D: 2 lengths, 1 stride, pointer),
    c. universal (2D: 2 lengths, 2 strides, pointer).
    continuous and canonical are good/fast for image processing.
  2. Done Implement flexible stack routines: ndslice: concatenate/vstack/hstack [$15 awarded] libmir/mir#213
  3. Done Update DCV using new ndslice.
  4. Update DCV using color
  5. Update color to be more user friendly for
    a. vectorisation
    b. image processing
    c. LDC
    d. betterC libraries

@TurkeyMan Please keep color as dub package.

We need color for DCV, and we will add changes, fixes, and updates for color. Because Phobos release cycle is very slow, we would not be able to work with Phobos repo, but dub package.

We will be happy to include it to the Mir Org as separate dub package.

@wilzbach
Copy link
Contributor

So what how do we proceed here? Two suggested ways:

I think its time for the vote. We can improve documentation later.

@TurkeyMan Please keep color as dub package.
We need color for DCV, and we will add changes, fixes, and updates for color. Because Phobos release cycle is very slow, we would not be able to work with Phobos repo, but dub package.
We will be happy to include it to the Mir Org as separate dub package.

@TurkeyMan maybe you can start a thread to resolve this status quo on the NG?
(of course you are still invited to migrate it to the Mir Org space)

@TurkeyMan
Copy link
Contributor Author

@9il Vectorisation of color is something I'm very interested in working on too, and it's going to be kinda hard. The reason I haven't attempted it sooner though, is because I think it will require some API assistance from ndslice (for instance); the looping/iterating logic will need to be able to make some decisions about bundling/grouping sequences of elements, then you can hand-write parallel operator functions which do strips of colours in various formats. The single-element operators are useless for performance.
Also, writing colours in such a way that the auto-vectoriser can do a good job is SUPER hard, and makes it very hard to maintain readable code :)
I tried a lot, but concluded that the single-element operators and the batch-operators need to be separate functions, and the iteration code (ndslice?) will need to learn how to call the batch operators instead of the single-element operators.

@TurkeyMan
Copy link
Contributor Author

@wilzbach Ilya makes a good point about iterating on it more, although even if it were accepted into phobos, I would like to think that's the whole point of the experimental namespace.

@rikkimax
Copy link
Contributor

@TurkeyMan There is nothing wrong with saying vectorization is out of scope at the moment for Phobos.
Let's get a standard single element implementation that can be used as the baseline first, then get it be amazingly fast. That way those who know how to vectorize can help without knowing color theory.

@TurkeyMan
Copy link
Contributor Author

This was my plan.

@9il
Copy link
Member

9il commented Feb 23, 2017

@TurkeyMan There is nothing wrong with saying vectorization is out of scope at the moment for Phobos.
Let's get a standard single element implementation that can be used as the baseline first, then get it be amazingly fast. That way those who know how to vectorize can help without knowing color theory.

This does not work at practice. The new ndslice API was created because the old one was not created for speed. The same situation will be with color. Futhermore, we would not use Phobos because its modify-test-release cycle is months vs dub's minutes.

@rikkimax
Copy link
Contributor

@9il that won't be an issue here.
Vectorization code can be kept on dub until it is ready for merging.

The color types are bare bones, there is no form of valid rearranging or removing of variables from what I can see. So all in all, if it goes into Phobos, it'll be a-ok to develop the faster processing algorithms separately.

@9il
Copy link
Member

9il commented Feb 23, 2017

@9il that won't be an issue here.
Vectorization code can be kept on dub until it is ready for merging.

The color types are bare bones, there is no form of valid rearranging or removing of variables from what I can see. So all in all, if it goes into Phobos, it'll be a-ok to develop the faster processing algorithms separately.
Add your review

If it go to Phobos we would not care about backward updates and will work on dub package separately. I had the same situation with ndslice: it takes to much time to synchronise Phobos and a dub package. In addition, users are disoriented and it is red flag for new comers.

@rikkimax
Copy link
Contributor

@9il What exactly do you envision you need to alter within the existing code as part of the separate new functions that are designed for batch operations?

@9il
Copy link
Member

9il commented Feb 23, 2017

@9il What exactly do you envision you need to alter within the existing code as part of the separate new functions that are designed for batch operations?

We do not know until we done a large optimisation work using color and ndslice. Phobos does not have iterators and it was a mistake (you can compare bitwise implementation in Phobos and Mir for example). Phobos uses Range API for RNGs and it was a mistake. First ndslice provided only numpy-like arrays - this was my mistake. BTW, ndslice was bare bone too! And the mistake was in the bare bones, hehe

@rikkimax
Copy link
Contributor

@9il You misunderstand. For batch operations you will need new free-functions. You cannot simply "vectorize" existing ones. The data structures such as RGB, do not have anything other than the components (from what I can see). The only modification I can envision would be needed is padding.

The existing functions deal with single color operations. Not batches e.g. an image, there are no easy wins there. So there is nothing to get a big speed boost for.

Until ndslice is ready, nothing related to it batch processing wise is going into Phobos and that is ok. Just getting existing image libraries compatible is the goal here. Fast comes later.

@9il
Copy link
Member

9il commented Feb 24, 2017

Nope. This all words are theory. Practice will show

@MetaLang
Copy link
Member

MetaLang commented Aug 6, 2017

As I said in #2862, this'll have to go through the Phobos review process so there's no point in keeping this PR open.

@MetaLang MetaLang closed this Aug 6, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.