This assignment is really more about making sure you are ready for those that follow than it is an actual assignment. It is dramatically easier than HW1.
Unlike other assignments
This assignment is due the second week of class but earlier = better.
You will submit, for each assignment:
A Makefile
with (at least) two targets: build
, which accepts no arguments, and run
, which accepts a single input file
argument.
Running
should execute your code on inputfilename.txt
.
Your code, including any necessary support libraries
A file named implemented.txt
that contains the names of the reference input files you believe your code handles, one per line
If all of your files are in the same directory, you can submit them as-is (but must submit all of them in one go; piecemeal uploads will not work).
If you need a specific directory structure, upload a .zip
or .tar
that contains those files. The logic for handling submissions is
Makefile
directly, we use thatMakefile
, we use thatMakefile
in that directory, we use thatThe input files your code will read are ASCII text files; after processing an input file, your code will produce one or more RGBA PNG files.
For your own testing sanity, you will also want to be able to turn sets of PNG files into an video file and to compare pixel differences between two PNG files. This writeup describes how to set those up, but we will not directly test these functionality, neither in this nor in subsequent homeworks.
Each run, your program will be given one command-line argument, which is the path to an input file.
Each input file will have a number of lines; each line will have a keyword first, followed by zero or more extra pieces of information separated by whitespace (some mix of ' '
and '\t'
). Lines should be read in order, first to last, because some lines refer to the lines above them.
Ignore blank lines and lines starting with anything other than a keyword you know. Always strip leading and trailing space from a line before parsing it.
In this assignment input files might look like
png 200 300 outfilename.png
xy 10 20
xyrgb 50 50 255 127 0
ignore this line since "ignore" is not a keyword you know
likewise ignore this line, which also starts with an unknown keyword
xyc 150 250 #ff00ee
You do not need to have error checking code. For example, if a png
keyword is not followed by exactly two positive integers and one string ending .png
, your code is welcome to break in any way you wish.
Each homework will define its own set of keywords. For HW0, these are:
Every file will begin with either png
or pngs
png
will be followed by two positive integers, width and height, and a filename. You should write a RGBA png image of the specified width and height (see [Image file creation]). You should write the file in the default directory. The initial color of every pixel in the image should be transparent black (0, 0, 0, 0).
You may assume the filename contains only non-whitespace ASCII characters and already has the appropriate .png
ending.
Every file will begin with either png
or pngs
pngs
will be followed by two positive integers, width and height; a base filename; and a number of frames to generate. Your should write frames distinct RGBA png images of the specified width and height in the default directory. Each should be named filename followed by a 3-digit number between 000 and frames with a .png
ending.
If an input file begins pngs 20 30 whatnot 12
your program will create twelve separate PNG files: whatnot000.png
, whatnot001.png
, … whatnot011.png
.
The initial color of every pixel in the image should be transparent black (0, 0, 0, 0).
You may assume the filename contains only non-whitespace ASCII characters.
frame
commands will only appear in files beginning pngs
, not files beginning png
. They specify that the subsequent commands should be applied to the given frame t, which will be an integer between 0 and the number of frames given on the pngs
line.
frame
lines will be given in increasing order: frame 3
will never appear after frame 4
. Some frames may be skipped, meaning that image should remain its initial color. If drawing commands appear before the first frame
, they apply to frame 0.
Fill the pixel noted by the x and y coordinate to be opaque white (255, 255, 255, 255). xy 0 0
should fill the top left corner pixel. If the image is 200 wide and 300 tall, then xy 199 299
would fill the bottom right pixel.
You may assume x and y are integers within the image bounds.
Fill the pixel noted by the x and y coordinate to have the specified color (r, g, b, 255).
You may assume r, g, and b are integers between 0 and 255, inclusive. See the discussion of xy
for comments on x and y.
Fill the pixel noted by the x and y coordinate to have the specified color. The color is given in a web-standard 3-byte hex code: #rrggbb
, where rr
is a two-digit hexidecimal value for red, gg
for green, and bb
for blue. Set the alpha to 255 (0xff)
You may assume hexColorString is always a seven-character string of the appropriate format. See the discussion of xy
for comments on x and y.
You should be able to pass both of the following. To get credit for them, make sure you put their names in your implemented.txt
file, like
hw0ex1.txt
hw0ex2.txt
This file’s contents are
png 5 8 hw0ex1.png
xy 0 1
xyrgb 1 2 127 255 255
xyc 2 3 #aaaaff
xy 3 4
xyrgb 4 5 200 120 3
xyrgb 3 3 0 0 0
xyrgb 2 4 0 0 0
and it should produces this image file: .
That’s so small it’s almost impossible to see, so let’s zoom in and put a striped background behind the image so you can tell the difference between transparent and white:
This file’s contents are
pngs 7 7 hw0ex2- 16
frame 0
xyrgb 6 3 0 0 0
frame 1
xyrgb 6 2 32 0 0
frame 2
xyrgb 5 1 64 0 0
frame 3
xyrgb 4 0 92 0 0
frame 4
xyrgb 3 0 128 0 0
frame 5
xyrgb 2 0 160 0 0
frame 6
xyrgb 1 1 192 0 0
frame 7
xyrgb 0 2 224 0 0
frame 8
xyrgb 0 3 255 0 0
frame 9
xyrgb 0 4 192 32 0
frame 10
xyrgb 1 5 128 64 0
frame 11
xyrgb 2 6 64 92 0
frame 12
xyrgb 3 6 0 128 0
frame 13
xyrgb 4 6 0 92 0
frame 14
xyrgb 5 5 0 64 0
frame 15
xyrgb 6 4 0 32 0
and it should produce 16 images (hw0ex2-000.png
through hw0ex2-015.png
) that create this animation (rendered at 16fps; if you don’t see animation please upgrade to a browser that supports APNG):
The submission site for this assignment (only) will run automated tests and add information about their outcomes to the submission file list. There may be a small delay before it is visible, as we queue each submission as it comes in. Feel free to re-submit until you get positive status results. Please refer questions to piazza or professor office hours.
You will create an 8-bit RGBA PNG image with a specified width and height. The way to do this will vary by language. You must use a technique that supports setting individual pixels to specific colors, not one with higher-level shape drawing functions (we’ll write those functions ourselves).
Some optional parts of homeworks 2 and 3 will include reading image files too. If you want to do those then, it might make sense to learn how now.
The following is example code to write PNGs taken from past semester’s student submissions. I don’t claim they are optimal, but they did work.
Students have used miniz.c and LodePNG.
An example using LodePNG:
#include "lodepng.h"
int main(int argc, char *argv[]){
/* ... */
unsigned char *image = calloc(width * height * 4, sizeof(unsigned char));
/* ... */
image[((y * width) + x)*4 + 0] = red;
image[((y * width) + x)*4 + 1] = green;
image[((y * width) + x)*4 + 2] = blue;
image[((y * width) + x)*4 + 3] = alpha;
/* ... */
lodepng_encode32_file(filename, image, width, height);
free(image);
}
An example using miniz
#include "miniz.h"
int main(int argc, char *argv[]){
/* ... */
unsigned char *image = calloc(width * height * 4, sizeof(unsigned char));
/* ... */
image[((y * width) + x)*4 + 0] = red;
image[((y * width) + x)*4 + 1] = green;
image[((y * width) + x)*4 + 2] = blue;
image[((y * width) + x)*4 + 3] = alpha;
/* ... */
size_t size;
void* data = tdefl_write_image_to_png_file_in_memory((void*) image, width, height, 4, &size);
FILE* out_file = fopen(filename, "wb");
fwrite(data, 1, size, out_file);
fclose(out_file);
free(data);
free(image);
}
All methods that work for C also work for C++, and most students used one of those. An OO interface is also available through CImg.
An example using CImg:
The testing server is Linux and runs mono, not Microsoft’s C# implementation. If you chose to use C#, you are responsible for ensuring it runs on Linux with mono.
The relevant class is System.Drawing.Bitmap
.
An example
The relevant package is image/image.dart
.
An example
import 'package:image/image.dart';
import 'dart:io';
void main(List<String> args) {
// ...
image = Image(width, height);
// ...
image.setPixelRgba(x, y, red, green, blue);
// ...
File(filename).writeBytesAsSync(encodePng(image));
}
The relevant package is image
.
An example
The relevant libraries are Color
from java.awt
, BufferedImage
and WritableRaster
from java.awt.image
and ImageIO
from javax.imageio
package. Do not use java.awt.Graphics
.
An example
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.awt.image.WriteableRaster;
import javax.imageio.ImageIO;
class ClassName {
public static void main(String[] args) {
// ...
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
WritableRaster raster = b.getRaster();
// ...
raster.SetPixel(x,y, new Color(red,green,blue,alpha));
// ...
ImageIO.write(image, "png", new File(filename));
}
}
The relevant library is pillow. To install, do pip install pillow
or pip3 install pillow
from the command line. Do not use the ImageDraw
module.
An example
The relevant library is std::io::RgbaImage
and sts::io:Rgba
.
An example
The relevant library is jimp
.
An example
In earlier semesters we’ve had students use D, Haskell, Kotlin, and Scala. In principle I am open to any language I can get to work on the testing server; just let me know what you’d like.
You will submit your code and a Makefile
. We will run your Makefile
on a Linux server. It is your responsibility to see that the Makefile
and your code work in a Linux environment. Following are minimal Makefiles you might use as a baseline. We recommend using make’s more advanced operations (separate .o
targets, pattern rules, variables, etc) if you understand them.
Note that Makefile
indentation must be in tabs, not spaces, but the syntax-highlighter I use changes tabs to spaces. You’ll need to change them back if you copy-paste these examples.
C Makefile
C++ Makefile
C# Makefile
Java Makefile
Java Makefile with packages
If your code is in a package (as many IDEs will make it), you’ll need a slightly more involved Makefile.
If the .java
files contain package some.name;
then they will be in some path path/prefix/some/name
. Put the Makefile
(and implemented.txt
) in path/prefix/
as follows:
SRC = $(wildcard some/name/*.java)
CLS = $(SRC:.java=.class)
.PHONEY: build, run
build: $(CLS)
javac $(SRC)
run: $(CLS)
java some.name.ClassWithMain $(file)
the SRC
uses the wildcard
function to find all Java files in that one package; if you use several packages, you will need to add additional wildcards there.
Some image viewers will let you scroll through a set of images quickly enough to see animation. But in case yours doesn’t…
Given a set of images created with pngs 30 50 someprefix 80
, you can create an animation from it using the extremely versatile tool ffmpeg. Some example uses include
# make an APNG, good for small transparent animated images
ffmpeg -r 16 -i someprefix%03d.png -f apng -plays 0 anim.png
## -r 16 16 fps; any number (even fractions) work
## -i someprefix%03.png gives the input images
## -f apng picks the output format
## -plays 0 repeat forever
## anim.png output filename
# make an mp4 using default compression
ffmpeg -r 30 -i someprefix%03d.png anim.mp4
# make an animated gif (an older inferior alternative to APNG)
ffmpeg -r 12 -i someprefix%03d.png anim.gif
Ffmpeg can do a lot more than this; see the docs if you are interested.
Think your output looks like the reference output? Maybe so, but like
is a fuzzy idea and sometimes we’ll hold you to a higher standard of similarity than your eye is trained to see.
Enter ImageMagick (or its less popular but faster clone, GraphicsMagick). ImageMagick is a collection of versatile command-line tools for manipulating images, including many forms of image comparison.
During grading, we use ImageMagick to create comparison images containing
student.png
ref.png
ae.png
rawdiff.png
diff.png
We create those images and stick them together into one large image to look at during grading using the following commands:
compare -fuzz 2% student.png ref.png ae.png
composite student.png ref.png -compose difference rawdiff.png
convert rawdiff.png -level 0%,8% diff.png
convert +append ref.png student.png ae.png rawdiff.png diff.png look_at_this.png
Note that some tasks permissive of some differences while others will be more strict. For example, consider this image:
It is similar to its reference image, but the outline is not the same (a few missing pixels along the left edge, touching in the middle) and there’s visible horizontal banding in the color error. If this input was meant to test shading and overlap, those would result in lost points. It it were meant to measure positioning and perspective, they’d not be a concern.