Help me to find high saturation and brightness colors.

The MagickWand interface is a new high-level C API interface to ImageMagick core methods. We discourage the use of the core methods and encourage the use of this API instead. Post MagickWand questions, bug reports, and suggestions to this forum.
rpatelob
Posts: 62
Joined: 2017-04-17T22:17:01-07:00
Authentication code: 1151

Help me to find high saturation and brightness colors.

Post by rpatelob »

I have a below command and trying to achieve the same in C.

Code: Select all

convert one.jpg -scale '50x50!' -depth 8 \
'(' -clone 0 -colorspace HSB -channel gb -separate +channel -threshold 50% -compose multiply -composite ')'\
 -alpha off -compose copy_opacity -composite sparse-color:-|\
convert -size 50x50 xc: -sparse-color voronoi @- +dither -colors 6 -depth 8 -format %c histogram:info:
I couldn't understand the part of sparse-color :- and the same sparse-color in second convert command sparse-color voronoi @-
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Help me to find high saturation and brightness colors.

Post by snibgo »

This is two "convert" commands, where the text output of the first is piped to the second.

To understand how it works, I suggest you separate the commands. Send the output of the first to a text file, and reads that text file in the second. Then you can read that text file to see what it contains.

You will see the text file has the coordinates and colours of the opaque pixels. In turn, these are pixels that have both brightness and saturation above the threshold.

The second command uses those pixel colours to colour an image. See http://www.imagemagick.org/script/comma ... arse-color

Grepping the IM library will find the C function you need for "-sparse-color voronoi @-".
snibgo's IM pages: im.snibgo.com
rpatelob
Posts: 62
Joined: 2017-04-17T22:17:01-07:00
Authentication code: 1151

Re: Help me to find high saturation and brightness colors.

Post by rpatelob »

@snibgo, Thank you.
As you have suggested. I got the output from first command then saved it into text file. In the second convert I read that text file and I got the result.

Code: Select all

 convert one.jpg -scale '50x50!' -depth 8 '(' -clone 0 -colorspace HSB -channel gb -separate +channel -threshold 50% -compose multiply -composite ')' -alpha off -compose copy_opacity -composite sparse-color:-test.txt
/*Pass text file*/
convert -size 50x50 xc: -sparse-color voronoi @-test.txt +dither -colors 6 -depth 8 -format %c histogram:info:  
To achieve same result in C, MagickSparseColorImage function might be useful. In first convert sparse-color: gives a list of x, y, color. Could you tell me how do I get the colors using C, like I got from first convert?
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Help me to find high saturation and brightness colors.

Post by snibgo »

rpatelob wrote:MagickSparseColorImage function might be useful.
Yes.

From the source code, you can see it needs an array of "double" numbers. The documentation doesn't explain this array, but you can see it calls SparseColorImage(), which is in distort.c, which explains:
% o arguments: array of floating point arguments for this method--
% x,y,color_values-- with color_values given as normalized values.
So you need to set up this array with coordinates and colours of opaque pixels from the image you have created. The obvious way to do this is in a y,x loop that reads the image and, for each opaque pixel, populate the next few array elements.
snibgo's IM pages: im.snibgo.com
rpatelob
Posts: 62
Joined: 2017-04-17T22:17:01-07:00
Authentication code: 1151

Re: Help me to find high saturation and brightness colors.

Post by rpatelob »

% o arguments: array of floating point arguments for this method--
% x,y,color_values-- with color_values given as normalized values.
Yes, you are right but how do I get those values "x,y, color_values" in C? In CLI, the first convert command gives me those values.
And the second convert command uses those values and return 6 colors.

Code: Select all

convert -size 50x50 xc: -sparse-color voronoi @-test.txt +dither -colors 6 -depth 8 -format %c histogram:info:  
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Help me to find high saturation and brightness colors.

Post by snibgo »

