Thread overview
Problem Computing Dot Product with mir
Feb 21, 2021
Kyle Ingraham
Feb 22, 2021
9il
Feb 23, 2021
Kyle Ingraham
Feb 23, 2021
Max Haughton
Feb 23, 2021
9il
February 21, 2021
I am trying to convert sRGB pixel values to XYZ with mir using the following guide: http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html

My problem is that I cannot figure out how to calculate a dot product using mir. Here is my code:

import std.stdio;

import mir.glas.l1 : dot;
import mir.ndslice;

void main()
{
	auto rgbToXyz = [0.4124564,  0.3575761,  0.1804375,
					 0.2126729,  0.7151522,  0.0721750,
 					 0.0193339,  0.1191920,  0.9503041]
 		.as!double
		.sliced(3, 3);

	alias reduceDot = reduce!"a * b";

	auto pixels = [255, 0, 0,
	 			   0, 255, 0,
	  			   0, 0, 255,
	   			   120, 120, 120]
		// convert input array elements to double - lazy
		.as!double
		// create a slice-shell over the input array
		.sliced(2, 2, 3)
		// normalize to range [0, 1]
		.map!(p => p / 255.0)
		// sRGB inverse compand
		.map!(V => V <= 0.04045 ? V / 12.92 : ((V + 0.055) / 1.055) ^^ 2.4)
		// linear RGB to XYZ
		// iterator over pixel values - 3rd dimension
		.pack!1
		// dot product of pixel value with conversion matrix
		.map!(a => reduceDot(rgbToXyz, a));
		//.map!(a => dot(rgbToXyz, a));

	writeln(pixels);
	writeln(pixels.shape);
}

In the last step I am trying to take each pixel value from my 2x2 'image' and compute a dot product of it and the conversion matrix rgbToXyz.

I have tried reduce and that results in:

Error: cannot implicitly convert expression nonInlinedNaryFun(seed, ls()) of type Slice!(VmapIterator!(double*, LeftOp!("*", double)), 2LU, cast(mir_slice_kind)2) to Slice!(double*, 2LU, cast(mir_slice_kind)2)

I have also tried dot from mir.glas.l1:

Error: template mir.glas.l1.dot cannot deduce function from argument types !()(Slice!(double*, 2LU, cast(mir_slice_kind)2), Slice!(MapIterator!(int*, pipe), 1LU, cast(mir_slice_kind)2))

I was expecting the conversion matrix (3x3) dotted with the pixel (3x1) to produce another pixel (3x1). What am I doing wrong here?
February 22, 2021
On Sunday, 21 February 2021 at 16:18:05 UTC, Kyle Ingraham wrote:
> I am trying to convert sRGB pixel values to XYZ with mir using the following guide: http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
>
> [...]

mir-glas is deprecated experimental project. It is worth use mir-blas or lubeck instead. There is also naming issue. In the classic BLAS naming dot refers a function that accept two 1D vectors.
February 23, 2021
On Monday, 22 February 2021 at 07:14:26 UTC, 9il wrote:
> On Sunday, 21 February 2021 at 16:18:05 UTC, Kyle Ingraham wrote:
>> I am trying to convert sRGB pixel values to XYZ with mir using the following guide: http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
>>
>> [...]
>
> mir-glas is deprecated experimental project. It is worth use mir-blas or lubeck instead. There is also naming issue. In the classic BLAS naming dot refers a function that accept two 1D vectors.

Your suggestion worked beautifully. I went with lubeck. I don't know how I missed it seeing that it is right there in the Dlang tour.

Thank you for writing such useful libraries.

Final code ended up being:

import std.stdio;

import kaleidic.lubeck: mtimes;
import mir.ndslice: as, byDim, fuse, map, sliced;

void main()
{
	auto rgbToXyz = [0.4124564,  0.3575761,  0.1804375,
					 0.2126729,  0.7151522,  0.0721750,
 					 0.0193339,  0.1191920,  0.9503041]
 		.as!double
		.sliced(3, 3);

	ubyte[] rgbPixels = [255, 0, 0,
	 			 		 0, 255, 0,
	  			 		 0, 0, 255,
	   			 		 120, 120, 120];

	auto xyzPixels = rgbPixels
		// convert input array elements to double - lazy
		.as!double
		// create a slice-shell over the input array
		.sliced(2, 2, 3)
		// normalize pixel channels to range [0, 1]
		.map!(chnl => chnl / 255.0)
		// sRGB inverse compand
		.map!(chnl => chnl <= 0.04045 ? chnl / 12.92 : ((chnl + 0.055) / 1.055) ^^ 2.4)
		// linear RGB to XYZ
		// iterator by x and y over pixels (3rd dimension)
		.byDim!(0, 1) // same as .pack!1
		// dot product of each pixel with conversion matrix
		.map!(pixel => mtimes(rgbToXyz, pixel))
		// join iterator values into a matrix
		.fuse;

	xyzPixels.writeln;
	xyzPixels.shape.writeln;
}
February 23, 2021
On Monday, 22 February 2021 at 07:14:26 UTC, 9il wrote:
> On Sunday, 21 February 2021 at 16:18:05 UTC, Kyle Ingraham wrote:
>> I am trying to convert sRGB pixel values to XYZ with mir using the following guide: http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
>>
>> [...]
>
> mir-glas is deprecated experimental project. It is worth use mir-blas or lubeck instead. There is also naming issue. In the classic BLAS naming dot refers a function that accept two 1D vectors.

Deprecated as in formally dead or postponed?
February 23, 2021
On Tuesday, 23 February 2021 at 03:48:15 UTC, Max Haughton wrote:
> On Monday, 22 February 2021 at 07:14:26 UTC, 9il wrote:
>> On Sunday, 21 February 2021 at 16:18:05 UTC, Kyle Ingraham wrote:
>>> I am trying to convert sRGB pixel values to XYZ with mir using the following guide: http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
>>>
>>> [...]
>>
>> mir-glas is deprecated experimental project. It is worth use mir-blas or lubeck instead. There is also naming issue. In the classic BLAS naming dot refers a function that accept two 1D vectors.
>
> Deprecated as in formally dead or postponed?

Postponed until someone wish to invest in BLAS library in D.