home—info—lects—labs—exams—hws
D2L—tutor/PIs—zoom (snow day)
Object120 + its docs—java.lang docs—java.util docs
processing bitmaps (color)
2-D arrays of objects
We will continue
processing images as 2-d arrays of pixels,
as in the previous lab (pixel as int — B&W),
and
the preceding
lecture (pixel as a
Color object).
Review
Review, on processing a 2-D array:
a helper method, vs. a nested loop:
- Approach 1:
To fill the array, fill each row.
To fill a row, fill the pixel in column 0 through column rowlength-1.
static void fillArrayRandomly( int[][] someArray ) {
for (int rowNum=0; rowNum<someArray.length; ++rowNum) {
fillRowRandomly( someArray, rowNum );
}
}
static void fillRowRandomly( int[][] someArray, int rowNum ) {
for (int colNum=0; colNum<someArray[rowNum].length; ++colNum) {
someArray[rowNum][colNum] = rng.nextInt(256);
}
}
// A static field: only one random-number-generator is needed
// for all the numbers we'll ever want.
static java.util.Random rng = new java.util.Random();
|
- Approach 2:
we can in-line the code for fillRowRandomly
into fillArrayRandomly:
static void fillArrayRandomly( int[][] someArray ) {
for (int rowNum=0; rowNum<someArray.length; ++rowNum) {
for (int colNum=0; colNum<someArray[rowNum].length; ++colNum) {
someArray[rowNum][colNum] = rng.nextInt(256);
}
}
}
// A static field: only one random-number-generator is needed
// for all the numbers we'll ever want.
static java.util.Random rng = new java.util.Random();
|
Pict.fileToPixelsBW takes the name of a jpeg or gif file
(either a filename, or a URL),
and returns a 2-D array of ints in [0,256).
Here are some pictures you might want to convert to an array-of-ints,
and then modify:
See further documentation
on the provided class Pict.
You can also look at and run the main method of that class.
You can put your methods in a separate class;
just be sure to call the provided (static?!) methods by using their class-name:
Pict.methodName.
representing Colors
Review:
These are the issues we talked about
this morning in lecture
A java.awt.Color
has three components: red (from 0 to 255), green, and blue
(customarily in that order).
So new Color(0, 255, 0) represents bright green:
it has
the maximum possible green-ness,
but zero red-ness and zero blue-ness.
White light is the mixture of all of these three primary colors:
new Color(255, 255, 255).
What represents black?
What colors can we mix, to get purple?
Gray?
We can use Pict.fileToPixelsColor to take in a filename or URL,
and be given a 2-D array of java.awt.Colors, to work with.
Likewise, Pict.displayPixels will take such a 2-D array and
display it on the screen as an image.
And as before, we might modify that 2-D array ourselves.
/** Change one pixel of an image, keeping all the red
* (but throwing away the blue and green components).
* @param img The image (2-D array of Colors) to modify.
* @param r the row-number of the pixel to modify.
* pre-condition: 0 <= r < img.length
* @param c the row-number of the pixel to modify.
* pre-condition: 0 <= c < img[r].length
*/
void filterRed( Color[][] img, int r, int c ) {
Color origPxl = img[r][c];
int origRed = origPxl.getRed();
Color udpatedPxl = new Color( origRed, 0, 0 );
img[r][c] = updatedPxl;
}
|
(Of course, the body of this method could easily be combined into one line:
img[r][c] = new Color( img[r][c].getRed(), 0, 0 );;
it is broken into multiple lines just to the individual steps easier to see.
Your task: write a method that filters the purple of
an entire image, not just one pixel.
(You can process the entire array in the same way
we initialized a 2-D array in class:
We already have a method to modify an designated pixel;
make a method which modifies one designated row
(calling the modify-one-pixel method as a helper)
then
make a method which modifies every row
(calling the modify-one-row method as a helper).
Color effects
-
Ignore:
We did this code in lecture
Make method invertColor, similar to invert,
which complements each component:
a color of red=0,green=10,blue=254
would be replaced with
a color of red=255,green=245,blue=1.
-
Make method filterPurple
which keeps the red and blue components of an entire image,
but sets the green component of each pixel to zero.
You should have a helper which just filters the purple in
one single row,
and another which just filters an individual pixel.
Optional:
The resulting image is less bright than the original (perhaps by 1/3 on average?).
If you want, try to
compensate by scaling up the other two components (but making sure not to exceed 255 in any one component).
-
Make method filterPurpleEveryOther
which only filters every other row of the input image/array.
This should call the helper from the last problem.
Be careful that you correctly handle images of odd width — don't try to tint a column
that doesn't exist!
hint:
One possible approach:
Make a variable i that goes from zero to half the width (quotient);
then color column 2*i.
-
Make method filterPurpleBands
which only filters every other group of k rows of the input image/array.
I recommend a helper function that just filters one band
of k rows.
What piece(s) of info do you need pass this function?
hint:
One possible approach:
Make a variable i that goes from zero to 1/2k of the width (quotient);
then start a new band at column i*2*k, coloring the following k rows.
-
Go back and rewrite filterPurpleEveryOther so that it is just a one line call to
filterPurpleBands.
-
Go back and rewrite filterPurple so that it is just a one line call to
filterPurpleBands.
hint: Remember how we compute the height and/or width of a 2-d array.
Submit what you are able to complete on D2L;
I hope that you complete at least #2 and #3.
More Ideas
If you want more ideas of photoshop effects,
there are plenty more ideas.
Try any of these, if they grab your fancy:
-
Make method toBlackAndWhite,
which replaces each pixel with the average of the three components.
That is,
a color of red=0,green=10,blue=80
would be replaced with
a color of red=30,green=30,blue=30.
-
We can also combine two pictures in various ways:
Superimpose one small picture on top of another.
Or, take the average of two pictures, to create a third.
Best: for any double p in 0..1,
blend two pictures by adding p times each pixel
from the first picture, plus (1-p) times each pixel
for the second picture.
(If you were make a movie where p varied from 0 to 1,
you'd have a continuous fade from one picture to another.)
-
Greenscreen --
Take a picture of yoruself against a solid green background
Now, copy all non-green pixels in that picture onto a
picture of (say) the moon.
Voila, we now have a pciture of you on the moon!
-
Take any two other effects you've written,
and make a method which applies both of them.
(Does the order matter?
That is, if you filterRed and then convert to black and white,
is that the same as converting to black and white and then filtering
out the red?)
-
Write a method fadeLeftToRight which leaves the
left column untouched, the middle column mulitplied by 1/2
(that is, faded halfway to 0),
and the rightmost column multiplied by 0 (entirely black),
in a continuous fashion.
-
Write blocky, which replaces each 3×3 group of pixels
with a single color (the average of the original nine).
For a further challenge,
generalize this to making n×n blocks, where n is a parameter.
-
Make method blur,
which replaces each pixel with the average of the pixels
adjacent to it.
Note that this is difficult to do “in place” (modifying the array);
instead have this method return a new array/image.
-
Make method edgy,
which replaces each pixel with the difference between it
and the pixel to its left.
(the leftmost column is unchanged).
That way, edges (which have a big difference from nearby pixels)
will be bright,
while large areas of the similar brightness (like a bright sky)
will be dark.
For better edge detection, replace each pixel with the
maximum difference between it and the pixel to
its left, above it, or above-left.
(Credit to jmdymacek for the exact scheme.)
Further notions
-
Write a method which adds colorful diagonal slashes at random.
-
Red-eye reduction (more difficult).
First, by hand, find some pictures that have red-eye in them,
and try to detect what RGB values the eyes have.
Then write a filter to try to detect and ameliorate
such colors in actual photographs.
(A professional application might even try to detect circles in
the input image, but that's a lot tougher.)
-
Write a method which applies one of your effects just to a circle
in the middle of the picture (with, say, a radius of 20 pixels).
Hint:
As before, still call the pixel-changing method on every single location,
but have that method only do its work if it is within 20 pixels
of the image's center.
-
See if you can find on the web, how to make an effect
replicating sepia (old-timey) photographs,
and implement that.
-
Surprise me!
For each of the above effects, it's interesting to wonder:
-
Does applying the effect twice differ from applying it once?
(
idempotence
)
-
Are there two different input pictures which might end up looking
identical after the effect?
(
invertable
)
-
If we keep applying the effect over and over and over, will we converge
on a certain solution? (
a fixpoint
)
Are there different images which might converge to the same solution?
(basins of attraction
)
-
If we apply two effects in a row, does it matter which order we do that in?
(
commutativity
)
The answers of course vary for the different choices of effects.
home—info—lects—labs—exams—hws
D2L—tutor/PIs—zoom (snow day)
Object120 + its docs—java.lang docs—java.util docs
 This page licensed CC-BY 4.0 Ian Barland Page last generated | Please mail any suggestions (incl. typos, broken links) to ibarland radford.edu |
 |