In this assignment, you will develop a simple program for loading and displaying an image formatted in the PPM P6 format

Objectives

This assignment is designed to teach you the basics of working with:

Part 1: Setting up your repository

If you haven’t already, you need to create an account on GitHub. You should also enable academic access if you haven’t already by “Requesting a discount” for your “Individual Account”.

Next, please create a repository for your assignment. Please follow this link to create your repository.

If you aren’t comfortable yet with git, please try out some tutorials online! try.github.io is great, as is http://rogerdudler.github.io/git-guide/, https://www.atlassian.com/git/tutorials, and https://git-scm.com/docs/gittutorial.

We will use git the entire semester, and this assignment is meant to get you started. Feel free to use a GUI client for git, but you may also want to consider learning how to use it from a terminal. Since I will managing the repositories, you likely will only need to learn four commands:

git clone
git add
git commit
git push

Part 2: Building your first program

After cloning your repository, note that there is some skeleton code in it. This provides a very basic program that creates an SDL window.

When compiling programs from the commandline with CMake, typically, one does what is called an “out-of-source” build. This helps keep build files separated from source files. The easiest way to do this is to create a separate build directory, change into it, and then run cmake pointing to the CMakeLists.txt file in the source directory.

$ mkdir build
$ cd build
$ cmake ..
$ make

CMake builds are two-step. First, one uses CMake to generate platform specific build files, and then one uses the build system of your platform (e.g. Makefiles on Unix).

Alternatively, you can use CMake in certain IDEs of your choice (such as Visual Studio, CLion, etc.). These IDEs typically will create a project for you directly from information specified in the CMakeLists.txt file.

Our CMakeLists.txt for this assignment looks as follows:

cmake_minimum_required(VERSION 2.8.11)
project(basic_sdl)

set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
find_package(SDL2)

set(source_files
  main.cpp 
)

include_directories (${SDL2_INCLUDE_DIR})
add_executable (${PROJECT_NAME} ${source_files})
target_link_libraries(${PROJECT_NAME} ${SDL2_LIBRARY})

The important commands are:

  • project(), which specifies the variable PROJECT_NAME
  • find_package(), which specifies the dependencies for the project that can be searched for on the system (in this case, we will search for the SDL2 library). find_package(X) also creates a number of variables for us to use for a given library X, including X_INCLUDE_DIR and X_LIBRARY. In this case, we use a custom script to find SDL2 (which is stored in the cmake/ subdirectory)
  • A standard set() command is used to create a variable that includes all .cpp files. There are many ways to do similar things in CMake, this example forces you to have to explicitly list all files (in this case, there is only one, main.cpp).
  • The final three standard lines are used for building almost any project:
    1. include_directories() lists the include paths that should be used for searching for header files. This is very similar to what would follow g++ -I. In this case, we are including the headers for SDL that find_package() automatically found for us.
    2. add_executable() specifies a build target that should be an executable (as opposed to a library). In this case, we are naming the executable ${PROJECT_NAME} and we are telling CMake that the source files we named as ${source_files} with the set() command should be compiled for this executable.
    3. target_link_libraries() specifies the linking dependencies for the target. In this case, we use the same name ${PROJECT_NAME} and tell it to link against the libraries we found from find_package(). This is very similar to what g++ -l does, except ${SDL_LIBRARIES} in this case specifies all of the libraries to link against.

After compiling with CMake and make, you should be able to execute a binary called basic_sdl which should display a simple window with an image.

Part 3: Your program

To start with, examine main.cpp. Note how the code is commented and be sure to follow a similar pattern as you write your own programs. While you do not need to use doxygen-style commenting, you must use some style and maintain this consistently throughout your programs.

int main() is structured in a common paradigm that we will use:

int main(int argc, char** argv) {
  //initialize 

  while(!quit) {
    //poll for input from mouse/keyboard
    //draw to screen
  }

  //cleanup
}

