CS 315 Homework 2 - MiniPaint
Due Fri Sep 20 Sun Sep 22 at 11:59pm
Overview
In this assignment, you will complete the implementation of a two-dimensional editor which does its own scan conversion of simple primitives. The user interacts with the editor using Android input mechanisms and touch (or mouse, for the emulator). The editor allows the user to draw points, lines, circles, polylines (a set of connected line segments), and filled rectangles. It also offers a flood-fill option, which replaces connected pixels of one color with another color. Finally, the editor also offers a slick-looking airbrush for true artists in the class.
This assignment should be completed individually.
Objectives
- Practice implementing scan conversion algorithms and working with pixel rasterization
- Begin working with color mixing and definitions
- Continue working with Android and the Android development environment
Necessary Files
You will need to download and extract a copy of the
starter code.
This project includes all the setup you should need to begin drawing. Note that the zip file also contains a README.txt
file that you will need to fill out.
Some notes about the starter code:
- There are two source files, similar to the previous assignment:
MainActivity
andMiniPaintView
. The Activity class runs the Android program and sets up the UI elements. The View class is the canvas upon which we are drawing. Skim over these classes and make sure you understand them! Note that you should not have to modify the Activity class, just the View class. - There are a number of methods which have been left for you to complete; each is marked with a TODO comment (which Eclipse should highlight for you--note the feedback from your IDE!) Details about completing these methods can be found below.
-
As you likely used in the previous assignment, the View class uses a
BitMap
as the underlying frame buffer. You can access the pixels of this bitmap using thesetPixel()
andgetPixel()
methods; I have also created convenience methods for you to use if you want.- In order to make development easier and to assist in debugging, the BitMap is sized to be a scaled down version of the Android View. This gives the view a lower dpi (dots per inch), and makes each "pixel" appear as a larger spot on the screen. You can adjust the scale of the BitMap by changing the value of the
PIXEL_SIZE
constant. A value of 8 produces nice large blocks that are easy to see. - The BitMap will draw changes to the screen as fast as it can (which won't be as fast as you'd like). However, if you want to slow down the drawing so that you can carefully watch what your program is doing, you can set the
DELAY_MODE
constant totrue
; if you are using the providedsetPixel()
helper method, this will put a small pause between each pixel drawing, allowing you to easily see the order. You can also modify theDELAY_TIME
.
- In order to make development easier and to assist in debugging, the BitMap is sized to be a scaled down version of the Android View. This gives the view a lower dpi (dots per inch), and makes each "pixel" appear as a larger spot on the screen. You can adjust the scale of the BitMap by changing the value of the
-
The program also supports loading in files that are lists of drawing commands. This can be very helpful for debugging, since it's a pain to reproduce a precise series of mouse clicks. Files are stored in the
res/raw/
folder as.minipaint
text files; the parser is already written for you. You can look at the sample files that come with the starter code to get a sense of the format. You are also welcome to create your own testing files; you will need to add them to the list of files in the Activity class.- Be sure your program still reads the .minipaint files when you are done! These are good way for you to test your program, and are how I will grade your work.
- Finally, be sure and refactor the project to change the package name to include your name! :)
Details
Your task is to fill in the empty methods and code blocks in order to implement the app's scan conversion of primitives. I have provided method signatures for you.
-
onTouchEvent()
responds to user interaction events (touches or mouse clicks). You will need to fill in some of the details of this method to respect primitives that require multiple touches to create. For example, the first touch specifies the upper corner of a rectangle, while the second touch specifies the lower corner. You can use the provided instance variables_startX
and_startY
to do this. Note that there is no drawPolyline method; you should just reuse the drawLine() method! -
drawLine()
should implement the Bresenham line algorithm that we discussed in class. -
drawCircle()
should implement the Bresenham circle algorithm that we discussed in class. -
drawRectangle()
should draw a filled rectangle. You are allowed (and encouraged) to reuse your drawLine() method for this. However, do not use your floodfill function to create the filled rectangle! -
floodFill()
should change all (connected) pixels that are the same color as the clicked "seed" pixel to whatever the current drawing color is. In order to get full credit, you need to implement therun-based
4-connected flood fill algorithm discussed in class.- You should implement this functionality without using a recursive function Each time you make a recursive function call, you add a significant amount of data onto the stack. Since the program stack is a finite size and most operating systems do not protect against stack overflow, it is dangerous to use recursion for flood fill. Moreover, the context switch required to move between program frames will introduce a noticable speed hit. Instead, you should use an explicit stack--you may implement your own, but you should probably just use the java
Stack
orLinkedList
classes that are available in Android.
- You should implement this functionality without using a recursive function Each time you make a recursive function call, you add a significant amount of data onto the stack. Since the program stack is a finite size and most operating systems do not protect against stack overflow, it is dangerous to use recursion for flood fill. Moreover, the context switch required to move between program frames will introduce a noticable speed hit. Instead, you should use an explicit stack--you may implement your own, but you should probably just use the java
-
airBrush()
is a method that implements an "airbrushing" technique similar to that used in Photoshop, where the color of the brush is blended with the color of the background. The pixel right where the user touched/clicked is painted with the paintbrush color, and every pixel within a specified radius is blended between the background and the paintbrush color. The farther a pixel is from the starting point, the more it looks like the background.- Note that we will not discuss this in class, so you'll need to design your own implementation. You can hard-code the "radius" of the brush (use a constant!), and you don't need to worry about optimizations at all. The goal is to begin thinking about color blending. Above is an example of what your airbrush should look like; the drawing color is black, and the red rectangle was there previously. Your airbrush does NOT have to follow this exact fall-off pattern!
-
A note on Color:
Colors in Android are represented by 4-byte integers. Each bit represents a different "channel" or component: red, green, blue, and alpha (used for transparency). You can access these colors using bitwise operations, or by using static utility methods in the
Color
class. For example, you can access the 'red' channel by using theColor.red()
method. You can create a new color from individual red green and blue components using theColor.rgb()
method.
Extensions
You are encouraged to add new features and capabilities to your minipaint program (e.g., new primitives, new interface features, new touch events, rotated rectangles, etc). Check in before you do anything too time consuming; this is intended to be a shorter assignment.
Submitting
BEFORE YOU SUBMIT: make sure your code is fully documented and functional! I will be grading primarily on functionality as demonstrated with the .minipaint files.
Upload your entire project (including all the src, resources, layouts, libraries, etc) to the Hwk2 submission folder on hedwig. Also include a filled-in copy of the README.txt file in your project directory!
The homework is due at midnight on Fri Sep 20.
Grading
This assignment will be graded based on approximately the following criteria:
- Scan-converts lines [15%]
- Scan-converts circles [15%]
- Supports polylines [10%]
- Scan-converts rectangles [10%]
- Supports floodfill [20%]
- Airbrush tool [20%]
- Code is documented and understandable [5%]
- README is completed [5%]