As I said: The obvious way to do this is in a y,x loop that reads the image and, for each opaque pixel, populate the next few array elements.
snibgo's IM pages: im.snibgo.com
rpatelob
Posts: 62
Joined: 2017-04-17T22:17:01-07:00
Authentication code: 1151

Re: Help me to find high saturation and brightness colors.

Post by rpatelob »

Thank you @snibgo
I have done it. :D
el_supremo
Posts: 1015
Joined: 2005-03-21T21:16:57-07:00

Re: Help me to find high saturation and brightness colors.

Post by el_supremo »

@rpatelob
Would you mind showing your code? I've almost got that working except for the last step.

Pete
Sorry, my ISP shutdown all personal webspace so my MagickWand Examples in C is offline.
See my message in this topic for a link to a zip of all the files.
rpatelob
Posts: 62
Joined: 2017-04-17T22:17:01-07:00
Authentication code: 1151

Re: Help me to find high saturation and brightness colors.

Post by rpatelob »

Yes sure!
Here is the code. I have skipped all other operations. Please check my below code, you will get the Sparse Colors.

Code: Select all

		size_t height = MagickGetImageHeight(wand);
		size_t width = MagickGetImageWidth(wand);
		size_t spares_index = 0;
		// Allocated enough memory to hold Sparse Color data
		double * sparse_args = malloc(sizeof(double) * height * width * 5);
		// Iterate over pixel data
		iteration = NewPixelIterator(wand);
		for (y = 0; y < height; ++ y)
		{
		    row = PixelGetNextIteratorRow(iteration, &row_width);
		    for (x = 0; x < row_width; ++x)
		    {
		        PixelGetMagickColor(row[x], &pixel);
		        // Append coord + color data if pixel is visible.
		        if (pixel.alpha == QuantumRange) {
		            sparse_args[spares_index++] = (double)x;
		            sparse_args[spares_index++] = (double)y;
		            sparse_args[spares_index++] = pixel.red / QuantumRange;
		            sparse_args[spares_index++] = pixel.green/ QuantumRange;
		            sparse_args[spares_index++] = pixel.blue / QuantumRange;
						}
		    }
		}
		iteration = DestroyPixelIterator(iteration);
		wand = DestroyMagickWand(wand);
This is first part. And as I said I skipped other operations like composite, scale, etc.
Now you just need to pass sparse_args to second part. Below is the second part.

Code: Select all

		MagickWand * final;
		final = NewMagickWand();
		MagickSetSize(final, 50, 50);
		MagickReadImage(final, "xc:");
		MagickSparseColorImage(final, VoronoiColorInterpolate, spares_index, sparse_args);
		MagickQuantizeImage(final, 6, UndefinedColorspace, 0, NoDitherMethod, MagickFalse);
Now find Histogram info for this wand, using MagickGetImageHistogram method.

Let me know if you still have some doubts.
el_supremo
Posts: 1015
Joined: 2005-03-21T21:16:57-07:00

Re: Help me to find high saturation and brightness colors.

Post by el_supremo »

Thanks.
I was dividing the pixel colours by 256 instead of QuantumRange. I'm using a Q16 IM so 256 doesn't work too well.
Now to figure out why I get 6 colours but they aren't the right ones.

Pete
Sorry, my ISP shutdown all personal webspace so my MagickWand Examples in C is offline.
See my message in this topic for a link to a zip of all the files.
el_supremo
Posts: 1015
Joined: 2005-03-21T21:16:57-07:00

Re: Help me to find high saturation and brightness colors.

Post by el_supremo »

Could you post the code which does the first convert command? I'm using the logo: image as input and my code produces two extra colours in the output, all the other are identical to the output from the convert command.

Pete
Sorry, my ISP shutdown all personal webspace so my MagickWand Examples in C is offline.
See my message in this topic for a link to a zip of all the files.
rpatelob
Posts: 62
Joined: 2017-04-17T22:17:01-07:00
Authentication code: 1151

Re: Help me to find high saturation and brightness colors.

