www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Colour operations using CyberShadow's graphics library

reply "Phil" <phil.j.ellison gmail.com> writes:
Hi, I'm new to D and having a go at writing some image processing 
stuff using Vladimir's ae.graphics library.

To filter (i.e. perform correlations/convolutions) on a view with 
colour type C, I'd like to perform intermediate calculations 
using a colour with the same number of channels as C, but all of 
type double, and then to convert back to something of type C at 
the end.

e.g. for a horizontal blur I'd like to keep a running total per 
channel, packaged in an all-doubles colour type, and then write 
(total / kernel width) for each channel back into a value of type 
C.

How do I perform the necessary type magic here? Thanks
Jan 18 2015
next sibling parent "Phil" <phil.j.ellison gmail.com> writes:
I've done this by declaring a static array of the same length as 
ViewColor!V.channels, and foreach-ing over the channels in a 
colour, but this seem uglier than it need to - it would be nice 
if I could just define + and = appropriately on double[] and 
colours to do the right thing.

On Sunday, 18 January 2015 at 21:10:05 UTC, Phil wrote:
 Hi, I'm new to D and having a go at writing some image 
 processing stuff using Vladimir's ae.graphics library.

 To filter (i.e. perform correlations/convolutions) on a view 
 with colour type C, I'd like to perform intermediate 
 calculations using a colour with the same number of channels as 
 C, but all of type double, and then to convert back to 
 something of type C at the end.

 e.g. for a horizontal blur I'd like to keep a running total per 
 channel, packaged in an all-doubles colour type, and then write 
 (total / kernel width) for each channel back into a value of 
 type C.

 How do I perform the necessary type magic here? Thanks
Jan 19 2015
prev sibling parent reply "Vladimir Panteleev" <vladimir thecybershadow.net> writes:
On Sunday, 18 January 2015 at 21:10:05 UTC, Phil wrote:
 Hi, I'm new to D and having a go at writing some image 
 processing stuff using Vladimir's ae.graphics library.

 To filter (i.e. perform correlations/convolutions) on a view 
 with colour type C, I'd like to perform intermediate 
 calculations using a colour with the same number of channels as 
 C, but all of type double, and then to convert back to 
 something of type C at the end.

 e.g. for a horizontal blur I'd like to keep a running total per 
 channel, packaged in an all-doubles colour type, and then write 
 (total / kernel width) for each channel back into a value of 
 type C.

 How do I perform the necessary type magic here? Thanks
Hi Phil, The Color template implements opCast for types with the same set of fields, so you should be able to just cast a struct with ubyte fields to one with double fields (or use std.conv.to). The only restriction is that the fields must have the same order. You can use the ChangeChannelType template to create a Color type from an existing one but a different type for the channel fields, for example this assert will hold: static assert(is(ChangeChannelType!(RGB, ushort) == RGB16)); To create a view with double-typed channels from an RGB view, you can use colorMap: alias doubleTypedView = colorMap!(c => cast(ChangeChannelType!(typeof(c), double))c); You can use this as with any other view transform: auto i = onePixel(L8(1)); auto d = i.doubleTypedView(); assert(d[0, 0].l == 1.0); By the way, as I've never tried using floating-point types, the code didn't quite work with them as it is, as some templates expected integral types in a few places. I guess you've fixed things on your side? Anyhow, I've now pushed a commit which fixes and adds tests for FP types.
Jan 19 2015
parent "Phil" <phil.j.ellison gmail.com> writes:
Brilliant, thanks a lot.

That works a treat, allowing me to use c1 + c2 when c1 :: RGB and 
c2 :: ChangeChannelType!(RGB, int), say.

It's not happy with doubles atm, but presumably this is sorted in 
your push. Thanks again :-)

On Monday, 19 January 2015 at 21:11:34 UTC, Vladimir Panteleev 
wrote:
 Hi Phil,

 The Color template implements opCast for types with the same 
 set of fields, so you should be able to just cast a struct with 
 ubyte fields to one with double fields (or use std.conv.to). 
 The only restriction is that the fields must have the same 
 order.

 You can use the ChangeChannelType template to create a Color 
 type from an existing one but a different type for the channel 
 fields, for example this assert will hold:

 static assert(is(ChangeChannelType!(RGB, ushort) == RGB16));

 To create a view with double-typed channels from an RGB view, 
 you can use colorMap:

 alias doubleTypedView = colorMap!(c => 
 cast(ChangeChannelType!(typeof(c), double))c);

 You can use this as with any other view transform:

 auto i = onePixel(L8(1));
 auto d = i.doubleTypedView();
 assert(d[0, 0].l == 1.0);

 By the way, as I've never tried using floating-point types, the 
 code didn't quite work with them as it is, as some templates 
 expected integral types in a few places. I guess you've fixed 
 things on your side? Anyhow, I've now pushed a commit which 
 fixes and adds tests for FP types.
Jan 19 2015