9

I need to figure out a way to find out the RGB color value at a certain coordinate in a Graphics object. The Graphics object I am dealing with is continually Dynamically updated, so it is made of moving objects. How can I find the color at a certain point in this moving graphics object.

There is a function, for Image type, called ImageValue which will give color at the given point, but then I have to somehow convert the Graphics to a Image each time I want to check the color at a point, since the Graphics is changing. I have the following code to do that, but it takes much too long to do so, and causes a visible pause. I replace the Dynamic type of the Graphics with Image.

image = screen /. Dynamic -> Image

The above calculation takes too long, when I checked the timing of it.

What I am asking for is a faster, easier way to make a Dynamic Graphic an Image so I can take color like that, or a way to take color at a certain point in Graphics.

Please help, A frustrated student.

Code except:

screen = Dynamic[Show[{backdrop, carsList}];
image = screen /. Dynamic -> Image;
points = ImageValue[image, {newX, newY}];
    For[i = 1, i < Length[points], i++,
            If[points[[i]] == {0, 0, 2/3} || points[[i]] == {1, 0, 0},
                valid = False;
                Break[];
            ];
        ];

points would usually hold more color data for points, I shortened code.

Chirese
  • 185
  • 1
  • 5
  • See this question and its answers. Is that what you're looking for? – rm -rf Apr 01 '12 at 04:19
  • 1
    Please consider including (a stripped down version of) your code in your question, so that those wishing to help do not have to recreated your project from scratch and a lot of guesswork. – Mr.Wizard Apr 01 '12 at 04:19
  • @R.M I presume he wants to go the other way: a simple "eyedropper" tool (Photoshop terminology). – Mr.Wizard Apr 01 '12 at 04:21
  • I edited to include code. It is a simplified version of what I have, with a lot of extra variables removed,etc. – Chirese Apr 01 '12 at 05:29

1 Answers1

5

This method uses Intersection to test the colours, which should be faster than looping through the list of sample points.

I.e. with sample image, a:

a = Graphics[{Yellow, Rectangle[{0, 0}, {300, 185}], 
    Inset[Graphics[{Blue, Rectangle[{0, 0}, {20, 10}]}],
     {100, 140}, {0, 0}, {20, 10}]},
   PlotRange -> {{0, 300}, {0, 185}}, ImageSize -> 300];

samplepoints = {{101, 141}, {117, 141}, {117, 148}};
testcolours = {{255, 255, 0}, {255, 255, 255}, {0, 0, 0}};

b = Rasterize[a];
pointcolors = Part[b, 1, 1, #2, #1] & @@@ samplepoints;
valid = Intersection[testcolours, pointcolors] == {}

True

The test does not find yellow, white or black at coordinates (101, 141), (117, 141) or (117, 148) and so sets valid True.

Note

I opted not to use ImageValue as I found its results unpredictable, e.g.

newsamplepoints = {{1, 1}, {101, 141}, {117, 141}, {117, 148}, {300, 185}};

b = Rasterize[a];
pointcolors = Part[b, 1, 1, #2, #1] & @@@ newsamplepoints;
Graphics[{RGBColor @@ #, Disk[]}, ImageSize -> 20] & /@ pointcolors

enter image description here

pointcolors = ImageValue[a, newsamplepoints];
Graphics[{RGBColor @@ #, Disk[]}, ImageSize -> 20] & /@ pointcolors

enter image description here

There are only colours yellow and blue in the sample graphic.

The rasterizing method does seem to be a little slower though. You could use either.

moresamplepoints = 
  Transpose[RandomInteger[{1, #}, 10000] & /@ {300, 185}];

Timing[(b = Rasterize[a];
  pointcolors = 
   Part[b, 1, 1, #2, #1] & @@@ moresamplepoints;)]

{0.078, Null}

Timing[pointcolors = ImageValue[a, moresamplepoints];]

{0.031, Null}

Chris Degnen
  • 30,927
  • 2
  • 54
  • 108