|
-
September 12th, 2011, 05:50 PM
#1
Problems with an algorithm - need help
Hello Users,
I am building an algorithm for a class assignment. It is a compilation of four files - ppmtest.cpp, pgmtest.cpp, pxmutils.cpp, and pxmutils.h. The two driver files are the first two names above, followed by the class function definitions in the third, then the header file which is fourth.
The algorithms, (which must be executed on linux with a command line argument, such as "./ppmtest ./picture.ppm") have to read images in to arrays, modify the images, and write them to new files with suffixes appended to the filenames. The catch is, I can't alter the two driver files, this all has to be done by modification of the class functions.
But I have two problems.
The main problems is, during execution of either script, I am not able to transfer array data from one object to another using class functions. How can I transfer array data from one object to another object using class member functions only? I have tried using instances of the objects which are first declared in the main function, but the compiler is telling me that the objects aren't defined when I try to instantiate them in the class member functions. And as you can see, the class assignment operators have to be overloaded(about halfway in the driver files, example img_g = img_c If there is a way to synchronize array data from one object to the other using this overloaded assignment operator, then this would be ideal. Otherwise any other way might work.
A second problem is why are the images not converting correctly? I have to produce negatives of both color images and grayscale, and I have to produce gray from color, and color from gray using a colormap. I have been somewhat successful, but there is alot of distortion in the images and I am not sure where the glitch is
Here is my code:
The Driver File For PGM Input:
<code>
#include <cstdlib>
#include <iostream>
#include <string>
using namespace std;
#include "pxmutils.h"
int main(int argc, char *argv[])
{
if (argc == 1) {
cerr << "No input file specified!\n";
exit(0);
}
string fname = argv[1];
size_t dp;
if ((dp = fname.rfind(".pgm")) == string::npos) {
cout << "PGM error: file suffix " << fname
<< " not recognized\n";
exit(0);
}
fname.erase(dp);
pgm img_g;
ppm img_c;
img_g.read(fname+".pgm");
if (argc == 3)
img_c.set_cmap(argv[2]);
img_c = img_g;
img_g.negative();
img_g.write(fname+"_n.pgm");
img_c.write(fname+"_c.ppm");
}
</code>
The Driver File For PPM Input:
<code>
#include <cstdlib>
#include <iostream>
#include <string>
using namespace std;
#include "pxmutils.h"
int main(int argc, char *argv[])
{
if (argc != 2) {
cerr << "No input file specified!\n";
exit(0);
}
string fname = argv[1];
size_t dp;
if ((dp = fname.rfind(".ppm")) == string::npos) {
cout << "PPM error: file suffix " << fname
<< " not recognized\n";
exit(0);
}
fname.erase(dp);
ppm img_c;
pgm img_g;
img_c.read(fname+".ppm");
img_g = img_c;
img_c.negative();
img_c.write(fname+"_n.ppm");
img_g.write(fname+"_g.pgm");
}
</code>
The Class Function Definitions:
<code>
#include <fstream>
#include "pxmutils.h"
//Class PGM Definitions:
pgm: gm()
{
}
pgm::~pgm()
{
//Delete Values
}
void pgm::read(string inputname)
{
//filename = inputname;
char* bufferchar2 = new char[5];
const char* temp2 = inputname.c_str();
totalsize = 0;
ifstream imagestream2;
imagestream2.open(temp2, ios::binary);
if (imagestream2.fail())
{
cout << endl;
cout << "File Opening Failed" << endl;
}
rows = 0;
cols = 0;
luminance = 0;
cout << "Temp: " << temp2 << endl;
//Reads in the header data:
imagestream2 >> filetype;
imagestream2 >> rows;
imagestream2 >> cols;
imagestream2 >> luminance;
imagestream2.read (bufferchar2, 1); // Should be set to '1' because with this setting, the image is displaying properly when all channels are set positiv Reads in the blank character following the header data, works a little differently at setting "2"
cout << "Filetype: " << filetype << endl;
cout << "Rows " << rows << endl;
cout << "Cols: " << cols << endl;
cout << "Luminance: " << luminance << endl;
if(filetype != "P5")
cout << "Wrong Filetype, Must Be \"P5\" " << endl;
totalsize = (rows*cols*3.1);
graypgm = new char[totalsize];
// read data as a block:
imagestream2.read (graypgm, totalsize);
//cout << "Output Read " << graypgm << endl;
}
void pgm::negative()
{
for (int i = 0; i < totalsize; i++)
{
graypgm[i] = (-graypgm[i]);
}
}
void pgm::write(string outputname2)
{
//gray.colorneg = ppm.colorneg;
//And these lines write the grayscale pgm version of the original image:
//sync(img_c, img_g);
const char* temp3 = outputname2.c_str();
string P5 = "P5";
cout << "PGM Write Name: " << temp3 << endl;
ofstream imageoutgray;
imageoutgray.open(temp3);
if (imageoutgray.fail())
{
cout << endl;
cout << "File Imageoutgray Opening Failed" << endl;
}
ofstream imageoutgraybin;
imageoutgraybin.open(temp3, ios::app|ios::binary);
if (imageoutgraybin.fail())
{
cout << endl;
cout << "File Imageoutgraybin Opening Failed" << endl;
}
imageoutgray << P5 << endl;
imageoutgray << rows << " " << cols << endl;
imageoutgray << luminance << endl;
imageoutgraybin.write (graypgm, totalsize);
}
pgm& pgm: perator =(const pgm& testx)
{
//sync(img_c, img_g);
//img_g.colorppm = img_c.colorppm;
//test = new char[totalsize];
char temp1 = 0;
char temp2 = 0;
char temp3 = 0;
char temp4 = 0;
int a = 0;
graypgm = new char[totalsize];
for (int i = 0; i < totalsize; i++)
{
//The following lines work to transfer the color byte data into a grayscale P5 image:
temp1 = ((colorppm[i]) * 1); //Green
temp2 = ((colorppm[i+1]) * 0); //Blue
temp3 = ((colorppm[i+2]) * 0); // Red
temp4 = temp1 + temp2 + temp3;
graypgm[a] = temp4;
i = i+2;
a++;
}
}
void pgm::set_cmap(string filename)
{
}
//Class PPM Definitions:
ppm: pm()
{
}
ppm::~ppm()
{
//delete values
}
void ppm::read(string inputname)
{
//filename = inputname;
char* bufferchar = new char[3];
const char* temp = inputname.c_str();
totalsize = 0;
ifstream imagestream;
imagestream.open(temp, ios::binary);
if (imagestream.fail())
{
cout << endl;
cout << "File Opening Failed" << endl;
//cout << "File Opened" << endl;
}
rows = 0;
cols = 0;
luminance = 0;
cout << "Temp: " << temp << endl;
//Reads in the header data:
imagestream >> filetype;
imagestream >> rows;
imagestream >> cols;
imagestream >> luminance;
imagestream.read (bufferchar, 1); // Should be set to '1' because with this setting, the image is displaying properly when all channels are set positive. Reads in the blank character following the header data, works a little differently at setting "2"
cout << "Filetype: " << filetype << endl;
cout << "Rows " << rows << endl;
cout << "Cols: " << cols << endl;
cout << "Luminance: " << luminance << endl;
if(filetype != "P6")
cout << "Wrong Filetype, Must Be \"P6\" " << endl;
totalsize = (rows*cols*3.1);
colorppm = new char[totalsize];
// read data as a block:
imagestream.read (colorppm, totalsize);
/*
//filename = inputname;
char* bufferchar = new char[3];
const char* temp = inputname.c_str();
totalsizeppm = 0;
ifstream imagestream;
imagestream.open(temp, ios::binary);
if (imagestream.fail())
{
cout << endl;
cout << "File Opening Failed" << endl;
}
//else if (imagestream.is_open())
//cout << "File Opened" << endl;
rowsppm = 0;
colsppm = 0;
luminanceppm = 0;
cout << "Temp: " << temp << endl;
//Reads in the header data:
imagestream >> filetype;
imagestream >> rowsppm;
imagestream >> colsppm;
imagestream >> luminanceppm;
imagestream.read (bufferchar, 1); // Should be set to '1' because with this setting, the image is displaying properly when all channels are set positive. Reads in the blank character following the header data, works a little differently at setting "2"
cout << "Filetype: " << filetype << endl;
cout << "Rows " << rowsppm << endl;
cout << "Cols: " << colsppm << endl;
cout << "Luminance: " << luminanceppm << endl;
if(filetype != "P6")
cout << "Wrong Filetype, Must Be \"P6\" " << endl;
totalsizeppm = (rowsppm*colsppm);
buffer = new char[99500000];
// read data as a block:
imagestream.read (buffer, 99500000);
*/
}
void ppm::negative()
{
colorneg = new char[totalsize];
int a = 0;
for (int i = 0; i < totalsize; i++)
{
//The three following lines work to transfer the color image into a negative image:
colorneg[a] = (-colorppm[i]); //Green
colorneg[a+1] = (-colorppm[i+1]); //Blue
colorneg[a+2] = (-colorppm[i+2]); // Red
//temp4 = temp1 + temp2 + temp3;
//output[a] = temp4;
i = i+2;
a = a+3;
}
}
void ppm::write(string outputname)
{
//And these lines write the color negative version of the original image:
const char* temp = outputname.c_str();
string P6 = "P6";
cout << "PPM Write Name: " << temp << endl;
ofstream imageoutneg;
imageoutneg.open(temp);
if (imageoutneg.fail())
{
cout << endl;
cout << "File Out1 Opening Failed" << endl;
}
ofstream imageoutbinneg;
imageoutbinneg.open(temp, ios::app|ios::binary);
if (imageoutbinneg.fail())
{
cout << endl;
cout << "File Out2 Opening Failed" << endl;
}
imageoutneg << P6 << endl;
imageoutneg << rows << " " << cols << endl;
imageoutneg << luminance << endl;
imageoutbinneg.write (colorneg, totalsize);
}
void ppm::set_cmap(string filename)
{
}
ppm& ppm: perator =(const class pgm&)
{
}
//End of File
</code>
And The Header File:
<code>
#ifndef PXMUTILS_H
#define PXMUTILS_H
#include <cstdlib>
#include <iostream>
#include <string>
using namespace std;
//typedef ?
//global functions ?
class pgm {
public:
pgm();//Constructor
~pgm();//Destructor
void read(string inputname);
void write(string outputname2);
void negative();
void to_rgb();
pgm& operator =(const pgm& testx);
void set_cmap(string filename);
string filetype;
int rows;
int cols;
int luminance;
int totalsize;
char* output;
char* colorppm;
char* graypgm;
char* colorneg;
char* graycolored;
char* grayneg;
// char* buffer;
// char* bufferchar;
//string filename;
private:
};
class ppm {
public:
ppm();//Constructor
~ppm();//Destructor
void read(string inputname);
void write(string outputname);
void negative();
void to_gray();
void set_cmap(string filename);
ppm& operator =(const class pgm&);
string filetype;
int rows;
int cols;
int luminance;
int totalsize;
char* buffer;
char* outputneg;
//char* bufferchar;
char* colorppm;
char* graypgm;
char* colorneg;
char* graycolored;
char* grayneg;
//string filename;
private:
};
#endif
</code>
Remember, to execute these drivers they must be done on UNIX with the command line prompt as above.
I mainly just want to be able to say img_g.colorppm = img_c.colorppm; (colorppm is an array).
Whoever can provide advice is very considerate.
-
September 15th, 2011, 03:04 AM
#2
Re: Problems with an algorithm - need help
 Originally Posted by Netmaxweb
