home—info—archive—exams—lectures—labs—hws
Recipe—Laws—lies—syntax—java.lang docs—java.util docs
lab14a
home photoshopping network
arrays of pixels
formatting tip:
See EStyle,
for a (beta) BLueJ plug-in which formats your code.
Read the short "Basics" section on that page, for instructions.
(EStyle is not installed on the lab machines.)
On computers, images are stored as two-dimensional arrays
of colors (“pixels”).
-
Each pixel has red,green,blue components in the range [0,256).
-
Black is represented as red=0,green=0,blue=0;
-
White is represented as red=255,green=255,blue=255;
-
Red is represented as red=255,green=0,blue=0;
-
Purple is represented as red=255,green=0,blue=255;
-
Medium-Gray is represented as red=127,green=127,blue=127;
You don't need it for this lab, but people have catalogued
the rgb values for
many color names.
(You might wonder, how many possible Colors are there?
Is this more or less than the number of possible colors irl?)
-
In Java, class java.awt.Color represents colors.
The methods of note are
getRed(),
getGreen(),
getBlue().
Note that Colors are immutable (no setter methods);
if you want a pixel to have a new Color,
you must create a new Color object and then
put that Color object into the pixel-location.
-
To do
-
Download the lab14a-picts.jar.
-
Make a new MyEffects object.
Note:
A new window will be created,
showing the picture.
It might be hidden behind other windows;
check the task bar.
-
Call runEffects. What happens?
-
Look at and understand the code for MyEffects:
-
When you create a new MyEffects, it
(a) creates a Pict object,
(storing it in a field named aPict).
This is the object which gets the image from the web and
displays it on-screen.
-
Then, the MyEffects constructor
(b) asks that Pict for its array of pixels,
storing the result in the field data[][].
-
Later,
when you actually call runEffects,
the code
(c) changes the values stored in our field data[][],
and then
(d) tells the Pict object to
re-load its pictures
from our (modified) data[][].
It is this last step which actually causes the underlying
picture to be modified!
Notice what happens to greenish things (trees) and bluish things (sky)
on this transformation -- they become black(ish).
In the original image,
which started with less red in it: the sky, or the trees?
(The answer is clear, now that we're seeing only the red.)
- As a group,
let's write a method blueStripe which
replaces the middle third of the picture with all-blue pixels.
-
Change the code for MyEffects so that it
loads a different picture than the default.
Perhaps one of
Effects
Choose some effects from the following list, and implement them!
-
Make method filterPurple
which keeps the red and blue components of an image,
but sets the green component of each pixel to zero.
-
Make method invert, similar to filterRed,
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 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.
-
Write a method fadeLeftToRight which leaves the
left column untouched, the middle column halfway faded to 0,
and the rightmost column entirely black,
in a continuous fashion.
-
Make method jailbar, similar to filterRed,
which puts black vertical stripes over the image.
Hint:
-
First try a version which makes (say) exactly 20 jailbars,
each exactly 5 pixels wide.
('Course, this is impossible to do
on images less than 100 pixels wide in total!)
Helper functions are your friends:
This sounds like calling “drawOneBar”
twenty times,
which might in turn call “drawPartOfBar”
five times.
What might the inputs to these helper functions need to be?
-
Now, make a version which where the number of jailbars actually
depends on the image's width, though they are still
exactly 5 pixels wide.
(The class Pict includes a method to get the
picture's width.)
-
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 filterRight which is like FilterRed
except that it only filters the right half (or, the bottom half) of
the image.
-
Make method mirrorLR, which flips a picture
left-to-right.
-
Make a method reflectVerticleMiddle,
which leaves the left-half of the
image intact, but makes the right half a reflection of the left.
-
Write a method which adds colorful diagonal slashes at random.
-
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.
(Why is this more difficult than the previous version?)
-
Make method edgy,
which replaces each pixel with the difference between it
and some neighboring pixels.
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.
(You can first make the image black-and-white,
or you can treat each component independently.)
-
Try writing code to sharpen an image.
(This can be difficult. Don't attempt this until you have
written edgy.)
-
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 note:
-
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—archive—exams—lectures—labs—hws
Recipe—Laws—lies—syntax—java.lang docs—java.util docs