Android Impressionist Painter

Due: Tues, Nov 22, 11:59PM


Assignment Overview

In this assignment, you will apply your growing UI programming skills to make a more sophisticated interactive prototype--an impressionist painter.
The painter works by loading in an existing image, examining some aspects of that image translated from the user's touch location (e.g., the color at pixel [x,y]), and using that to dynamic set properties in a brush. This assignment is based on Paul Baeberli's seminal 1990 SIGGRAPH paper "Paint By Numbers: Abstract Image Representations" (DOI) and by a course assignment offered in Computer Science and Engineering at the University of Washington, which I did back in 2005 but was highly influential to me! (2005 link, more recent 2014 offering).

While there are similarities between IA08: Doodle and IA09: Impressionist, you should start a completely new project for IA09 in Android Studio. In contrast to the last assignment, I would like you to default to a landscape orientation where the loaded image is on the left (in an ImageView) and the impressionist painting space is on the right (a custom View class, which I call ImpressionistView). In addition, please focus on designing for a tablet device (though your code/UI should also run on an Android phone). To help you get started, I have provided a skeleton project with an initial layout, some buttons, and the ImpressionistView class (link). You are welcome to change any of this as you see fit.

Similar to IA08, you will post your code to github and upload a demo of your interface to YouTube. In addition, we ask that you upload 1-3 pieces of artwork that you made with your app. Matt and I will cull these to a list of our top ~10 favorites, which the class will then vote for. Top selections will be listed on this webpage.

Video Demo

This video demo illustrates the overall functionality of this assignment and some example brush types. The video is not comprehensive and does not include all required features (e.g., the save feature is not shown).

Required Features

  1. You must implement three brush types where a brush type is defined by having a certain shape (circles, triangles, squares) and/or behavior (paint splatter). At least one brush type must change it's behavior based on the motion of the user's finger (e.g., the brush size is dynamically set by the velocity of the finger or the brush direction is orthogonal to the user's motion). The user should be able to dynamically select the brush types and use multiple brushes on the same painting. To help inspire you to think of brush types, here are the results for the Google Images search: "Impressionist Art".
  2. You must implement a load image feature. This is already done in the initial project code I provided.
  3. You must implement a save feature. The saved file should be automatically added to the Android photo gallery.
  4. You must implement a clear feature that clears the painting but keeps the loaded image.
  5. You must implement one bonus feature that is distinct from IA08: Doodle. So, for example, if you implemented undo/redo in IA08, you cannot use this as your bonus feature in IA09 (though you can certainly program this functionality). See below for a list of potential bonus features. Note: we will give 5 extra bonus points for creative uses of Android Motion Sensors (e.g., brush moves on canvas with device motion, paint drips based on device tilt).

Bonus Feature Ideas

This list is just to get you started. Feel free to implement one of these ideas, remix one of these ideas, and/or do something completely new!
  • Use the device's camera to take a picture and load as the current ImageView, so you can quickly make impressionist artwork of your friends or other interesting things
  • To give your users more feedback, draw the location of the touch down and movement point on the ImageView. To do this, I suggest creating your own ImageView (e.g, ImpressionistImageView) that subscribes to touchdown events in the main ImpressionistView. You will have to translate the [x,y] touch locations to the ImageView.
  • Use Android's built-in physical motion sensors like the accelerometer or gyroscope to enhance your impressionist interface--for example, a brush is controlled by tilting the device. See Android Motion Sensors.
  • Read in and playback an MP3 file. As the music plays, analyze properties of the sound to dynamically change the brush (e.g., map brush size to current volume, analyze beats to control splatter, etc.)
  • When the device switches from landscape (the default) to portrait, change the layout of the app so that the paint interface takes up the full screen (or most of it) and the loaded image is shown behind it.
  • Create a particle emitter brushtype in a particle system that emits/spits out particles as your finger moves.
  • Support multi-touch so multiple fingers can simultaneously paint

Learning Goals and Outcomes

A brief summary of this assignment's core learning goals:
  • Strengthen understanding of input events and input event listeners
  • Provide UI programming context that requires creatively thinking about efficient drawing routines and coordinating between multiple views
  • Learn more about paint objects and how to use these to create sophisticated interactive behaviors


  • On Thurs, Nov 17, you must come to class with an initial interactive prototype of your Impressionist interface and a pre-brainstormed list of potential features. At a minimum, your prototype should include one working brush that takes the pixel color from the corresponding touch location in the ImageView and draws it appropriately in the ImpressionistView.

  • On Tues, Nov 22, you will submit your deliverables via Canvas.

Record a Video

Once you're done coding, take a ~3-to-5 minute video showing off the required features plus your custom feature. Clearly explain the interface using oral narration (to save time for this assignment, you do not need to add captions--unless you want to). You can record either the emulator (use a tablet emulator) or your app running on an actual Android tablet.


On Canvas, you will submit:
  • a link to your YouTube video,
  • a PDF of your favorite 1-3 pieces of artwork created with your app side-by-side with the original image,
  • a link to the sourcecode on github; the github root should contain a readme that describes how to run your program and lists references to online sources that you used to build your prototype.
  • and a zip file of the source code (and requisite libraries).


You can download the rubric here (a screenshot below, which you can click to enlarge, is included for your convenience):


Best of IA09: Impressionist

Like with IA08: Doodle, we would like to recognize a subset of submissions as the best in class. This time, we are doing something a bit different--we are honoring not just implementations of the impressionist project but the artwork created with them. For artwork, Matt and I will select the top 10-15 pieces and you will vote using a double blind process (the voters were anonymous and the artists were also anonymous). We will recognize the top 5-6 art pieces, the best brushes, and the best features in the Impressionist project. You can see the winners from the Spring 2016 semester here.

Best Artwork

6th Place - Jacqueline Chen

5th Place - Maria Furman

4th Place - Michael Ekstrom

3rd Place - Michael Delaney

2nd Place - Maria Furman

1st Place - Matthew Brady

Best Brushes
Peter Koutras
Pete implemented interesting X and Edge brushes which produce some very nice effects (e.g., warped glass effect) which was very unique (direct link):

Runners Up

Best Features
Victor De Souza
Victor implemented an interesting UI that allows the user to combine number brushes and effects in addition to implementing tilt functionality; the application video is definitely worth checking out (direct link):

Runners Up


  • For efficiency purposes, you will want to draw your brush to an offscreen bitmap and then in the ImpressionistView.onDraw method, you simply call canvas.drawBitmap(_offScreenBitmap, 0, 0, null); See skeleton code.
  • You can call "Bitmap imageViewBitmap = _imageView.getDrawingCache();" to get a copy of the ImageView as a bitmap
  • Once you have a reference to this bitmap, you can get the color for the pixel corresponding to the user's touch location in the ImpressionistView: int colorAtTouchPixelInImage = imageViewBitmap.getPixel(curPoint.x, curPoint.y); Note that this color contains R,G,B, and A values, so if you want direct control over alpha, you'll have to set this independently.

More Examples