Exploring the new PV-WAVE Photo functions (Part 1)

on Feb 14, 17 • by Ed Stewart • with No Comments

When I saw new Photo functions added for the latest release, PV-WAVE 2016.1, I was excited to try them out. I am familiar with photo editing in my personal life, so I wanted to try out the tool...

Home » Data Visualization » Exploring the new PV-WAVE Photo functions (Part 1)

I’m not that close to the PV-WAVE team any more, but still have the product installed and use it regularly for quick data analysis. In the past, I’ve used the Image functions some, but rarely. When I saw new Photo functions added for the latest release, 2016.1, I was excited to try them out. I am familiar with photo editing in my personal life, so I wanted to try out the tool.

I grabbed a recent gorgeous picture from my phone, copied it over to a file sharing app, and downloaded a copy to my work laptop. I loaded it up quickly in PV-WAVE with no issues using the new PHOTO_READ function:

WAVE> t = PHOTO_READ(‘c:\dev\data\trees.jpg’)

And then I wanted to see it on my screen, and there’s a built-in PHOTO_DISPLAY for this:


I didn’t see what I expected, see below.

First, it was rotated sideways, which I would blame on the metadata from the phone rather than PV-WAVE. The file properties indicate it is 4032 x 3024 pixels even though it was taken in portrait mode, which means I’ll need to rotate it. Further, the photo was huge on my screen. As someone lagging behind in the 4K revolution, my monitors are 1920 x 1080 at best. PV-WAVE, as a data analysis tool, is never going to modify what you see for convenience; rather, it will show you all the data it can, and all those pixels overflowed my screen. So I’ll need to resize it as well.

PV-WAVE has functions that will do these kinds of tasks to arbitrary n-dimensional arrays, but not necessarily to photographs. To make my life a little easier, and hopefully yours, I wanted to wrap some of these functions but apply them to the new photo associative arrays. I began with the ROTATE and RESAMP functions and created new PHOTO_ROTATE and PHOTO_RESAMP helper functions.

The signature for ROTATE accepts an array and a direction parameter, so I simply wrapped that API where the first argument is a photo associative array instead. Internally, it pulls out the pixel array and calls the ROTATE function with the direction supplied. The width and height keys for the photo are adjusted as well based on the resulting pixel array using the SIZE function. With this new function in hand, I can now at least get the photograph right side up with:


Next, to resize the image, I wrapped RESAMP, which accepts parameters for the new width and height along with an optional Interp keyword for bilinear interpolation instead of nearest-neighbor. I had considered making /Interp mandatory because I personally believe NN interpolation gives generally poor results, especially for images. However, NN is quite fast and there might be a use case for it. In the interest of wrapping a consistent interface, I implemented PHOTO_RESAMP to pass the keyword through to RESAMP. The width and height keys are adjusted too, although it isn’t clear to me (as far from an expert in digital photography) how or if the resolution keys should be modified, so they are left unchanged. Now I can get the full picture on my screen with:

WAVE> ts = PHOTO_RESAMP(tr, 750, 1000, /Interp)

And my photograph appeared in a PV-WAVE Window, and it looked wonderful.

Two more things appeared on my list that stemmed from this initial work. First, I tend to use the slightly more powerful ROT function over ROTATE, and second, to resize the image properly and not destroy the aspect ratio, I had to know some details about the image to properly resize it with PHOTO_RESIZE. Therefore, I added two additional short wrapper utilities.

First, PHOTO_ROT wraps the ROT function interface, accepting all of its parameters including an arbitrary angle, magnification factor, and x,y center location along with its Interp and Missing keywords. Using ROT, the output array is always the same size as the input, and so the dimension keys are not updated. This wrapper opens up some more complex manipulation options that I enjoyed playing with to see the results.

To solve my aspect ratio dilemma, I further wrapped PHOTO_RESAMP in another function called PHOTO_RESIZE. This one does not map to an existing PV-WAVE function. Instead, it allows a user to arbitrarily resize an image providing just one keyword of: Magnification, Width, or Height. Keeping the aspect ratio (AR = W/H) constant, the other two values can be computed from the supplied keyword. While using the Magnification keyword requires knowledge of the original image size, supplying either the Width or Height keyword does not.

At this point, I can now load in my phone’s photograph, rotate it, resize it for my small monitor and display it with the following:

WAVE> t = PHOTO_READ('c:\dev\data\trees.jpg')
WAVE> s = PHOTO_RESIZE(r, Height=1000)

The helper functions are included in their entirety on GitLab. Hopefully other users looking to try out the new photo functions in PV-WAVE 2016.1 will find these helpful. You can now read part 2, where I will present additional tools and utilities as I explore the new functionality.

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to top