Post by rpatelob »

Check below code, you will get the sparse colours from it. This is the first part, double sparse_args hold all sparse colours, now you just need to pass sparse_args to second part. Check my previous post for second part. Let me know if you still not get the expected output.

Code: Select all

                MagickWand * wand, * wand0, * wand1;
		PixelIterator * iteration;
		PixelWand ** row;
		PixelInfo pixel;
		size_t x, y, row_width;

		wand = NewMagickWand();
		MagickReadImage(wand, "one.jpg");
		MagickSetImageAlphaChannel(wand, OffAlphaChannel);

		MagickScaleImage(wand, 50, 50);
		MagickSetImageDepth(wand,8);

		wand0 = CloneMagickWand(wand);
		wand1 = CloneMagickWand(wand);

		MagickTransformImageColorspace(wand0, HSBColorspace);
		MagickSetImageChannelMask(wand0, GreenChannel);
		MagickSeparateImage(wand0, GreenChannel);
		MagickThresholdImage(wand0, QuantumRange*50/100);

		MagickTransformImageColorspace(wand1, HSBColorspace);
		MagickSetImageChannelMask(wand1, BlueChannel);
		MagickSeparateImage(wand1, BlueChannel);
		MagickThresholdImage(wand1, QuantumRange*50/100);

		MagickCompositeImage(wand0, wand1, MultiplyCompositeOp, MagickFalse, 0, 0);

		wand1 = DestroyMagickWand(wand1);

		MagickSetImageAlphaChannel(wand, OffAlphaChannel);
		MagickCompositeImage(wand, wand0, CopyAlphaCompositeOp, MagickFalse, 0, 0);

		wand0 = DestroyMagickWand(wand0);

		size_t height = MagickGetImageHeight(wand);
		size_t width = MagickGetImageWidth(wand);
		size_t spares_index = 0;
		// Allocated enough memory to hold Sparse Color data
		double * sparse_args = malloc(sizeof(double) * height * width * 5);
		// Iterate over pixel data
		iteration = NewPixelIterator(wand);
		for (y = 0; y < height; ++ y)
		{
		    row = PixelGetNextIteratorRow(iteration, &row_width);
		    for (x = 0; x < row_width; ++x)
		    {
		        PixelGetMagickColor(row[x], &pixel);
		        // Append coord + color data if pixel is visible.
		        if (pixel.alpha == QuantumRange) {
		            sparse_args[spares_index++] = (double)x;
		            sparse_args[spares_index++] = (double)y;
		            sparse_args[spares_index++] = pixel.red / QuantumRange;
		            sparse_args[spares_index++] = pixel.green/ QuantumRange;
		            sparse_args[spares_index++] = pixel.blue / QuantumRange;
						}
		    }
		}
		iteration = DestroyPixelIterator(iteration);
		wand = DestroyMagickWand(wand);
el_supremo
Posts: 1015
Joined: 2005-03-21T21:16:57-07:00

Re: Help me to find high saturation and brightness colors.

Post by el_supremo »

Thanks for posting your code.
It produces the same output for the logo: image as my code does and they don't agree with the command line output.
This command line:

Code: Select all

convert one.jpg -scale '50x50!' -depth 8 \
'(' -clone 0 -colorspace HSB -channel gb -separate +channel -threshold 50% -compose multiply -composite ')'\
 -alpha off -compose copy_opacity -composite sparse-color:
produces 125 pixels:

Code: Select all

