Title: Image Manipulation
1Image Manipulation
Eric Roberts CS 106A February 18, 2009
2Graphics Contest Results
The CS106A Graphics Contest February 2009
3Graphics Contest Results
Best in show
Francesco Georg, Orb
First place (algorithmic)
Michael Alyono, Welcome to the 3rd
Runner-up (algorithmic)
Lily Guo, Karels Voyage Home
Runner-up (algorithmic)
Rui Yang, Fractal Biohazard
First place (aesthetic)
Dawson Zhou, Paddle Ball
Runner-up (aesthetic)
Meghali Chopra, Just Dance
Runner-up (aesthetic)
William Ito, Random Scooby Doo Chase
Honorable mention
Matthew Blum, The Matrix
Honorable mention
Neville Eclov, Keytar Hero
Honorable mention
Garrett Schlesinger, This Is Just To Say
Honorable mention
Allen Schmaltz, Japanese Vocabulary Flash Cards
Honorable mention
Spencer Stamats, Ninja Game
Honorable mention
Jonathan Tilley, Persistence of Vision
Honorable mention
Shannon Wong, Aquarium
4Class Standings
17/36 0.47
27/34 0.79
37/59 0.63
49/83 0.59
39/69 0.57
23/70 0.33
28/89 0.31
19/67 0.28
Freshman
Sophomore
Junior
Senior
5Image Manipulation
6Image Processing
- Suppose that you have a file named JTFLogo.gif
containing the logo for the ACM Java Task Force
shown on the right.
- As you know from the discussion of the GImage
class in Chapter 9, the image actually consists
of a set of pixels arranged in a two-dimensional
array, as shown in the expanded image.
- The GImage class allows you to convert the data
for the image into a two-dimensional array of
pixel values. Once you have this array, you can
work with the data to change the image.
7Pixel Arrays
- If you have a GImage object, you can obtain the
underlying pixel array by calling the
getPixelArray, which returns a two-dimensional
array of type int.
- The first subscript in a pixel array selects a
row in the image, beginning at the top. The
height of the image is therefore given by the
expression pixels.length.
- The second subscript in a pixel array selects an
individual pixel within a row, beginning at the
left. You can use the expression
pixels0.length to determine the width of the
image.
8Pixel Values
- Each individual element in a pixel array is an
int in which the 32 bits are interpreted as
follows
1
1
1
1
1
1
1
1
1
0
0
1
1
0
0
1
0
1
1
0
0
1
1
0
0
0
1
1
0
0
1
1
transparency (?)
red
green
blue
- The first byte of the pixel value specifies the
transparency of the color, which is described in
more detail on the next slide.
9Transparency
- The first byte of the pixel value specifies the
transparency of the color, which indicates how
much of the background shows through. This value
is often denoted using the Greek letter alpha (?).
- Transparency values vary from 0 to 255. The
value 0 is used to indicate a completely
transparent color in which only the background
appears. The value 255 indicates an opaque color
that completely obscures the background. The
standard color constants all have alpha values of
255.
10Image Manipulation
- You can use the facilities of the GImage class to
manipulate images by executing the following
steps
- The program on the next slide shows how you can
apply this technique to flip an image vertically.
The general strategy for inverting the image is
simply to reverse the elements of the pixel
array, using the same technique as the
reverseArray method on an earlier slide.
11The FlipVertical Program
public void run() GImage original new
GImage("Candle.gif") GImage flipped
flipVertical(original) double y
(getHeight() - original.getHeight()) / 2
double x1 (getWidth() - IMAGE_SEP) / 2
double x0 x1 - original.getWidth() -
IMAGE_SEP add(original, x0, y)
add(flipped, x1, y)
original
flipped
y
x1
x0
24
305
164
100
FlipVertical
skip simulation
12Bitwise Operators
- If you need to change the colors of individual
pixels inside a pixel array, you need to learn
about Javas operators for working with
individual bits in the binary representation of
an integer. These operators are called the
bitwise operators.
13The Bitwise AND Operator
- The bitwise AND operator () takes two integer
operands, x and y, and computes a result that has
a 1 bit in every position in which both x and y
have 1 bits. A table for the operator appears
to the right.
1
0
0
0
0
1
1
0
- The primary application of the operator is to
select certain bits in an integer, clearing the
unwanted bits to 0. This operation is called
masking.
14The Bitwise OR Operator
- The bitwise OR operator () takes two integer
operands, x and y, and computes a result that has
a 1 bit in every position in which either x or y
has a 1 bit, as shown in the table on the right.
1
0
0
1
0
1
1
1
- The primary use of the operator is to assemble
a single integer value from other values, each of
which contains a subset of the desired bits.
15The Exclusive OR Operator
- The exclusive OR or XOR operator () takes two
integer operands, x and y, and computes a result
that has a 1 bit in every position in which x and
y have different bit values, as shown on the
right.
1
0
0
1
0
1
0
1
- The XOR operator has many applications in
programming, most of which are beyond the scope
of this text.
- Complementing a color twice restores the original
color.
16The Bitwise NOT Operator
- The bitwise NOT operator () takes a single
operand x and returns a value that has a 1
wherever x has a 0, and vice versa.
- You can use the bitwise NOT operator to create a
mask in which you mark the bits you want to
eliminate as opposed to the ones you want to
preserve.
17The Shift Operators
- Java defines three operators that have the effect
of shifting the bits in a word by a given number
of bit positions.
- The expression x ltlt n shifts the bits in the
integer x leftward n positions. Spaces appearing
on the right are filled with 0s.
- The expressions x gtgt n and x gtgtgt n both shift
the bits in the integer x rightward n positions.
The difference between the two operators lies
only in the bit value shifted in as empty spaces
appear on the left.
- The gtgt operator performs what computer scientists
call an arithmetic shift in which the leading bit
in the value of x never changes. Thus, if the
first bit is a 1, the gtgt operator fills spaces
with 1s if it is a 0, the spaces are filled with
0s.
- The gtgtgt operator performs a logical shift in
which the spaces appearing at the left are always
filled with 0s.
18Exercise Shift Operators
Suppose that the integer variable pixel contains
the following bit pattern, which corresponds to a
light-brown color
1. What is the value of pixel ltlt 2?
2. What is the value of pixel gtgt 8?
3. What is the value of pixel gtgtgt 24?
19Manipulating Pixel Values
- The bitwise operators make it possible to work
with the components of a pixel value. For
example, the expression (pixel gtgt 16) 0xFF
isolates the red component
- The GImage class exports several static methods
to support this style of pixel manipulation, as
shown on the next slide.
20Static Methods in GImage
/ Returns the alpha component from an RGB
value. / public static int getAlpha(int
pixel) return (pixel gtgt 24) 0xFF
/ Returns the red component from an RGB
value. / public static int getRed(int pixel)
return (pixel gtgt 16) 0xFF /
Returns the green component from an RGB value.
/ public static int getGreen(int pixel)
return (pixel gtgt 8) 0xFF / Returns
the blue component from an RGB value. /
public static int getBlue(int pixel)
return pixel 0xFF / Creates an opaque
pixel value from the color components /
public static int createRGBPixel(int r, int g,
int b) return createRGBPixel(r, g, b,
0xFF) / Creates a pixel value from the
color components, including alpha / public
static int createRGBPixel(int r, int g, int b,
int alpha) return (alpha ltlt 24) (r ltlt
16) (g ltlt 8) b
21Creating a Grayscale Image
- As an illustration of how to use the bitwise
operators to manipulate colors in an image, the
text implements a method called
createGrayscaleImage that converts a color image
into a black-and-white image, as shown in the
sample run at the bottom of this slide.
- The code to implement this method appears on the
next slide.
CreateGrayscale
22The CreateGrayscale Program
/ Creates a grayscale version of the original
image / private GImage createGrayscaleImage(GImag
e image) int array image.getPixelArray(
) int height array.length int width
array0.length for (int i 0 i lt height
i) for (int j 0 j lt width j)
int pixel arrayij int r
GImage.getRed(pixel) int g
GImage.getGreen(pixel) int b
GImage.getBlue(pixel) int xx
computeLuminosity(r, g, b) arrayij
GImage.createRGBPixel(xx, xx, xx)
return new GImage(array) / Calculates
the luminosity of a pixel using the NTSC formula
/ private int computeLuminosity(int r, int g,
int b) return GMath.round(0.299 r 0.587
g 0.114 b)
23Steganography
The more I reflected upon the daring, dashing,
and discriminating ingenuity of D-- . . . the
more satisfied I became that, to conceal this
letter, the Minister had resorted to the
comprehensive and sagacious expedient of not
attempting to conceal it at all.
Edgar Allan Poe, The Purloined Letter, 1845
- In his famous short story, Poe argues that it is
often best to hide things in plain sight. That
idea is sometimes used in cryptography to encode
messages thateven though they are completely
publicno one knows that the mesage is there.
This technique is called steganography.
24Exercise Stenographic Encoding
How would you write a method getStenographicChar
to extract the eight-bit character stored in a
pixel like this
private char getStenographicChar(int pixel)
int c0c1c2 (pixel gtgt 16) 0x7 int c3c4c5
(pixel gtgt 8) 0x7 int c6c7 pixel 0x3
return (char) ((c0c1c2 ltlt 5) (c3c4c5 ltlt 2)
c6c7)
25The End