CS 324E Assignment 2


Assignment 2: Image Manipulation



Project Description

In this assignment, you will explore per-pixel manipulation in order to create a series of commonly-used filters. You will also implement basic input-handling and image buffering. Your file will open an image within the MonoGame window upon clicking "Run." Filters will be applied to this image when the user clicks the number keys. Each filter will be applied individually. That is, filters should not stack, and you will include a key that returns the image to its original state. Extra credit is possible for combining filters in unique ways.

Basic Requirements

You will implement functionality for:
Image loading
Keyboard input-handling
A kernel/convolution matrix

You will then use those features to implement the following filters:
Grayscale
Tint
Gaussian blur approximation (3x3)
Gaussing blur approximation (5x5)
Edge detection
Image loading: Provide functionality for loading an image of your choice. Even though you only need to support this one image, this code should be flexible and load images of multiple sizes, as the MonoGame window itself should map to the size of any given image.

Keyboard input-handling: The user should be able to input key commands for 1-5 as well as 0. The functionality of each button is described below with the filter it applies. If you want to make additional filters, include additional key inputs and document all extra work within your assignment doc, so the graders know what to expect.

A kernel/convolution matrix: This convolution matrix will be applied to all pixels when filters requiring neighborhood information are called. Example code is included in the slides, but there are a couple more caveats:

  1. Your code should handle the edge pixels in some reasonable way -- a black border is not acceptable. Potential solutions are included in the slides.
  2. Your code should account for the possibility of the convolution outputting negative values or values that are above the 255 "limit" within each color channel. Failing to do this will lead to wrong (and sometimes outright bizarre!) image manipulations.

Grayscale: This filter will convert a color image to a grayscale image when the user presses "1". One way to do this is by averaging across all color channels on a per-pixel basis then assigning that value across all three color channels. This roughly preserves the value even if hue and saturation are discarded.

Tint: This filter will apply the tint of your choice to the image when the user presses "2". You can calculate tint in a variety of ways, but your report should specify the equation you're using to apply tint and maybe a short explanation of why you implemented tint the way you did.

Gaussian blur approximation (3x3): This filter will approximate a 3x3 Gaussian Blur when the user presses "3". Since blurring requires neighborhood knowledge of pixels, it will rely on your kernel, or convolution matrix, to extract and manipulate the necessary pixel information. You will need to buffer the updated image in order to prevent your changes to the image from influencing its neightbors. Example of a 3x3 approximation below (from Wikipedia).

Gaussian blur approximation (5x5): This filter will approximate a 5x5 Gaussian Blur when the user presses "4". Since blurring requires neighborhood knowledge of pixels, it will rely on your kernel, or convolution matrix, to extract and manipulate the necessary pixel information. You will need to buffer the updated image in order to prevent your changes to the image from influencing its neightbors. Example of a 5x5 approximation below (from Wikipedia).

Note to receive full credit, this should use the same function as the other Gaussian blur approximation, so please make sure you code is flexible enough to hand kernels of different sizes.

Edge detection: This filter will perform edge detection using the Sobel operators when the user presses "5". This filter also requires neighborhood knowledge of pixels, and therefore will also use your kernel. Again, you will need to buffer the updated image to prevent any changes in pixels from influencing their neighbors.

Remember from the class that there are two Sobel operators: horizontal and vertical. To combine these operators, you will determine each pixel's updated value in both the vertical and horizontal directions. You can then take the magnitude (i.e. distance) and assign that value to the final pixel output. To take the magnitude take the square root of the added squared convolution values.

No Filter When the user presses "0" the displayed image should return to its original form. You should consider always displaying the same "working copy" Texture2D but write back to it from the "clean" copy when this key is pressed rather than displaying a different image.

Extra Credit

All assignments have possible extensions that you might consider adding to your scene for extra credit. Note that if the submission is well beyond the scope of the assignment, we will consider giving extra credit even if the features implemented are not ones suggested below.

Implementing Contrast (3 points)

Implement a "High Contrast" filter which is based on HSV's Value (or Brightness) rather than RGB information. To do this correctly, you will need to implement some functions that correctly convert RGB to HSV (and HSV to RGB). Information on the math to do this is here. In order to create this filter, you will need to convert each pixel's RGB color value to HSV, find a threshold value to decide whether to make the pixel brighter or darker, then convert the data back to RGB to save it back into the image.

What to turn in

You will submit the following in the folder youreid_assignment2:

  1. A MonoGame project named youreid_assignment2 that loads an image upon Running. This project should have keyboard functionality for all filters listed within the project description.
  2. A sample image that will automatically load and display all filter functionality during the testing.
  3. A README text file that tells us the exact steps necessary to run your code.
  4. A project report, A2Report, that tells us what functionalities you've implemented, how you've structured your code, and other interesting features or extra credit within the program, software it relies on that you didn't write, and issues you encountered if there are unresolved problems. This file can be .txt or .pdf.

Zip this folder and submit via Canvas.


Last modified: 09/23/25 by Sarah Abraham theshark@cs.utexas.edu