17,4,srgba(255,121,121,1)
17,5,srgba(255,66,66,1)
20,5,srgba(255,70,70,1)
21,5,srgba(255,115,115,1)
22,5,srgba(255,98,98,1)
15,6,srgba(255,109,109,1)
18,6,srgba(255,97,97,1)
19,6,srgba(255,85,85,1)
20,6,srgba(255,84,84,1)
21,6,srgba(255,96,96,1)
22,6,srgba(255,112,112,1)
23,6,srgba(255,125,125,1)
24,6,srgba(255,122,122,1)
25,6,srgba(255,122,122,1)
15,7,srgba(255,118,118,1)
22,7,srgba(255,85,85,1)
24,7,srgba(255,126,126,1)
26,7,srgba(255,57,57,1)
14,8,srgba(255,112,112,1)
26,8,srgba(255,99,99,1)
13,9,srgba(255,94,94,1)
14,9,srgba(255,92,92,1)
12,10,srgba(255,93,93,1)
36,10,srgba(49,75,139,1)
12,11,srgba(255,95,95,1)
35,11,srgba(189,191,78,1)
34,12,srgba(36,64,145,1)
35,12,srgba(229,225,61,1)
10,13,srgba(255,120,120,1)
11,13,srgba(255,111,111,1)
21,13,srgba(149,147,74,1)
34,13,srgba(61,84,134,1)
10,14,srgba(255,113,113,1)
9,15,srgba(255,118,118,1)
10,15,srgba(255,91,91,1)
33,15,srgba(34,62,146,1)
34,15,srgba(40,67,143,1)
33,16,srgba(38,65,144,1)
33,17,srgba(227,223,62,1)
21,20,srgba(160,101,68,1)
22,20,srgba(141,89,62,1)
23,20,srgba(168,112,83,1)
30,20,srgba(205,125,85,1)
31,20,srgba(207,128,88,1)
22,21,srgba(208,121,77,1)
23,21,srgba(202,125,86,1)
33,21,srgba(187,115,78,1)
22,22,srgba(140,79,48,1)
23,22,srgba(241,143,94,1)
33,22,srgba(202,126,88,1)
23,23,srgba(137,73,42,1)
24,23,srgba(153,97,75,1)
25,23,srgba(64,81,130,1)
30,23,srgba(165,103,72,1)
33,23,srgba(240,142,93,1)
34,23,srgba(182,117,85,1)
25,24,srgba(32,58,137,1)
33,24,srgba(229,135,88,1)
25,25,srgba(34,62,146,1)
33,25,srgba(197,111,69,1)
25,26,srgba(34,60,142,1)
26,26,srgba(34,61,144,1)
25,27,srgba(35,55,133,1)
26,27,srgba(34,62,146,1)
27,27,srgba(34,62,145,1)
26,28,srgba(35,61,144,1)
27,28,srgba(34,62,146,1)
27,29,srgba(35,60,142,1)
28,32,srgba(34,60,142,1)
28,33,srgba(34,60,143,1)
37,33,srgba(33,59,139,1)
38,33,srgba(34,59,139,1)
38,34,srgba(35,54,130,1)
29,35,srgba(32,59,138,1)
29,36,srgba(34,62,146,1)
29,37,srgba(34,62,146,1)
30,37,srgba(31,57,133,1)
29,38,srgba(34,62,146,1)
30,38,srgba(34,62,146,1)
29,39,srgba(34,62,146,1)
30,39,srgba(34,62,146,1)
31,39,srgba(34,62,145,1)
29,40,srgba(34,62,146,1)
30,40,srgba(34,62,146,1)
31,40,srgba(34,62,146,1)
32,40,srgba(33,61,143,1)
29,41,srgba(31,56,131,1)
30,41,srgba(34,62,146,1)
31,41,srgba(34,62,146,1)
32,41,srgba(34,62,146,1)
33,41,srgba(34,62,146,1)
30,42,srgba(34,62,146,1)
31,42,srgba(34,62,146,1)
32,42,srgba(34,62,146,1)
33,42,srgba(34,62,146,1)
34,42,srgba(34,62,146,1)
35,42,srgba(34,62,146,1)
36,42,srgba(34,62,146,1)
37,42,srgba(35,60,142,1)
30,43,srgba(34,62,145,1)
31,43,srgba(34,62,146,1)
32,43,srgba(34,62,146,1)
33,43,srgba(34,62,146,1)
34,43,srgba(34,62,146,1)
35,43,srgba(34,62,146,1)
36,43,srgba(34,62,146,1)
37,43,srgba(35,61,143,1)
31,44,srgba(34,62,146,1)
32,44,srgba(34,62,146,1)
33,44,srgba(34,62,146,1)
34,44,srgba(34,62,146,1)
35,44,srgba(34,62,146,1)
36,44,srgba(34,62,146,1)
37,44,srgba(35,60,142,1)
30,45,srgba(161,35,38,1)
32,45,srgba(31,56,131,1)
33,45,srgba(34,62,146,1)
34,45,srgba(34,62,146,1)
35,45,srgba(34,62,146,1)
36,45,srgba(34,62,145,1)
37,45,srgba(38,54,131,1)
30,46,srgba(161,24,27,1)
31,46,srgba(134,20,23,1)
35,46,srgba(34,54,130,1)
40,46,srgba(162,27,33,1)
But the code posted by @rpatelob in the previous message (and my code) produces these 127 pixels:

