colour lib needs reviewers

Manu via Digitalmars-d digitalmars-d at puremagic.com
Mon Sep 12 18:05:56 PDT 2016


On 13 September 2016 at 06:29, Random D user via Digitalmars-d
<digitalmars-d at puremagic.com> wrote:
> On Monday, 12 September 2016 at 04:14:27 UTC, Manu wrote:
>>
>> I think I'm about as happy with my colour lib as I'm going to be. It
>> really needs reviews.
>>
>> - Manu
>
>
> Hi. I'm just a random forum lurker, but here's my feedback.
>
> It needs more docs/examples for the basic usage cases (i.e. how to skip docs
> and start working).
>
> Now at first glance it looks like working with RGBA (most common case (with
> srgb)) is complicated and while reading the docs I kind of felt like I'd
> just write my own.

You'll get it wrong though!

Can you describe what  you  perceive to be hard?

  import std.experimental.color;

  RGBA8 a(0xFF808000);
  RGBA8 b("GoldenRodYellow");
  auto r = a + b; // do normal operations

Or:
  auto image = new RGBA8[height][width];
  image[x][y] = RGBA8("Aquamarine");


> Few basic things I'd be interested in (examples):
> 1. How to pack/unpack color into uint/rgba channels.

auto c  = RGBA8(r, g, b, a);
uint r = c.r.value; // 'r' is a 'NormalizedInt", so you need '.value'
to get the raw integer value
float g = cast(float)c.g; // cast to float knows about the normalized 0-1 range

> Also can I swizzle channels directly?

I could add something like:
  auto brg =  c.swizzle!"brg";

The result would be strongly typed to the new arrangement.

> How would I extract a single channel from color?

uint r = c.r.value; // like this?

> 2. Can I just cast an array of bytes into a RGBA array and operate on that?

Yes. Of course, if the image library returned an array of colors, you
wouldn't have an array of raw bytes in the first place.

> 3. How to scale color channels e.g. 5 bits to 8 bits and vice versa. How to
> convert color formats? Can I combine scale/conversion with single channel or
> channel swizzling?

alias CustomPackedColor = PackedRGB!("BGR_5_6_5", ubyte); // <- ordered bgr
CustomPackedColor[] image = loadPackedImage();

auto unpacked = cast(RGB8)image[0]; // unpack and swizzle

I'm not sure what you mean by "with single channel"?

> 4. Which way are RGBA format names defined ("byte array order" r is first
> byte or "uint order" r is in high bits)?

I describe formats in byte (bit) order. It's the only reasonable way
that works outside of a uint.

> 5. Is it the same for packed rgba formats?

Yes.

> I'm not sure if packedrgb is a necessary distinction. Aren't they all kind
> of packed (small structs)? There's no guarantee that 1 byte is not just a
> part of a bigger field.

RGBA8 has 4 ubytes, and you can operate on them.
  ubyte a, b; a += b; // <- is valid D code
Unpacked types can do maths. Packed types can't do maths, they need to
be unpacked before you can do anything, and you don't generally want
the result to be immediately packed again.
If I allowed maths on PackedRGB for instance, it would be expected
that the result is re-packed at the end of every operation, and that
would be useless.

PackedRGB is for storage, not for doing work. This is why they're distinct.

> Btw. Your RGBA8 example is a bit weird:
> static assert(RGBA8("0x908000FF") == RGBA8(0x80,0x00,0xFF,0x90));
> I'd assume RGBA8(r,g,b,a) would be either "uint order" r(0x90), g(0x80),
> b(0x00), a(0xFF) or "byte array order" (le) r(0xFF), g(0x00), b(0x80),
> a(0x90)

I'm showing that parsing colors from string's follow the web
convention. I can't redefine how colours are expressed on the web for
decades.
I think you've just highlighted that I need to remove the '0x'
notation though, that is definitely misleading! Use '#', that should
be clear.

> 6. Perhaps you should define all the usual color formats, since everybody
> and their cat has their own preference for rgba channel orders.
> In my experience all these 4 variants for RGBA8888 are pretty common:
> RGBA8888
> BGRA8888
> ARGB8888
> ABGR8888
> and their X and 24bit variants.

I don't think they're common at all. Only 2 are common (one of which
is deprecated), the other 2 are very niche.
I was trying to balance a tasteful amount of instantiations. I don't
really want to provide an instantiation of every single realtime
format I've ever encountered out of the box.


> For 16 bits fairly common are:
> RGB565 and RGBA5551, also sometimes you see one of RGBA4444 permutations
> (like RGBA8 above).

Nobody uses 16bit textures anymore. Compressed textures are both MUCH
smaller, and generally higher quality.

> Also L16 is pretty common for heightfields or other data images/textures.

I could probably put that one.

> I guess there are also planar formats, but I think those are more of a Image
> problem space.

I think if people want to provide instantiations for convenience, it
should be in the libs that interact with those formats.

For instance, I imagine in OpenGL binding there might be:
  alias C = ColorFor!GL_R11F_G11F_B10F; // <- instantiation of the
proper type for the GL enum.

Most people really just want RGB8, or RGBA8. If you're interacting
with PackedRGB, you're already in specialist territory.


> Just as a completely random idea - How about aliases for HDR formats like
> HDR10 and Dolby Vision? Kind of looks like they're just combinations what
> you already have.

This is very specialist. Instantiations are expensive. If they're not
used, it's a waste of compiler effort.


More information about the Digitalmars-d mailing list