C++ pic

profiletroook61
pa2.zip

PA#2/ PA#2.docx

This assignment is a continuation of lab 4. In this homework, you will create a program that will add simple effects to a PPM image.

Prerequisites

Before beginning this assignment, you will need some sort of imaging software that can open PPM- based images. I recommend Ifranview for Windows as it's free and lightweight.

PPM Image Format

The PPM image format is encoded in human-readable ASCII text. It might be helpful to read over the formal PPM specification document. A PPM document has two pieces: the header and the body. The header is always the top three uncommented lines in the file:

The first line specifies the type of image that is contained within the file. We will always use the "P3" specification. The second line specifies the number of columns and rows present in the image. In this example, we have a 4x4 image. The final number indicates the maximum value for each red, green, and blue element in the picture. Having a max value of 255 is quite common and is the value that we will always use. Below the header is the body of the PPM file. Each pixel has a red, green, and blue value. For example, the content of our 4x4 image might be:

P3 44 255

000 10000 000 255 0255 000 0255175 000 000 000 000 015175 000 255 0 255 0 0 0 0 0 0 255 255 255

With these values, the pixel in the first column and row has a RGB value of (0,0,0) and the last column in the first row has an RGB value of (255,0,255). A blown-up image containing these values would look like:

Task

Your task is to write a program that will perform the following basic image manipulations on a user specified image. Below is a reference value and the images that result from the image processing.

Original Image

Remove Red

Will remove all red (i.e. set red to 0) pixels in the image

Remove Green

Will remove all green pixels in the image

Remove Blue

Will remove all blue pixels in the image

Negate Red

Will negate all red pixels in an image. To negate a color, simply subtract the current pixel's red color value from 255.

Negate Green

Will negate all green pixels in an image.

Negate Blue

Will negate all blue pixels in an image.

Add Random Noise

Will add random noise to the image by randomly selecting a value ranging from -10 to 10 and adding that value to the pixel's current value. If the addition causes the pixel value to be less than 0, then set to 0. Likewise, if the addition causes the pixel's value to be greater than 255, just set the pixel's value to 255. For example, we randomly generate the number -7. Next, we add -7 to each of the current pixel's red, green, and blue values.

High Contrast

Examine each color in a pixel. If the color is greater than half of 255, then max the color out (i.e. set to 255). Otherwise, set the value to 0. For example, performing a high contrast operation on a pixel whose RGB values are 170, 50, 100 would result in an RGB value of 255, 0, 0.

Grayscale

Converts the image to grayscale by setting the value of each color in a given pixel to the average of all three values. For example, if a pixel's RGB was 177, 15, 39, the resulting RGB value would be 77, 77, 77.

BONUS - Flip Horizontal

Flips the image along the horizontal axis.

BONUS - Flip Vertical

Flips the image along the vertical axis.

Chaining Effects Together

Note that manipulations can be chained together. Below is the image generated from performing a negate red, negate green, and negate blue operation.

UML Diagram

In order to complete this assignment, you must develop and implement the following classes:

Note that it might help to zoom in on the UML diagram. We start with the Point class that we developed in Lab 4. In the center, we have the SimpleImageEffect interface that defines a single pure virtual function called processImage. Each effect described in the previous section derives itself from SimpleImageEffect, implementing the processImage method in such a way to fulfill its role (e.g. NegateRedEffect will negate all red pixels in the image). Note that while a factory-type class isn't defined, it may be useful for you to write one.

Also note the white diamond going from SimpleImageEffect to Point. This is called "aggregation" and is another form of a "has-a" relationship. The main difference between aggregation and composition (black diamond) has to deal with the lifespan of an object. A black diamond means that the object goes out of scope at the same time as the owner class. A white diamond means that the object stays alive even when the owner class goes out of scope. If you think about the lifespan of a Point, it is easy to see that a given Point will exist for a longer period than the SimpleImageEffect. This makes sense as the Point still needs to be written to the output file!

Getting Your Code to Work with HackerRank

In order to make your code work both inside and outside of HackerRank, the first thing you'll need to do is to determine whether or not the input is coming from cin or from a file. HackerRank expects

everything to come in via cin while a normal program would expect data to come in via a file object. As such, your program should start off by asking the user where data will be read (see screenshot below).

Sample Output

Note that the program allows for unlimited effects to be added to a given image. Also note that some of these effects might take a while for your computer to process!

Possible Strategy for Getting Started

If you're feeling overwhelmed, try implementing one of the more simplistic image effects (e.g. remove red) inside of main. Once you get that working on a PPM file, put the necessary code into its own class and .h file.

 Alternatively, do the image effects last. Instead, work on file processing. Spend time making sure that you can open and write PPM files.

 Also, use Lab 4 as a template. Most of the ideas we covered in lab can be directly applied to the solving of this assignment. Header Comment, and Formatting