Modify the provided source code to read and then display a PPM image. To do so, you will create a C++ class that can be used for encapsulating C++ images. You can assume all PPM images will be provided in the P6 format. PPM images have a simple format, that you must parse:

P6  
# COMMENTS always start with a pound sign, skip these lines  
[WIDTH] [HEIGHT]  
[MAX VALUE] 
[RAW DATA]

For this assignment, you need only support PPM files with a [MAX VALUE] of 255. All portions of the above header are in ASCII except for the raw data, which is encoded directly as binary data.

Internally, your class may use whatever raw data type you prefer to store the dataset that you read from file, but it must provide functionality to load an image from a file and store an array of pixel data. It must also provide access to pass this data to the SDL Texture that you will draw.

It is also recommended that you provide functionality to encapsulate a color that your image will store, potentially as a separate class. In my example, I use a simple unsigned char* data to store the data, both linearizing the two dimensional array of pixels into a one dimensional array as well as interlacing the color channels for each pixel.

Your PPM image class should also provide functionality to access the width and height of the image, as well as to access individual pixel values. These will need to be exposed to map the image data into an SDL_Texture.

The expectation is that we will use this class in numerous future assignments, potentially with modifications. Design carefully with this in mind!

After creating your class, modify the initialization portion of the code to create an instance of it and to load the image from a filename specified at run time (modifying the commandline parameters of the code). You should resize the window to accommodate the width/height of the image you load.

Test your program with the images found in the data/ subdirectory of the default repo. You may also want to test with other images you find – you should be able to convert them to PPM format using a variety of tools, but be careful as some converters may produce images where the [MAX VALUE] may not always be 255 or the format may not be P6.

Part 4: Survey

For the written portion of the assignment, create a second plain-text ASCII file, named survey.txt, and also place it in the top-level directory of your git-repository. Commit and push this file after filling out the following survey, with answers formatted roughly like this:

1. I loved video games and want to know how they work.

2. Cool ways to make pictures with computers!  

3. C++ (10), Python (5), LOLCODE (2)

...

You are not required to answer any of the questions if you don’t want to, but non-submission does not count! Please write “no answer” for any question that you choose not to answer.

I am going to use the answers to calibrate the remainder of the course, so this is an opportunity for you to influence where the course goes. There are no right or wrong answers in this questionnaire. All I ask is you answer honestly, without trying to figure out what I might want to read. The more you write, the more I’ll know about your expectations and what you are interested in.

Survey Questions

  1. Why are you taking this course?

  2. What do you think you’ll learn in this course?

  3. List the three programming languages you are most comfortable with, with how many years of experience you have with each

  4. What experience do you have with C++? Have you used the STL before?

  5. Do you know what operators are in C++ and how to overload them? If so, in what situations have you found these useful?

  6. What’s the best computer graphics you’ve ever seen? Why do you like it?

  7. What’s the worst computer graphics you’ve ever seen? Why do you not like it?

  8. Tell me about something cool you learned recently. If you were meeting with a friend, what would you chat about? Possible answers: books, movies, TV shows, blogs, podcasts, etc. It does not have to be about computer graphics.

Submission

You should use git to submit all source code files and a working CMakeLists.txt. Do not submit any build files, binary files, or otherwise except for specific test data. The expectation is that your code will be graded by cloning your repo and then executing:

$ mkdir build
$ cd build
$ cmake ..
$ make

Your code must compile on the CS lab machines, in particular we will test on cambridge. Code that does not compile in this way will be given an automatic zero. You will be given one “warning” for the first instance during the semester that it does not compile, but after a zero will occur If you are working on a different environment, please log into these machines and test your code before submitting.

Make sure that this build process produces an executable named prog01. You will need to edit CMakeLists.txt accordingly.

Please provide a README.md file that provides a text description of how to run your program and any command line parameters that you used. Also document any idiosyncrasies, behaviors, or bugs of note that you want us to be aware of.

