The Mathematica Journal
Departments
Feature Articles
Columns
New Products
New Publications
Classifieds
Calendar
News Bulletins
Mailbox
Letters
Write Us
About the Journal
Staff and Contributors
Submissions
Subscriptions
Advertising
Back Issues
Home
Download this Issue

Image Manipulation in Color

Color image manipulation is just like grayscale image manipulation times three. Unfortunately, it uses at least three times as much time and memory, and because color involves triplets of numbers (red, green, and blue) rather than a single grayscale value, it's harder to treat the image as a mathematical object. Be warned! The examples below, when applied to the [Graphics:../Images/index_gr_75.gif] pixel image we're using as an example, use a very large amount of memory in the kernel. You'll need at least 60 MB for the kernel to do even a few examples like these.

Of course, you can always treat a color image as three separate grayscale images, one for each color channel. Fortunately it's possible to be a bit more clever. The ListInterpolation function we used for grayscale images is able to handle not just two-dimensional data, but n-dimensional. You can think of a color image as a three-dimensional data set, two physical dimensions plus a color dimension (which happens to have only three sample points). The following command constructs an InterpolatingFunction where the third argument to the function specifies which color component you want (1 for red, 2 for green, and 3 for blue). The option InterpolationOrder tells it to use cubic interpolation in the x and y dimensions (this is the default used for grayscale images as well). Zero-order interpolation is adequate in the third (color) dimension, since we're not going to ask for values other than at exactly the sample points.

We should emphasize that using the third argument (the third dimension) to represent the color is purely a trick with no mathematical significance. You could specify values other than 1, 2, or 3 for the third argument, but the resulting images would be uninteresting. If you don't believe us, try it yourself.

[Graphics:../Images/index_gr_76.gif]

For example, to get the red color component at {0.2, 0.3}:

[Graphics:../Images/index_gr_77.gif]
[Graphics:../Images/index_gr_78.gif]

We can make a function that returns all three components at once, by generating a three-element table.

[Graphics:../Images/index_gr_79.gif]

Here is the same point as in the example above, but this time we get all three colors.

[Graphics:../Images/index_gr_80.gif]
[Graphics:../Images/index_gr_81.gif]

Now we are ready to begin plotting this image. Unfortunately, we can't use DensityPlot, because DensityPlot requires that the return value of the function being plotted be a single number. Fortunately, the way we are using DensityPlot, it's really just a simple wrapper for creating a Raster object, which we can do manually.

To simplify further examples, we'll use the following utility function to encapsulate the necessary steps.

[Graphics:../Images/index_gr_82.gif]

Here is an example using this utility function (note that the arguments are pretty much the same as they were for the grayscale examples done using DensityPlot).

[Graphics:../Images/index_gr_83.gif]
[Graphics:../Images/index_gr_84.gif]

[Graphics:../Images/index_gr_85.gif]

What about rotation? To simplify the syntax, we can define a variation of colorPuppyFunction that accepts a list (vector) of two values as a single argument, rather than two separate arguments. This allows us to use matrix manipulations to transform the coordinates.

[Graphics:../Images/index_gr_86.gif]

Here is a simple rotation of the image (done by multiplying the [Graphics:../Images/index_gr_87.gif] coordinate vector by a standard rotation matrix). In this case we are rotating by one radian (about 57 degrees).

[Graphics:../Images/index_gr_88.gif]

[Graphics:../Images/index_gr_89.gif]

What are the surprising bars around the edge of the image? We created an interpolating function that represents the image, and then we asked it to extrapolate, to give us values outside the range for which we specified sample points.

Let's try some examples where the angle of rotation depends on the distance from the center of the image. First, linearly proportional to the distance.

[Graphics:../Images/index_gr_90.gif]

[Graphics:../Images/index_gr_91.gif]

Next, proportional to the square of the distance, which turns out to give a more pleasing result, probably because it keeps the face intact while providing more twist farther out.

[Graphics:../Images/index_gr_92.gif]

[Graphics:../Images/index_gr_93.gif]

Ah, what more could anyone ask for!


Converted by Mathematica      April 21, 2000

[Article Index] [Prev Page][Next Page]