I mainly just want to be able to say img_g.colorppm = img_c.colorppm; (colorppm is an array).
If you were to declare your arrays as std::vector instead you would be able to remove all of the manual memory management from your code and img_g.colorppm = img_c.colorppm would 'just work'.
"It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
Richard P. Feynman
-
September 17th, 2011, 10:50 AM
#3
Re: Problems with an algorithm - need help
so much code. so few code tags
-
September 17th, 2011, 02:12 PM
#4
Re: Problems with an algorithm - need help
 Originally Posted by Netmaxweb
But I have two problems.
You have more than two problems.
1) Use code tags when posting code. The code you posted is practically unreadable.
2) Why are you using char pointers and new[]? Here is an example:
Code:
char* bufferchar2 = new char[5];
Either declare an array,
Code:
char bufferchar2[5];
or use std::string. There is no reason whatsoever to be using char* in your program at all. Everything can be done using std::string or as pointed out previously, std::vector<char>.
Another thing is that you are using "5" as the size. What is the reason why you're assuming only 5 characters? What if the number of characters is 6? or 7?. If you are using arrays, you shouldn't declare them to have a size that can lead to memory access violations. Declare the array large enough so that there is little chance of there being an array boundary error.
Better than that, just use std::string instead of arrays.
Also, the way you learn things in C++ is to write small test applications so that you become familiar with how to use the concepts. Introducing new concepts into the middle of a larger program isn't the way to do things.
And last, instead of posting your entire project and asking "what's wrong?" did you run your program using your debugger? The debugger is supposed to be used when you encounter a bug or the program isn't behaving as expected. Learning how to debug and use the debugging tools that are available to you is part and parcel of writing C++ programs.
Regards,
Paul McKenzie
Last edited by Paul McKenzie; September 17th, 2011 at 02:22 PM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|