Code: Select all

23,2,srgba(142,141,71,1)
17,4,srgba(255,121,121,1)
17,5,srgba(255,66,66,1)
20,5,srgba(255,70,70,1)
21,5,srgba(255,115,115,1)
22,5,srgba(255,98,98,1)
15,6,srgba(255,109,109,1)
18,6,srgba(255,97,97,1)
19,6,srgba(255,85,85,1)
20,6,srgba(255,84,84,1)
21,6,srgba(255,96,96,1)
22,6,srgba(255,112,112,1)
23,6,srgba(255,125,125,1)
24,6,srgba(255,122,122,1)
25,6,srgba(255,122,122,1)
15,7,srgba(255,118,118,1)
22,7,srgba(255,85,85,1)
24,7,srgba(255,126,126,1)
26,7,srgba(255,57,57,1)
14,8,srgba(255,112,112,1)
26,8,srgba(255,99,99,1)
13,9,srgba(255,94,94,1)
14,9,srgba(255,92,92,1)
12,10,srgba(255,93,93,1)
36,10,srgba(49,75,139,1)
12,11,srgba(255,95,95,1)
35,11,srgba(189,191,78,1)
34,12,srgba(36,64,145,1)
35,12,srgba(229,225,61,1)
36,12,srgba(165,168,84,1)
10,13,srgba(255,120,120,1)
11,13,srgba(255,111,111,1)
21,13,srgba(149,147,74,1)
34,13,srgba(61,84,134,1)
10,14,srgba(255,113,113,1)
9,15,srgba(255,118,118,1)
10,15,srgba(255,91,91,1)
33,15,srgba(34,62,146,1)
34,15,srgba(40,67,143,1)
33,16,srgba(38,65,144,1)
33,17,srgba(227,223,62,1)
21,20,srgba(160,101,68,1)
22,20,srgba(141,89,62,1)
23,20,srgba(168,112,83,1)
30,20,srgba(205,125,85,1)
31,20,srgba(207,128,88,1)
22,21,srgba(208,121,77,1)
23,21,srgba(202,125,86,1)
33,21,srgba(187,115,78,1)
22,22,srgba(140,79,48,1)
23,22,srgba(241,143,94,1)
33,22,srgba(202,126,88,1)
23,23,srgba(137,73,42,1)
24,23,srgba(153,97,75,1)
25,23,srgba(64,81,130,1)
30,23,srgba(165,103,72,1)
33,23,srgba(240,142,93,1)
34,23,srgba(182,117,85,1)
25,24,srgba(32,58,137,1)
33,24,srgba(229,135,88,1)
25,25,srgba(34,62,146,1)
33,25,srgba(197,111,69,1)
25,26,srgba(34,60,142,1)
26,26,srgba(34,61,144,1)
25,27,srgba(35,55,133,1)
26,27,srgba(34,62,146,1)
27,27,srgba(34,62,145,1)
26,28,srgba(35,61,144,1)
27,28,srgba(34,62,146,1)
27,29,srgba(35,60,142,1)
28,32,srgba(34,60,142,1)
28,33,srgba(34,60,143,1)
37,33,srgba(33,59,139,1)
38,33,srgba(34,59,139,1)
38,34,srgba(35,54,130,1)
29,35,srgba(32,59,138,1)
29,36,srgba(34,62,146,1)
29,37,srgba(34,62,146,1)
30,37,srgba(31,57,133,1)
29,38,srgba(34,62,146,1)
30,38,srgba(34,62,146,1)
29,39,srgba(34,62,146,1)
30,39,srgba(34,62,146,1)
31,39,srgba(34,62,145,1)
29,40,srgba(34,62,146,1)
30,40,srgba(34,62,146,1)
31,40,srgba(34,62,146,1)
32,40,srgba(33,61,143,1)
29,41,srgba(31,56,131,1)
30,41,srgba(34,62,146,1)
31,41,srgba(34,62,146,1)
32,41,srgba(34,62,146,1)
33,41,srgba(34,62,146,1)
30,42,srgba(34,62,146,1)
31,42,srgba(34,62,146,1)
32,42,srgba(34,62,146,1)
33,42,srgba(34,62,146,1)
34,42,srgba(34,62,146,1)
35,42,srgba(34,62,146,1)
36,42,srgba(34,62,146,1)
37,42,srgba(35,60,142,1)
30,43,srgba(34,62,145,1)
31,43,srgba(34,62,146,1)
32,43,srgba(34,62,146,1)
33,43,srgba(34,62,146,1)
34,43,srgba(34,62,146,1)
35,43,srgba(34,62,146,1)
36,43,srgba(34,62,146,1)
37,43,srgba(35,61,143,1)
31,44,srgba(34,62,146,1)
32,44,srgba(34,62,146,1)
33,44,srgba(34,62,146,1)
34,44,srgba(34,62,146,1)
35,44,srgba(34,62,146,1)
36,44,srgba(34,62,146,1)
37,44,srgba(35,60,142,1)
30,45,srgba(161,35,38,1)
32,45,srgba(31,56,131,1)
33,45,srgba(34,62,146,1)
34,45,srgba(34,62,146,1)
35,45,srgba(34,62,146,1)
36,45,srgba(34,62,145,1)
37,45,srgba(38,54,131,1)
30,46,srgba(161,24,27,1)
31,46,srgba(134,20,23,1)
35,46,srgba(34,54,130,1)
40,46,srgba(162,27,33,1)
The first and 30th entries in the second list are not in the first one.

