3
$\begingroup$

I've built a small manipulate widget to extract a pixel value from an image whereever the mouse is clicked:

img = ExampleData[{"TestImage", "Lena"}];
{w, h} = ImageDimensions@img;
Manipulate[
 Grid[{{img, 
    Grid[{{"Point Value", pt}, {"RGB Value", 
       ImageData[img][[Round[pt[[1]]]]][[Round[pt[[2]]]]]}}, 
     Frame -> All]}}], {pt, {0, 0}, {w, h}, Locator}]

This works really well. Now, my images of interest are quite large, and I'd like to be able to zoom into the image. So, I tried replacing my image, with a DynamicImage:

img = ExampleData[{"TestImage", "Lena"}];
{w, h} = ImageDimensions@img;
Manipulate[
 Grid[{{DynamicImage[img], 
    Grid[{{"Point Value", pt}, {"RGB Value", 
       ImageData[img][[Round[pt[[1]]]]][[Round[pt[[2]]]]]}}, 
     Frame -> All]}}], {pt, {0, 0}, {w, h}, Locator}]

DynamicImage, and Mainpulate appear to be fighting for control of the mouse, so when I click on a pixel in the zoomed in image, the image rescales to full size, and I lose the zooming.

Is there an easy way to fix this?

$\endgroup$

3 Answers 3

3
$\begingroup$

There is also built-in functionality that is much like what you ask for. If you import your image, click on it, and choose the "Coordinates Tool" then you get a numerical readout of the position and r-g-b values of the image. You can "zoom in" by selecting the Tooltip Options to set the range of pixel values displayed in the popup box.

enter image description here

$\endgroup$
1
  • $\begingroup$ That is the motherlode of widgets I've been wanting to find in Mathematica, and hadn't realized it was right under my nose.... Boy do I feel silly not noticing that earlier. THANKS! $\endgroup$
    – John
    Feb 20, 2021 at 17:38
1
$\begingroup$

You are right, Manipulate capture the mouse. A way around this is to make the zoom and the point choice separate functionalities. Toward this aim, I draw 2 images, the first one to choose a point. The second smaller one to choose the zoom window.

img = ExampleData[{"TestImage", "Lena"}];
{w0, h0} = ImageDimensions@img;
Column[{pt = {0.5, 0.5} {w0, h0};
  Dynamic@
   LocatorPane[Dynamic@pt, 
    Image[ImageTrim[img, {zo1, zo2}], ImageSize -> {w0, h0}]], 
  Dynamic@Grid[{{"Point Value", 
      Dynamic[Round /@ pt + zo1]}, {"RGB Value", 
      ImageData[img][[Round[pt[[1]]]]][[Round[pt[[2]]]]]}}, 
    Frame -> All], zo1 = {0, 0}; zo2 = {w0, h0}; 
  LocatorPane[Dynamic[{zo1, zo2}], img]}]

enter image description here

enter image description here

enter image description here

$\endgroup$
0
$\begingroup$

The Manipulate is a kind of DynamicModule and it does not like when you try to put another such module (DynamicImage) inside it. Let's say, the img=a. I tried something like this:

{w, h} = ImageDimensions[a];
pt = Round[{w, h}/2];
pb = {};
zmax = 120;
fixed = False;
Manipulate[
 Column@{
   Panel@Row@{
      Button[
       If[fixed, "Unfix zoom", "Fix.zoom"],
       If[fixed, fixed = False; pt = pb, fixed = True; bb = b; 
        pb = pt],
       ImageSize -> 100],
      Spacer[100],
      Column@{
        If[fixed,
         Grid@Transpose@{{"R: ", "G: ", "B: "}, PixelValue[bb, pt]}, 
         Style["Fix Zoom for pixel check!", Blue, 16, Bold]]}
      },
   pmin = {w/zmax zz, h/zmax zz};
   pmax = {w/zmax zz, h/zmax zz};
   b = ImageTrim[a, {pt - pmin, pt + pmax}];
   LocatorPane[Dynamic@pt, Show[If[fixed, bb, b], ImageSize -> 800]]
   }, {{zz, zmax, "Zoom"}, zmax, 1, -0.05}]

It works easy: if zoom is unfixed, an any point can be chosen by mouse clicking as point of interest. After this the Zoom-slider allows desired zooming of the image around the chosen point. When zoom is enough, fix it by pressing the button "Fix zoom". It switches the interface to pixel value measurements - just point out the desired pixel by mouse clicking and see the RGB data..

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.