1. Be sure to modify the file header comment at the top of your script to indicate your name, student ID, completion time, and the names of any individuals that you collaborated with on the assignment.

2. Remember to follow the basic coding style guide. A basic list of rules is included with this document.

Reflection Essay

In addition to the programming tasks listed above, your submission must include an essay that reflects on your experiences with this homework. This essay must be at least 350 words long. Note that the focus of this paper should be on your reflection, not on structure (e.g. introductory paragraph, conclusion, etc.). The essay is graded on content (i.e. it shows deep though) rather than syntax (e.g. spelling) and structure. Below are some prompts that can be used to get you thinking. Feel free to use these or to make up your own.

 Describe a particular struggle that you overcame when working on this programming assignment.

 Conversely, describe an issue with your assignment that you were unable to resolve.

 Provide advice to a future student on how he or she might succeed on this assignment.

 Describe the most fun aspect of the assignment.

 Describe the most challenging aspect of the assignment.

 Describe the most difficult aspect of the assignment to understand.

 Provide any suggestions for improving the assignment in the future. Deliverables You must upload your program and reflection as a ZIP file through Canvas and your code through HackerRank no later than midnight on Thursday, March 2, 2017. Remember that your submission must either contain a CodeBlocks, Netbeans, or Visual Studio project file! Grading Criteria Your assignment will be judged by the following criteria: Reflection essay (5pts)

Your reflection meets the minimum requirements as specified earlier in this document.

Style (20pts)

