Create a toolbox of image transformations and filters, with a programming emphasis on C pointers.
Start from the ppm_example.c code on the syllabus page, or from your modified version from class exercises. You should add all your new code and functions to this file, because you will not be allowed to submit any additional files. This restriction simplifies the submission process.
You code must be written in pure C—no C++ or Qt is allowed. You are welcome to use C99 and C11 constructs, especially declaring variables anywhere in the function body and in for loop initializers.
Maintain a log of all help you receive and resources you use. Make sure the date and time, the names of everyone you work with or get help from, including in office hours, and every URL you use, except as noted in the collaboration policy. Also briefly log your question, bug or the topic you were looking up/discussing. Ideally, you should also the answer to your question or solution to your bug. This will help you learn and provide a useful reference for future assignments and exams. This also helps us know if there is a topic that people are finding difficult. You will submit this as a plain text file.
You must adhere to the guidelines below. In addition, you must implement all the features from section 4 and a selection of features from section 5.
where -option1... are options that specify the various transformations and features you have implemented. These features should be applied one after another to <input.ppm>, and the result should be written to <output.ppm>.ppm_example <input.ppm> -option1 -option2 ... <output.ppm>
Your program must implement the all the following features. You will probably want to write a separate function for each of these, that main will call if the correct argument is supplied. It is up to you what arguments those functions should take, and what (if anything) they should return.
-grayscale
: convert the image to grayscale
using the formula Y == .299R + .587G +
.114B
.-flip
: Mirror the image left-to-right. You
should not need to allocate or free any memory to perform this
operation.-flop
: Mirror the image top-to-bottom. You
should not need to allocate or free any memory to perform this
operation.-transpose
: Transpose the image like a matrix,
i.e. flip it along the diagonal axis from top-left to
bottom-right. You will probably need to malloc
additional memory to do this.-boxblur n
: Perform
a box
blur of radius n. A box blur slides a square
with sides of length 2n + 1 across the
image, and replaces the center pixel with the average of all
pixels in the box. You will need to store the blurred pixels
in a new image so they don't interfere with blurring
subsequent pixels. Round the resulting value to the nearest
integer, and clamp to the range 0..255. Replace any pixels
that are within n pixels of the image boundary with
bright green (0, 255, 0). (In practice, there are
different ways of handling pixels that are too close to the
boundary to every be at the center of the square. Replacing
them with bright green makes it easy for you and the TAs to
see that you are handling them as a special case.)-median n
: Perform
a median
filter of radius n. This works like the box blur,
but it replaces the center pixel with the median pixel value
rather than the average. Replace pixels too close to the
boundary with bright green.-gaussian n s
: Perform a
Gaussian
convolution of radius n and standard
deviation s. This is slightly more involved than a
box blur, but is a more typical blurring function. It is also
a canonical example of a convolution filter.
Implement at least two of the following transformations, which are listed in roughly increasing order of difficulty. If you implement more than two, or additional transformations of your own, you will receive extra credit. List all transformations you implemented in your readme file, including the appropriate command-line options for any that are not listed below. (Your own transformations will receive extra credit based on the complexity of pointer manipulation and memory management as well as the complexity of the transformation.)
-sobel
: Convert the image to grayscale,
perform Sobel
edge detection and output the gradient magnitude
image G.-scale factor
and -size width
height
: Resize the image to factor times its
original dimensions (e.g. -scale 0.5 scales
the image to half its original width and height), or
two width pixels by height pixels. You
must implement both command-line options, but they should
rely on the same underlying code to resize the image. You
will need to use a reverse mapping to implement this: for
each pixel in the resized image, compute the
corresponding coordinates in the original image (do
not round them!). Then
use bilinear
interpolation to compute the color based on the nearest
pixels in the orignal image. Take especial care of the
border pixels: if you handle them correctly, the corner
pixels of the resized image should match the corner pixels
of the original image exactly.-rotate angle
: Rotate the image
by angle degrees counter-clockwise. The
output image should be large enough to contain the entire
rotated image (round the new width and height to the nearest
integer), and pixels in the rotated image that fall outside
the original image boundary should be colored bright green.
(Hint: rotate each of the original images coordinates to
figure out the minimum and maximum x- and y-values in the
rotated image.) You will need to use a reverse mapping and
bilinear interpolation just like in image resizing. You will
also find it helpful to construct
a rotation
matrix to compute rotate coordinates. Finally, it will
probably be easiest to set (0, 0) to be the center of each
image, rather than the top-left. You can do this by
subtracting the midpoint of an image from the pixel's row and
column.-whirl angle
: Whirl an image by angle
degrees counter-clockwise. You will
implement Gimp's
whirl algorithm, with a radius of 1 and a pinch of 0. A
whirl is similar to a rotation, except that the the amount of
rotation at a pixel is proportional to the square of its
distance along a line from the image's center to the image's
edge. The center pixel rotates by angle degrees,
while pixels too near the corners do not rotate at all.
Concretely, if you resize the image to be square, pixels
outside the circle inscribed in the square do not rotate. As
a result, the output image has the same dimesnions as the
input image. (Don't worry if the description makes no sense;
this feature is really an exercise in understanding the
uncommented gimp code in the link.)Download and complete this readme_filters.txt template in a text editor (NOT Windows Notepad, Mac TextEdit, or Word because they will mangle the file). Submit the readme, your helplog (also as a plain text file), and your code through the Dashboard. You may submit as often as you like, but only your last submission will be graded. You only need to resubmit files that have changed since your previous submission.