Anyone got any ideas why they are different?

Pete
Sorry, my ISP shutdown all personal webspace so my MagickWand Examples in C is offline.
See my message in this topic for a link to a zip of all the files.
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Help me to find high saturation and brightness colors.

Post by snibgo »

The CLI given by el_supremo looks the same as the C code from rpatelob, but with a possible problem in "QuantumRange*50/100" which might cause integer overflow or rounding problems. I would express this by "QuantumRange*(50.0/100.0)".

I assume, of course, that identical versions of IM are used for both.

As the two outputs don't match, I suggest both versions are given "write" commands for each intermediate image. This should isolate where the difference occurs.
snibgo's IM pages: im.snibgo.com
el_supremo
Posts: 1015
Joined: 2005-03-21T21:16:57-07:00

Re: Help me to find high saturation and brightness colors.

Post by el_supremo »

Hi snibgo:
I just tried "QuantumRange*50./100" and "QuantumRange*0.5" and they don't change the output.
I'm using ImageMagick 7.0.5-5 Q16 x64
I did output intermediate images but I only eyeballed them. I'll let IM compare them to see if there are any differences.

Thanks
Pete
Sorry, my ISP shutdown all personal webspace so my MagickWand Examples in C is offline.
See my message in this topic for a link to a zip of all the files.
Post Reply