Your project contains good structure and implements the required classes. Your program intelligently uses classes when appropriate and generally conforms to good OOP design (i.e. everything isn't slapped into main).

HackerRank Test Cases (75pts)

Your program successfully passes all test cases

EXTRA CREDIT (5pts)

[1/2 credit] You add either the ability to flip the image horizontally or vertically. [full credit] You add the ability to flip the image both horizontally and vertically.

Grade Distribution

Your final grade for the assignment will be determined based on the number of points earned. Note that failing to use good design (e.g. objects, appropriate data structures), regardless of score earned, may result in a lower overall grade.

90 80

70

70 55

40

50 25

25 15

Score Points Required

100

85

80

60

40

20

image4.jpeg

image5.jpeg

image6.jpeg

image7.jpeg

image8.jpeg

image4.png

image9.jpeg

image5.png

image6.png

image10.jpeg

image7.png

image8.png

image9.png

image10.png

image11.png

image12.png

image13.png

image14.png

image15.png

image16.png

image17.png

image18.png

image19.png

image1.png

image2.png

image3.png

image1.jpeg

image2.jpeg

image3.jpeg

__MACOSX/PA#2/._ PA#2.docx

PA#2/.DS_Store

__MACOSX/PA#2/._.DS_Store

PA#2/bunny.ppm

__MACOSX/PA#2/._bunny.ppm

PA#2/LAB4.docx

Lab #4

This lab is intended to get you started on PA #2. To this end, Lab 3 introduces you to the portable pixel map (PPM) image format and basic image manipulation.

Goals

In completing this lab, you will have been exposed to the following:

 Test-driven development

 PPM image format

 File processing

 Object-oriented design

 Inheritance

 Polymorphism Prerequisites Before beginning this lab, you will need some sort of imaging software that can open PPM-based images. I would recommend Ifranview for Windows as it's free and lightweight. PPM Image Format The PPM image format is encoded in human-readable ASCII text. It might be helpful to read over the formal PPM specification document. A PPM document has two pieces: the header and the body. The header is always the top three uncommented lines in the file: The first line specifies the type of image that is contained within the file. We will always use the "P3" specification. The second line specifies the number of columns and rows present in the image. In this example, we have a 4x4 image. The final number indicates the maximum value for each red, green, and blue element in the picture. Having a max value of 255 is quite common and is the value that we will always use. Below the header is the body of the PPM file. Each pixel has a red, green, and blue value. For example, the content of our 4x4 image might be:

P3 44 255

000 10000 000 255 0255 000 0255175 000 000 000 000 015175 000 255 0 255 0 0 0 0 0 0 255 255 255

With these values, the pixel in the first column and row has a RGB value of (0,0,0) and the last column in the first row has an RGB value of (255,0,255). A blown-up image containing these values would look like:

Task

Your task for this lab is to write an image effect that removes all green from a given image. Note that this can be accomplished by simply setting the green value in each RGP triplet to zero.

UML Diagram

Below is a UML diagram for the lab. While it is most certainly overkill for this lab task, it sets you up nicely to complete the homework assignment.

Note that we use the Point class to represent a given RGB triplet in the PPM file. We create the SimpleImageEffect interface to represent a given image effect (the HW has many more) with RemoveGreenEffect being a concrete implementation of a given image effect. Note that the processImage function should process the PPM one line at a time.

Expected Output (for Hacker Rank)

Hacker Rank has its own simplified tests for your program to pass. These test cases can be found by following this link.

Sample Output (for testing)

Below is a screenshot of my lab along with the input and output files:

Note that the "parsing" stage may take a while (several seconds).

Bunny.ppm

This is the original bunny file:

Bunny_out.ppm

And the image with green removed:

image1.jpeg

image2.jpeg

image1.png

image2.png

image3.png

image4.png

image5.png

image6.png

__MACOSX/PA#2/._LAB4.docx

PA#2/main/main.cpp

/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ /* * File: main.cpp * Author: asc564 * * Created on February 13, 2017, 5:12 PM */ #include <cstdlib> #include <string> #include <vector> #include <fstream> #include <sstream> #include <iostream> #include "Point.h" #include "RemoveGreenEffect.h" using namespace std; //converts a string-based line into a vector of INTs vector<Point> parse_line(string line) { istringstream scanner{line}; vector<Point> result{}; int red; int green; int blue; //read all ints present on the line while(scanner.good()) { scanner >> red; scanner >> green; scanner >> blue; Point p{ red, green, blue }; result.push_back(p); } return result; } /* * */ int main(int argc, char** argv) { string line = ""; //throw all lines into a vector of strings vector<string> lines_in_file{}; SimpleImageEffect *effect = nullptr; //TODO: use menu to alter effect. For now, hard code to green effect = new RemoveGreenEffect{}; getline(cin, line); while(line.length() > 0) { lines_in_file.push_back(line); getline(cin, line); } //lines_in_file should contain all lines in our PPM //[0] - PPM spec //[1] - dimension //[2] - max RGB value //[3]+ - pixels //output back to cout cout << lines_in_file[0] << endl; cout << lines_in_file[1] << endl; cout << lines_in_file[2] << endl; //output back the pixels for(int i = 3; i < lines_in_file.size(); i++) { //convert text into a series of numbers vector<Point> points = parse_line(lines_in_file[i]); //apply image effect effect->processImage(points); //output all values to the screen for(auto p : points) { //with java-style call cout << p.toString(); //with c++ style call //cout << p; cout << endl; } } return 0; }

__MACOSX/PA#2/main/._main.cpp

PA#2/main/Point.h

#ifndef POINT_H #define POINT_H #include <string> #include <sstream> #include <ostream> using namespace std; class Point { private: int _red = 0; int _green = 0; int _blue = 0; public: Point(int r = 0, int g = 0, int b = 0) { _red = r; _green = g; _blue = b; } int getRed() const { return _red; } int getGreen() const { return _green; } int getBlue() const { return _blue; } void setRed(int r) { if (r >= 0 <= 255) { _red = r; } } void setGreen(int g) { _green = g; } void setBlue(int b) { _blue = b; } //Java-style string toString() const { ostringstream output{}; output << _red << " " << _green << " " << _blue; return output.str(); } }; //C++ style ostream& operator<<(ostream &out, const Point& p) { out << p.toString(); return out; } #endif // ! POINT_H

__MACOSX/PA#2/main/._Point.h

PA#2/main/RemoveGreenEffect.h

#ifndef REMOVE_GREEN_EFFECT #define REMOVE_GREEN_EFFECT #include "Point.h" #include "SimpleImageEffect.h" #include <vector> using std::vector; class RemoveGreenEffect : public SimpleImageEffect { public: //note: we're using pass by reference because it's faster //AND it allows us to modify the original point values. virtual void processImage(vector<Point> &points) { for (Point& p : points) { p.setGreen(0); } } }; #endif // !SIMPLE_IMAGE_EFFECT_H

__MACOSX/PA#2/main/._RemoveGreenEffect.h

PA#2/main/SimpleImageEffect.h

#ifndef SIMPLE_IMAGE_EFFECT_H #define SIMPLE_IMAGE_EFFECT_H #include "Point.h" #include <vector> using std::vector; class SimpleImageEffect { public: //note: we're using pass by reference because it's faster //AND it allows us to modify the original point values. virtual void processImage(vector<Point> &points) = 0; }; #endif // !SIMPLE_IMAGE_EFFECT_H

__MACOSX/PA#2/main/._SimpleImageEffect.h

__MACOSX/PA#2/._main

PA#2/sampleinputs/blocks.ppm

__MACOSX/PA#2/sampleinputs/._blocks.ppm

PA#2/sampleinputs/cake.ppm

__MACOSX/PA#2/sampleinputs/._cake.ppm

PA#2/sampleinputs/squares.ppm

__MACOSX/PA#2/sampleinputs/._squares.ppm

PA#2/sampleinputs/tinypix.ppm

__MACOSX/PA#2/sampleinputs/._tinypix.ppm

__MACOSX/PA#2/._sampleinputs