« Cris Luengo on Image...
Pixel Grid Update »

Image Zoom and Pan Utilities

Steve Eddins
Posted on Thursday, August 29, 2024

Since my retirement from MathWorks earlier this year, I have enjoyed writing MATLAB code just for myself. I tinker with things that I’m interested in, and I make them work to suit my own preferences.

Image display is one area that interests me. I’ve been involved in the evolution of the imshow function since I beta-tested Image Processing Toolbox version 1.0 in 1993, and now I want to make something that behaves a bit differently.

To get there, I need to query and set the zoom level of an image. I also need a way to query the approximate physical extent of image pixels.

To satisfy those needs, I created the “Image Zoom Level and Pan Utilities” add-on. You can get it from File Exchange or from GitHub. Here is a simple animation that I created using these utilities.

image_0.gif

Let’s explore.

Zoom level

roses = imread("roses-se.jpg");
imshow(roses)

figure_0.png

getImageZoomLevel
ans = 1x2
   27.4667   27.4667

That means that the “zoom level” is 27.5% horizontally and 27.5% vertically. But what does “zoom level” mean?

I’m defining zoom level as the horizontal and vertical extent of one image pixel, expressed as a percentage of the extent of what I’ll call a “virtual screen pixel.” In today’s world of display devices with a wide range of resolutions, this notion of a virtual pixel has evolved to help interface and website designers achieve reasonably consistent results on different devices. It’s equivalent to the CSS pixel, which is

[…] relative to the viewing device. For low-dpi devices, 1px is one device pixel (dot) of the display. For printers and high resolution screens 1px implies multiple device pixels.

https://www.w3schools.com/cssref/css_units.php

In my definition, a zoom level of 100% is equivalent to viewing an image in a web browser, such as Chrome or Safari, and selecting View / Actual Size. I can use setImageZoomLevel to show the image above at 100%.

imshow(roses)
setImageZoomLevel(100)

figure_1.png

Notice that only the central portion of the image is displayed above. That’s because setImageZoomLevel changes the zoom level without changing the axes or figure position. When you use it to zoom in, then, you might not be able to see the entire image, unless perhaps you resize the figure.

getImageZoomLevel
ans = 1x2
  100.0000  100.0000

Zooming and filling the plot region

The image zooming behavior of MATLAB and imshow has some issues. In particular, when zooming in on an image whose aspect ratio is significantly different than the normal plot region aspect ratio, the zoom doesn’t behave well. Let me show you what I mean, using a strip from the roses image that is tall and skinny.

roses_strip = roses(:,400:700,:);
imshow(roses_strip)
axis on

figure_2.png

These next lines simulate a few interactive zoom-in clicks.

xlim([107 196])
ylim([360 657])

figure_3.png

Note that the plot region hasn’t changed. It’s still tall and skinny, even though the zoomed-in image view should ideally take up more of the available width in the plot region now. Here is the available plot region:

ax = gca;
annotation("rectangle",ax.Position)

figure_4.png

The function setImageZoomLevel has been written so that the available plot region is used when the zoom level is changed. Compare with the results above:

imshow(roses_strip)
axis on

figure_5.png

setImageZoomLevel(200)

figure_6.png

Convenient zoom syntax

The add-on includes a convenient function, zoomImage, that zooms an image in and out relative to the current zoom level. For example, zoomImage(20) zooms in by a factor of 20.

imshow(roses)

figure_7.png

zoomImage(20)

figure_8.png

zoomImage(1/50)

figure_9.png

Panning

The File Exchange add-on also includes functions for querying and setting the setting the center (x,y) location of the axes. Programmatically setting this location can be used to implement a panning effect.

imshow(roses)
setImageZoomLevel(200)
axis on

figure_10.png

getAxesCenterXY
ans = 1x2
  500.5000  500.5000
setAxesCenterXY([200 50])

figure_11.png

Pixel extent

The last service provided by the add-on is determining the physical extent of image pixels. This is done using getImagePixelExtentInches.

imshow(roses)
setAxesCenterXY([685 320])
setImageZoomLevel(4919)

figure_12.png

getImagePixelExtentInches
ans = 1x2
    0.5124    0.5124

Note that these values are only rough approximations and will vary depending on the characteristics of the particular display device.

MATLAB enhancement request

I’m going to submit a MATLAB enhancement request to MathWorks about the situation where zooming in on a plot doesn’t expand to fill the available plot region. Although I showed this behavior above using imshow, I have also reproduced it using plot. I believe that it happens whenever the DataAspectRatio is set to a fixed value. Once DataAspectRatio is set, subsequent zooming operations appear to be fixed within the same “tight position.”

I think this zooming behavior is unexpected and not useful, and I hope that MathWorks will change it.