Image Zoom and Pan Utilities
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.
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.
Let's explore.
Zoom level
roses = imread("roses-se.jpg");
imshow(roses)
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.
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)
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
These next lines simulate a few interactive zoom-in clicks.
xlim([107 196])
ylim([360 657])
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)
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
setImageZoomLevel(200)
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)
zoomImage(20)
zoomImage(1/50)
## 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
getAxesCenterXY
ans = 1x2
500.5000 500.5000
setAxesCenterXY([200 50])
## 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)
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.