Table of Contents

Deadline: May 7th, 23:55

Introduction

For this assignment, we will work with images and implement some basic image manipulations. We will work with two types of images: greyscale and RGB.

Image representation

Internally, images are modeled as two-dimensional matrices of pixels; in Haskell we will model this by using lists of lists.

Tasks (total 1p)

For these two formats (greyscale and RGB) you are asked to implement some transformations. The next section lists common transformations (that should not depend on whether the pixel is a grayscale value or a RGB triplet); the section after that describes transformations that should have separate implementations, one for each format.

1. Common transformations (0.2p)

1.1. vertical flip

1.2. horizontal flip

1.3. 90 degree left-rotation

1.4. 90 degree right-rotation

1.5. 180 degree left-rotation

1.6. 180 degree right-rotation

2. Type-specific transformations (0.8p)

2.1. color inversion

2.2. cropping with a rectangle selection

2.3. brightness adjustment

2.4. masking with a bitmap mask

2.5. color swapping

2.6. conversion to greyscale

For all the tasks listed above you do not need to implement any sanity check on the inputs; you can safely assume all inputs are valid. For example, you can assume that all lists of lists you work with are valid two-dimensional matrices (no line is longer or shorter than the others); all color values are between 0 and 255; for cropping, the rectangle described will always fall within the bounds of the image; for masking, the mask will always be the same size as the image; etc.

You can download the starting code here. Unpack the archive and look in the folder skel/. Write the implementations in the files Common.hs, Greyscale.hs and Color.hs; the function types are already provided. You can ignore all the other haskell source files in that folder, they are only needed if you intend to test it on real Netpbm images.

Image processing is a vast, complex subject in itself; often, there are multiple ways of achieving an effect, distinguished by output quality, ease of implementation, resource usage etc. Our focus here is simply on how to program in a functional style, so we don't really aim for performance and smooth results.

For example, the scaling algorithm presented (a form of nearest-neighbor interpolation) is easy to write, but its results are poor. You can see here a quality comparison of various algorithms.

Helper code

For very basic testing, you can define your own test-cases. However, to give you a big-picture view and some satisfying results, we offer you a testing framework for Netpbm ASCII-format images.

Netpbm is a simplistic pixel-map image format, capable of modelling both greyscale and RGB pictures.

A Netpbm image file has the following structure:

The code provided reads and parses a Netpbm image, then appropriately calls the functions you implemented to perform a transformation, creating an output file which you can then inspect, either as values in a text editor, or as an image in an image viewer.

We provide you with a few Netpbm samples, but you can create your own images. Most image editors (e.g. Photoshop, GIMP) should be able to convert an arbitrary image to a Netpbm format; when asked about “data formatting” (or similar terms), select “ASCII”, not “raw”.

A warning: for various reasons the resulting code is quite inefficient, so it will take a few seconds to process even small images. The bigger the image, the longer the processing time.

Usage

To run the provided helper code and test your functionality, you first need to select which function you want to test out. For that, you need to edit one or two lines in the file Main.hs.

After having edited Main.hs you can run it; depending on the number of arguments, it will choose an appropriate type of transformation (single/multiple image); it also correctly chooses between greyscale/RGB functions based on the actual filetype. To run the file you need the runhaskell binary (or runghc; both should come with the haskell platform), then run it from a shell:

# Runs the single-image transformation set on line 13 on the image in file "./input.ppm"; the result is written to "./out.ppm".
runhaskell Main.sh ./input.ppm ./out.ppm
# Runs the mask transformation set on line 16 on the image in file "./input.ppm" with the mask in "./mask.pbm"; the result is written to "./out.ppm".
runhaskell Main.hs ./image.ppm ./mask.pbm ./out.ppm

The folder res/ contains several greyscale and RGB images, as well as two masks. The masks are also in a Netpbm format; you can view any of these images with a regular image-viewer.

Scoring

The assignment is worth 1 point; 0.2p for the common transformations; 0.4p for greyscale and 0.4p for RGB.

Submission

For submission you should create a zip archive of the three files you modified: Common.hs, Greyscale.hs and Color.hs and a README. The README should contain a succinct high-level presentation of your work. The archive name should be LASTNAME_Firstname_FP_A1.zip (if you have multiple firstnames, separate them by an underline “_”). Mail it to mihai.dumitru2201@upb.ro.