Programming assignment #1 - Paint program
CS 248 - Introduction to Computer Graphics
Autumn Quarter, 2006
Demos on Wednesday, October 11
Writeups due on Thursday, October 12 by 2:00pm
Your assignment is to write a 24-bit paint program that runs on the teaching
lab PCs in Gates B08, using the provided user interface package.
Implement a simple rectangular overpainting brush as described in
Allow slider control over the color and size of your brush. For color control
of this brush and the tinting brush below, provide two sets of three sliders,
one set that controls R, G, and B, and a second set that controls H, S, and V
(using the single-hexcone colorspace described in section 13.3.4 of the
textbook). Allow either set to be used to select the brush color, but keep the
other set consistent on the display. For size control of this brush and the
tinting brush below, use separate sliders for width and height, or for size and
aspect ratio. We suggest the latter.
Implement a weighted mask-driven tinting brush as described in handout #4.
Allow slider control over the color and size of your brush, as described above.
Regardless of which set of three sliders (RGB or HSV) you use to select the
color of your brush, you should perform your tinting calculations in HSV, as
defined by option 2 of the section entitled "Simple tinting" in handout #4, and
using the single-hexcone space described in section 13.3.4 of the textbook.
Using check boxes, allow the user to select which coordinate(s) are affected: H
alone, S alone, V alone, H & S, H & V, S & V, or all three. Non-affected
coordinates should remain unchanged. (In other words, leave these coordinates
as you found them in the canvas.) Think carefully about interpolating hue (H),
given the circularity of that axis. Choose any mask function you like that
satisfies the conditions listed at the bottom of the section entitled "Weighted
mask-driven tinting" in handout #4. Allow slider control over one or more
parameters of your function (other than brush size and aspect ratio).
Draw 1x (actual size) and 4x (enlarged by 4x in both X and Y) visualizations of
the current brush in a second canvas. These visualizations should depict the
size, shape, falloff, and color of the brush. The visualizations should be
clearly and always visible, regardless of the brush color, the settings of the
H, S, and V check boxes, etc. Update the visualizations whenever a related
slider is moved. The purpose of these visualizations is to understand the
brush shape in its WYSIWYG, spatially discretized glory. Therefore, in the
enlarged visualization, one pixel of the actual brush should be displayed as a
4x4 pixel constant-color block; don't interpolate for the sake of the
To eliminate X or OpenGL hacking, we provide a software package,
xsupport, that displays any number of windows, called canvases, a
programmable number of sliders, and several kinds of buttons. You will need at
least two canvases, one for your painting and one for your brush shape
visualizations. The size of these canvases is programmable. The support
package runs on the teaching lab PCs and most other X-compatible workstations.
If you are working on a 24-bit workstation with hardware gamma correction (such
as our PCs), the package allows you to display your 24-bit painting directly.
If you are working on an 8-bit color workstation with no hardware gamma
correction, the package automatically dithers and gamma corrects your painting
prior to display.
The package is described in the file
/usr/class/cs248/assignments/assignment1/xsupport/README.xsupport. Everything you need to
know is contained in this file. We recommend you begin the assignment by
copying the directory /usr/class/cs248/assignments/assignment1 to somewhere in
your home directory structure and modifying the skeleton paint program
provided. While the program uses C++, it contains no fancy templates or
inheritance, so if you know C then you'll be fine. You can develop your paint
program on any platform you like, but all demos must be given on a teaching lab
PC. To help us judge the performance of your program, it should be displaying
on the same machine it is executing on during your demo.
Some hints and additional requirements
The support package handles all mouse events outside the canvas; you handle
mouse events inside the canvas. Painting should start when the left mouse
button is pushed and the mouse is in the canvas. It should stop when the
button is released. While the button is pushed, you could either paint at full
throttle even if the mouse is held motionless, or you could apply a new brush
instance only if the mouse moves some minimum distance. Experiment with
different effects. (You only need to implement one.) Note that the support
package allows you to modify the rate at which you receive mouse events if the
mouse is held motionless while the button is pushed.
During painting, you should clip the brush action to the boundaries of the
canvas. (This is required.) Your goal should be to allow unimpeded painting
near the boundary even if the brush straddles the boundary. You want your
painting surface to seem infinitely large, seen through a window equal to your
canvas. If your clipping is working correctly, you should be able to paint the
lower-leftmost pixel in your canvas using the upper-rightmost pixel in your
brush even though most of the brush is beyond the canvas boundaries. Note that
in keeping with the usual X convention, you retain control of the mouse when it
wanders beyond the canvas boundaries as long as the button stays pressed.
Use this control to your advantage in satisfying the above requirement.
To facilitate debugging of this and future assignments, we suggest making
liberal use of a standalone pixel magnification utility, such as "xmag" in
/usr/pubsw/X/bin/ (works on any X workstation). Your program must include the
ability to load images from .ppm files. (This ability is already built into
paint.c.) If you want a test background image, large and small versions of an
alpine pasture and other images are available at /usr/class/cs248/images/*.ppm.
To get an intuition for how RGB and HSV color mixing work, try one of the many
interactive color pickers on the web (for example at
Think hard about the design of your user interface. Are your controls easy to
use? For example, if the user chooses a brush color that causes the brush
visualization to disappear, should they need to fiddle with a separate control
to make it appear again? Do your controls keep the user from "getting in
trouble"? For example, you probably shouldn't allow a brush size of 0 pixels,
or 1000 pixels! Are your controls intuitive? If the user sets the saturation
to zero, hue becomes undefined. However, setting the displayed hue to -1 in
this case is probably not a good UI feature. Moreover, if the user sets the
saturation to zero, then resets it to a non-zero value, why should they lose
their hue setting at all?
Every year, a few students completely misinterpret the intended behavior of the
required brushes. If you attend the help session, we will demonstrate how
these brushes should work. If you don't attend, at least look over the
Powerpoint slides from the session. We also allow and encourage you to glance
briefly at your neighbor's paint program (but not at their code) to make sure
your brushes are doing the right thing. Ask their permission first, of course.
There are two parts to submitting your paint program: giving a demo on
Wednesday, October 11, and submitting an online writeup by 2:00pm on Thursday,
For the demos, an online signup sheet will be linked from the CS248 webpage a
few days before October 11. Sign up for a one-hour slot sometime during which
you will be called upon to give a 10-15 minute demo. The evening slots will be
reserved for SITN students. Other students can sign up for these slots only if
all other slots are taken. All demos must be given in the lab. To keep the
demos fair, you must freeze your executable by 7:30am on demo day and give your
demo from that executable. To freeze your executable, run the script
/usr/class/cs248/bin/submit. You will be prompted for the location of your
submission directory. If you run the above command from that directory, just
type "." (without the quotes). You may make multiple submissions until 7:30am,
after which time submission will be disabled for the remainder of the day.
Since you will be demoing from the executable you submitted, make sure it is a
Linux executable that runs on the teaching lab PCs. During the demo, we will
ask you to load an image of our choosing. Make sure this functionality works
in your code, including proper sizing of the canvas array.
Writeups consist of a commented copy of your source code, a Linux executable
that runs on the teaching lab PCs, a Makefile, and a README describing the
functionality implemented. Be brief but complete; one screenful is enough. If
you did something especially clever, tell us about it. By the way, if we need
to do anything more than 'make' to compile your code, please include these
instructions in your README file. To make your submission, place all these
files in one directory (and optionally subdirectories) and once again run the
script /usr/class/cs248/bin/submit. You may make multiple submissions; we will
consider only your latest submission while grading. If all goes well with the
submission, pat yourself on the back and start gearing up for the next project.
If not, and the submit script reports errors, please email the error messages
with a gzipped tarball of your submission directory to
The assignment will be graded on correctness (40 points), efficiency (20
points), programming style, including your writeup (20 points), and the
elegance of your user interface (20 points). Note: you are welcome to fix bugs
between freezing your executable for the demo and submitting your writeup.
However, the functionality, correctness, efficiency, and UI of your program
will be graded based only on what you show us during the demo. Only your
source code and your README file will be graded from your submitted writeup.
If you have completed the assignment you can earn extra credit by adding bells
and whistles. Here are some suggestions. Feel free to make up your own.
Allow interactive manipulation of brush size, shape, and fall-off directly on
the visualizations displayed in the second canvas (as an alternative to
sliders). Make your interface intuitive.
Implement a software cursor, used only when the mouse is inside the canvas,
that is more suitable for painting than the default arrow cursor. A good
cursor would be visible over any image, regardless of color, and it would avoid
obscuring too much of the area being painted. Segmentation faults are frowned
upon, so remember to clip your cursor to the boundaries of the canvas. You can
disable the hardware arrow cursor in xsupport by setting the
"DisableHardwareCursor" member of the canvas structure to a non-zero value
prior to calling LiftOff().
Implement some fancy brushes, such as a filter brush, smear brush, color cycle
brush, or rubber-stamp brush with transparency. We'll describe these and
others in the help session for this assignment.
Implement painting on textured paper. Provide some kind of user control over
the texture. For inspiration, look at Procreate's Painter program.
Implement cloning such as found in Procreate's Painter. A good paper on this
technique is Paul Haeberli's `Paint By Numbers: Abstract Image
Representations,' Computer Graphics (Proc. Siggraph), Vol. 24, No. 4,
August, 1990, pp. 207-214. (We'll give this paper out in class. In addition,
PDF file with the images in color is linked into the course schedule.
Implement a fill algorithm from section 19.5 of the textbook. For more fun,
implement a soft-filling algorithm.
Implement unlimited undo / redo, allowing the user to "cancel" / "restore" the
effect of any number of brush strokes (from button down to button up). Why
unlimited? An artist working rapidly may lay down many brush strokes before
realizing that a mistake has been made. Single-stroke undo is seldom
sufficient. Some cleverness will be required to avoid excessive memory use or
Record a painting session (multiple brushstrokes), then allow the user to
change one or more brush parameters (color, size, shape, etc.), and "replay"
the session, yielding a new painting. For extra fun, allow the user to control
which brushstrokes are affected by a change. One way to select brushstrokes is
to provide slider-controlled playback of the painting session (using your
unlimited undo machinery). Another way would be geometrically, using a
bounding rectangle or freeform lasso (like Photoshop).
Display in a third canvas the constant H, constant S, and constant V surfaces
from a hexcone or other cylindrical colorspace. (You need to implement all
three to get credit for this one.) Allow selection of H, S, and V for your
brush from any of these three surfaces. When a value is selected from one of
the surfaces, update the other two to display the appropriate slices from the
hexcone. For extra credit, add an axonometric or perspective projection of the
3D colorspace showing in color the currently selected constant H, S, and V
Copyright © 2006 Marc Levoy
October 2, 2006 05:28:06 PM