C++ Program.Running in Visual Studios. Intials J.E. Part 3: Digital Images You w
ID: 3794608 • Letter: C
Question
C++ Program.Running in Visual Studios. Intials J.E.
Part 3: Digital Images You will not only learn to program C++ in this class, we will also show you some other things. One of these things is the plain PGM image file format. You will be working with this image format in this class. First, read this short introduction (doc version) to digital images and the PGM image format. Many applications have PGM support built-in. Unfortunately, neither Windows nor Mac OS X currently come with an app which can display PGM images. On Windows, you can download IrfanView if you need a viewer. It is highly recommended that you have a program to view these files. For Macs, MacOS Sierra has finally added support for PGM images to the all-purpose viewer Preview, but you can also use Toy Viewer (available free on the App store), which I find convenient for image viewing. For Irfanview, uncheck "Use Resample for fitting" and "Use Resample for zooming under "View | Display Options". Otherwise (by default) Irfanview blurs images when you zoom them. That's great for general image viewing, but awkward for programmers trying to figure out what their program just wrote out to a PGMfile. The complete specification for the PGM format can be found on the netpbm website (look for plain PGM) or in Wikipedia: Portable Pixmap. A plain PGM file is just a simple ieexi file thnifoll ther fcolley nretlExplanation / Answer
//main.cpp
#include <iostream>
#include <fstream>
#include "image.h"
using namespace std;
int readImageHeader(char fname[], int& N, int& M, int& Q, bool& type)
{
int i, j;
unsigned char *charImage;
char header [100], *ptr;
ifstream ifp;
ifp.open(fname, ios::in | ios::binary); //Please enter your input file here
if (!ifp)
{
cout << "Can't read image: " << fname << endl;
exit(1);
}
ifp.getline(header,100,' ');
while(header[0]=='#')
ifp.getline(header,100,' ');
M=strtol(header,&ptr,0);
N=atoi(ptr);
ifp.getline(header,100,' ');
Q=strtol(header,&ptr,0);
ifp.close();
return(1);
}
int readImage(char fname[], Image& image)
{
int i, j;
int N, M, Q;
unsigned char *charImage;
char header [100], *ptr;
ifstream ifp;
ifp.open(fname, ios::in | ios::binary);
if (!ifp) //error checking
{
cout << "Can't read image: " << fname << endl;
exit(1);
}
// read header
ifp.getline(header,100,' '); //magic number
if ( (header[0]!=80) || (header[1]!=53) ) //if not P5
{
cout << "Image " << fname << " is not PGM" << endl;
exit(1);
}
ifp.getline(header,100,' ');
while(header[0]=='#') //file name line in file starts with #
ifp.getline(header,100,' ');
M=strtol(header,&ptr,0); //number of colums
N=atoi(ptr); //number of rows
ifp.getline(header,100,' ');
Q=strtol(header,&ptr,0); //max gray value
charImage = (unsigned char *) new unsigned char [M*N]; //creates 2D array
ifp.read( reinterpret_cast<char *>(charImage), (M*N)*sizeof(unsigned char)); //reads in 2D array
if (ifp.fail())
{
cout << "Image " << fname << " has wrong size" << endl;
exit(1);
}
ifp.close();
// Convert the unsigned characters to integers
int val;
for(i=0; i<N; i++)
for(j=0; j<M; j++)
{
val = (int)charImage[i*M+j];
image.setPixelVal(i, j, val);
}
delete [] charImage;
return (1);
}
int main(int argc, char *argv[])
{
int M, N, Q; // rows, cols, grayscale
int val;
bool type;
// read image header
readImageHeader(argv[1], N, M, Q, type);
// allocate memory for the image array
Image image(N, M, Q);
// read image
readImage(argv[1], image);
}
// image.h
#ifndef IMAGE_H
#define IMAGE_H
class Image
{
public:
Image(); //constructor
Image(int numRows, int numCols, int grayLevels); //constructor
~Image(); //destructor
Image(const Image& oldImage); //constructor
void operator=(const Image&); //overloaded assignment operator
void setImageInfo(int numRows, int numCols, int maxVal);
void getImageInfo(int &numRows, int &numCols, int &maxVal);
int getPixelVal(int row, int col);
void setPixelVal(int row, int col, int value);
bool inBounds(int row, int col); //checks to see if a pixel is in bounds
void getSubImage(int upperLeftRow, int upperLeftCol,
int lowerRightRow, int lowerRightCol, Image& oldImage);
void enlargeImage(int value, Image& oldImage);
void shrinkImage(int value, Image& oldImage);
void reflectImage(bool flag, Image& oldImage);
void translateImage(int value, Image& oldImage);
void rotateImage(int theta, Image& oldImage);
Image operator+(const Image &oldImage); //overloaded + operator
Image operator-(const Image& oldImage); //overloaded - operator
void negateImage(Image& oldImage);
private:
int N; // number of rows
int M; // number of columns
int Q; // number of gray levels
int **pixelVal; //2D array
};
#endif
//image.cpp
/*
Christopher Ginac
image.cpp
*/
#include <stdlib.h>
#include <iostream>
#include "image.h"
#include <cmath>
using namespace std;
Image::Image()
/* Creates an Image 0x0 */
{
N = 0;
M = 0;
Q = 0;
pixelVal = NULL;
}
Image::Image(int numRows, int numCols, int grayLevels)
/* Creates an Image of numRows x numCols and creates the arrays for it*/
{
N = numRows;
M = numCols;
Q = grayLevels;
pixelVal = new int *[N];
for(int i = 0; i < N; i++)
{
pixelVal[i] = new int [M];
for(int j = 0; j < M; j++)
pixelVal[i][j] = 0;
}
}
Image::~Image()
/*destroy image*/
{
N = 0;
M = 0;
Q = 0;
for(int i = 0; i < N; i++)
delete pixelVal [N];
delete pixelVal;
}
Image::Image(const Image& oldImage)
/*copies oldImage into new Image object*/
{
N = oldImage.N;
M = oldImage.M;
Q = oldImage.Q;
pixelVal = new int* [N];
for(int i = 0; i < N; i++)
{
pixelVal[i] = new int [M];
for(int j = 0; j < M; j++)
pixelVal[i][j] = oldImage.pixelVal[i][j];
}
}
void Image::operator=(const Image& oldImage)
/*copies oldImage into whatever you = it to*/
{
N = oldImage.N;
M = oldImage.M;
Q = oldImage.Q;
pixelVal = new int* [N];
for(int i = 0; i < N; i++)
{
pixelVal[i] = new int [M];
for(int j = 0; j < M; j++)
pixelVal[i][j] = oldImage.pixelVal[i][j];
}
}
void Image::setImageInfo(int numRows, int numCols, int maxVal)
/*sets the number of rows, columns and graylevels*/
{
N = numRows;
M = numCols;
Q = maxVal;
}
void Image::getImageInfo(int &numRows, int &numCols, int &maxVal)
/*returns the number of rows, columns and gray levels*/
{
numRows = N;
numCols = M;
maxVal = Q;
}
int Image::getPixelVal(int row, int col)
/*returns the gray value of a specific pixel*/
{
return pixelVal[row][col];
}
void Image::setPixelVal(int row, int col, int value)
/*sets the gray value of a specific pixel*/
{
pixelVal[row][col] = value;
}
bool Image::inBounds(int row, int col)
/*checks to see if a pixel is within the image, returns true or false*/
{
if(row >= N || row < 0 || col >=M || col < 0)
return false;
//else
return true;
}
void Image::getSubImage(int upperLeftRow, int upperLeftCol, int lowerRightRow,
int lowerRightCol, Image& oldImage)
/*Pulls a sub image out of oldImage based on users values, and then stores it
in oldImage*/
{
int width, height;
width = lowerRightCol - upperLeftCol;
height = lowerRightRow - upperLeftRow;
Image tempImage(height, width, Q);
for(int i = upperLeftRow; i < lowerRightRow; i++)
{
for(int j = upperLeftCol; j < lowerRightCol; j++)
tempImage.pixelVal[i - upperLeftRow][j - upperLeftCol] = oldImage.pixelVal[i][j];
}
oldImage = tempImage;
}
void Image::enlargeImage(int value, Image& oldImage)
/*enlarges Image and stores it in tempImage, resizes oldImage and stores the
larger image in oldImage*/
{
int rows, cols, gray;
int pixel;
int enlargeRow, enlargeCol;
rows = oldImage.N * value;
cols = oldImage.M * value;
gray = oldImage.Q;
Image tempImage(rows, cols, gray);
for(int i = 0; i < oldImage.N; i++)
{
for(int j = 0; j < oldImage.M; j++)
{
pixel = oldImage.pixelVal[i][j];
enlargeRow = i * value;
enlargeCol = j * value;
for(int c = enlargeRow; c < (enlargeRow + value); c++)
{
for(int d = enlargeCol; d < (enlargeCol + value); d++)
{
tempImage.pixelVal[c][d] = pixel;
}
}
}
}
oldImage = tempImage;
}
void Image::shrinkImage(int value, Image& oldImage)
/*Shrinks image as storing it in tempImage, resizes oldImage, and stores it in
oldImage*/
{
int rows, cols, gray;
rows = oldImage.N / value;
cols = oldImage.M / value;
gray = oldImage.Q;
Image tempImage(rows, cols, gray);
for(int i = 0; i < rows; i++)
{
for(int j = 0; j < cols; j++)
tempImage.pixelVal[i][j] = oldImage.pixelVal[i * value][j * value];
}
oldImage = tempImage;
}
void Image::reflectImage(bool flag, Image& oldImage)
/*Reflects the Image based on users input*/
{
int rows = oldImage.N;
int cols = oldImage.M;
Image tempImage(oldImage);
if(flag == true) //horizontal reflection
{
for(int i = 0; i < rows; i++)
{
for(int j = 0; j < cols; j++)
tempImage.pixelVal[rows - (i + 1)][j] = oldImage.pixelVal[i][j];
}
}
else //vertical reflection
{
for(int i = 0; i < rows; i++)
{
for(int j = 0; j < cols; j++)
tempImage.pixelVal[i][cols - (j + 1)] = oldImage.pixelVal[i][j];
}
}
oldImage = tempImage;
}
void Image::translateImage(int value, Image& oldImage)
/*translates image down and right based on user value*/
{
int rows = oldImage.N;
int cols = oldImage.M;
int gray = oldImage.Q;
Image tempImage(N, M, Q);
for(int i = 0; i < (rows - value); i++)
{
for(int j = 0; j < (cols - value); j++)
tempImage.pixelVal[i + value][j + value] = oldImage.pixelVal[i][j];
}
oldImage = tempImage;
}
void Image::rotateImage(int theta, Image& oldImage)
/*based on users input and rotates it around the center of the image.*/
{
int r0, c0;
int r1, c1;
int rows, cols;
rows = oldImage.N;
cols = oldImage.M;
Image tempImage(rows, cols, oldImage.Q);
float rads = (theta * 3.14159265)/180.0;
r0 = rows / 2;
c0 = cols / 2;
for(int r = 0; r < rows; r++)
{
for(int c = 0; c < cols; c++)
{
r1 = (int) (r0 + ((r - r0) * cos(rads)) - ((c - c0) * sin(rads)));
c1 = (int) (c0 + ((r - r0) * sin(rads)) + ((c - c0) * cos(rads)));
if(inBounds(r1,c1))
{
tempImage.pixelVal[r1][c1] = oldImage.pixelVal[r][c];
}
}
}
for(int i = 0; i < rows; i++)
{
for(int j = 0; j < cols; j++)
{
if(tempImage.pixelVal[i][j] == 0)
tempImage.pixelVal[i][j] = tempImage.pixelVal[i][j+1];
}
}
oldImage = tempImage;
}
Image Image::operator+(const Image &oldImage)
/*adds images together, half one image, half the other*/
{
Image tempImage(oldImage);
int rows, cols;
rows = oldImage.N;
cols = oldImage.M;
for(int i = 0; i < rows; i++)
{
for(int j = 0; j < cols; j++)
tempImage.pixelVal[i][j] = (pixelVal[i][j] + oldImage.pixelVal[i][j]) / 2;
}
return tempImage;
}
Image Image::operator-(const Image& oldImage)
/*subtracts images from each other*/
{
Image tempImage(oldImage);
int rows, cols;
rows = oldImage.N;
cols = oldImage.M;
int tempGray = 0;
for(int i = 0; i < rows; i++)
{
for(int j = 0; j < cols; j++)
{
tempGray = abs(pixelVal[i][j] - oldImage.pixelVal[i][j]);
if(tempGray < 35)// accounts for sensor flux
tempGray = 0;
tempImage.pixelVal[i][j] = tempGray;
}
}
return tempImage;
}
void Image::negateImage(Image& oldImage)
/*negates image*/
{
int rows, cols, gray;
rows = N;
cols = M;
gray = Q;
Image tempImage(N,M,Q);
for(int i = 0; i < rows; i++)
{
for(int j = 0; j < cols; j++)
tempImage.pixelVal[i][j] = -(pixelVal[i][j]) + 255;
}
oldImage = tempImage;
}
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.