To summarize, my expectation is that your repo will contain:

  1. A README.md file
  2. A survey.txt file
  3. A CMakeLists.txt file
  4. All .cpp and .h files that you authored.
  5. (Optionally) any other test images that you want.

Testing on the CS Machines

All students in the class have been provided accounts to test their code. All code should be able to compile on cambridge.cs.arizona.edu.

To test, you should be able to ssh into the cambridge, git clone your repo, and then try out compiling it. However, graphical programs will not be able to display over SSH.

To get around this limitation, we will use VNC to test our code. VNC is installed on cambridge and should work with a remote login. This requires a few steps to execute correctly:

VNC Step 1: Connecting Remotely

First, you’ll need to configure a remote connection to cambridge. This is enabled by using SSH with port forwarding. On Mac OSX and Linux, you can do this from the commandline using the -L command. You will have to specify a specific port to forward, which should be a unique number larger than 5900. In this example, I will use port 5917 and my username josh:

josh@mylaptop$ ssh -L 5917:localhost:5917 josh@cambridge.cs.arizona.edu

The above line logs into cambridge remotely and it forwards port 5917 on cambridge to port 5917 on my machine (localhost:5917).

More info on port forwarding is available at the “Secure your VNC Connection” step of this tutorial. On windows, you can do the same thing through a free ssh client, PuTTY.

VNC Step 2: Configure your vncserver

Once you log into cambridge, we can set up your VNC server. To do this, you first need to configure what happens when you run vnc. No packages need to be installed, but you will need to edit ~/.vnc/xstartup. I found that the xstartup file listed here worked well on cambridge:

This will produce a gnome desktop (or what looked like one for me).

VNC Step 3: Initialize your vncserver

You should be able to start the server with a basic command:

josh@cambridge$ vncserver :17

In the above, :17 refers to the virtual port for the VNC server. This maps to port 5900+number, so in this case, it maps to port 5917, which is the same port we forwarded above.

The very first time you run vncserver, you’ll have to create a VNC connection password (this is stored in .vnc/passwd). You’ll need this when you connect, and I would use something different than your account password.

In addition, you will likely want to explicitly set the color depth for your VNC server. This requires one additional option that you should do instead of the above:

josh@cambridge$ vncserver -depth 24 :17

Which sets the color depth to 24 bit color.

VNC Step 4: Connect to your vncserver

Finally, you need to connect. On OSX, I did this by downloading a VNC viewer. Specifically, I used TurboVNC

The .dmg installs in /opt/TurboVNC. If you’ve done steps (1)-(3) correctly, you should be able to connect immediately with:

josh@mylaptop$ /opt/TurboVNC/bin/vncviewer localhost:5917

At which point, you’ll use your VNC connection password to authenticate and then you should be good to go. You may also want to try out RealVNC Viewer instead, which should work on all operating systems. The instructions for how to set up that connection are in the “Connect to VNC from your Desktop” portion of this tutorial.

VNC Step 5: Close your vncserver.

Finally, and most importantly, when your session is done, BE SURE TO KILL THE VNCSERVER BEFORE LOGGING OUT OF CAMBRIDGE. Luckily, this is easy to do:

josh@cambridge$ vncserver -kill :17

Grading

Deductions

Reason Value
Program does not compile. (First instance across all assignments will receive a warning with a chance to resubmit, but subsequence non-compiling assignments will receive the full penalty) -100
Program crashes due to bugs -10 each bug at grader's discretion to fix


Point Breakdown of Features

Requirement Value
Consistent modular coding style 10
External documentation (README.md), Providing a working CMakeLists.txt 5
Class documentation, Internal documentation (Block and Inline). Wherever applicable / for all files 15
Expected output / behavior based on the assignment specification, including

Correctly parsing P6 PPM format and storing it internally.20
Displaying the PPM image in an SDL_Texture15
Properly resizing the window on load and tracking the image dimensions.10
Correctly handling command line parameters for reading the filename.5

50
Survey Submission (Written Questions) 20
Total 100