Help with C++ program converting PBM (p4) to PPM (p5)

H

Howler

Hello all,

I am having a hard time seeing what I am doing wrong with a program I
am having to write that converts pbm monochrome images into a similar
pgm file. The problem I am having is understanding how to properly
convert the bit/pixel in pbm to byte/pixel in pgm. My program is very
straight forward conceptually open files, read header, read binary
data, convert to p5 in loop and then write file out. My for loop is
where I am having a problem.

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

/*** New Data Types ***/
typedef unsigned char BYTE;

struct PIC
{
unsigned int nChannel;
bool InterLeaved;
unsigned int Width, Height;
BYTE *img;
};


void WritePGM(ofstream & outfile, PIC pic)
{
outfile << "P5" << endl;
outfile << pic.Width << " " << pic.Height << endl;
outfile << 255 << endl;

outfile.write(reinterpret_cast<char *>(pic.img),
pic.Width*pic.Height);
}


void LoadImage(ifstream &infile, PIC &pic)
{
infile.read(reinterpret_cast<char *>(pic.img),
pic.Width*pic.Height*pic.nChannel);
}


bool LoadP4Header(ifstream &infile, PIC &pic)
{
bool rtv = true;;
char buf[16];
int bufIndex;
int width, height, maxValue;

infile.read(buf, 2); // get the magic number
buf[2]='\0';

if(buf[0] == 'P' && buf[1] == '4'){
infile.read(buf, 1);
while(isspace(buf[0])){ // Skip white space(s)
infile.read(buf,1);
}

if(buf[0] == '#') { // Skip the comment line
while(buf[0] != '\n'){ // search end of line
infile.read(buf,1);
}
while(isspace(buf[0])){ // Skip white space(s)
infile.read(buf,1);
}
}

// get width
bufIndex = 0;
while(bufIndex < 15 && !isspace(buf[bufIndex])){
bufIndex++;
infile.read(buf+bufIndex, 1);
}
buf[bufIndex] = NULL; // null terminated string
width = atoi(buf);

// get height
infile.read(buf,1);
while(isspace(buf[0])){ // Skip white space(s)
infile.read(buf,1);
}
bufIndex = 0;
while(bufIndex < 15 && !isspace(buf[bufIndex])){
bufIndex++;
infile.read(buf+bufIndex, 1);
}
buf[bufIndex] = NULL; // null terminated string
height = atoi(buf);


// set the image information in the struct
pic.nChannel = 1;
pic.InterLeaved = false;
pic.Width = width;
pic.Height = height;

}
//else rtv = false;

return rtv;
}; // end of LoadP4Header()


int main(int argc, char* argv[])
/**************************************************************************************************
Arguments:
argv[1]: input file name
argv[2]: output file name
**************************************************************************************************/
{
ifstream infile; /* input file */
ofstream outfile;
char inFileName[128]; /* input file name */
char outFileName[128];
int Npixels, i, j;
PIC P4,P5;


// read the arguments
if(argc == 3)
{
strcpy(inFileName, argv[1]);
strcpy(outFileName, argv[2]);
}
else
{
cout<<"input Filename: ";
cin>>inFileName;
cout<<"Output Filename: ";
cin>>outFileName;

}

/* open input/output file */
infile.open(inFileName, ios::binary);
outfile.open(outFileName, ios::binary);

/* check input file */
if(!infile)
{
cout<<"Cannot open input file "<< inFileName<<endl;
return 1;
}

if (LoadP4Header(infile, P4)) // load pbm (P4) image header
information
{
// allocate the memory for the input image
P4.img = new BYTE[P4.Width*P4.Height*P4.nChannel/8];

LoadImage(infile, P4);

// allocate memory for output images
P5.nChannel = 1;
P5.InterLeaved = false;
P5.Width = P4.Width;
P5.Height = P4.Height;

Npixels = P4.Width*P4.Height;
P5.img = new BYTE [Npixels]; //pgm format 1 byte per pixel
int j = 0;
// de-interleaved

BYTE Results[8];

for (i=0; i < Npixels; i++){
BYTE aResult = (1-(P4.img&0x80)) * 255;
BYTE bResult = (1-(P4.img&0x40)) * 255;
BYTE cResult = (1-(P4.img&0x20)) * 255;
BYTE dResult = (1-(P4.img&0x10)) * 255;
BYTE eResult = (1-(P4.img&0x08)) * 255;
BYTE fResult = (1-(P4.img&0x04)) * 255;
BYTE gResult = (1-(P4.img&0x02)) * 255;
BYTE hResult = (1-(P4.img&0x01)) * 255;
cout<<aResult;
cout<<bResult;
cout<<cResult;
//for(y=0; y <8; y++)


}//end for outer loop

// output PGM (P5) images
WritePGM(outfile, P5);

/* Delete the pointers */
delete [] P4.img;
delete [] P5.img;
}
else
{
cout << "Error - reading PPM (P4) image header\n";
return 1;
}


/* Close file */

outfile.close();
infile.close();

return 0;
}
 
D

David Harmon

On 13 Sep 2006 20:39:16 -0700 in comp.lang.c++, "Howler"
My for loop is where I am having a problem. ....
for (i=0; i < Npixels; i++){
BYTE aResult = (1-(P4.img&0x80)) * 255;
BYTE bResult = (1-(P4.img&0x40)) * 255;
BYTE cResult = (1-(P4.img&0x20)) * 255;


OK, I'm not sure of the intent of your loop, so this probably isn't
quite right either. Repetitive code like that always bugs me, so
I'd go for something more like:

BYTE *inptr = P4.img, *outptr = P5.img, mask = 0x80;

for (int i=0; i < Npixels; i++){
*outptr++ = (*inptr & mask) ? 255 : 0;
mask >>= 1;
if (mask == 0) {
mask = 0x80;
inptr++;
}
}
 
H

Howler

David said:
On 13 Sep 2006 20:39:16 -0700 in comp.lang.c++, "Howler"
My for loop is where I am having a problem. ...
for (i=0; i < Npixels; i++){
BYTE aResult = (1-(P4.img&0x80)) * 255;
BYTE bResult = (1-(P4.img&0x40)) * 255;
BYTE cResult = (1-(P4.img&0x20)) * 255;


OK, I'm not sure of the intent of your loop, so this probably isn't
quite right either. Repetitive code like that always bugs me, so
I'd go for something more like:

BYTE *inptr = P4.img, *outptr = P5.img, mask = 0x80;

for (int i=0; i < Npixels; i++){
*outptr++ = (*inptr & mask) ? 255 : 0;
mask >>= 1;
if (mask == 0) {
mask = 0x80;
inptr++;
}
}
 
H

Howler

David said:
On 13 Sep 2006 20:39:16 -0700 in comp.lang.c++, "Howler"
My for loop is where I am having a problem. ...
for (i=0; i < Npixels; i++){
BYTE aResult = (1-(P4.img&0x80)) * 255;
BYTE bResult = (1-(P4.img&0x40)) * 255;
BYTE cResult = (1-(P4.img&0x20)) * 255;


OK, I'm not sure of the intent of your loop, so this probably isn't
quite right either. Repetitive code like that always bugs me, so
I'd go for something more like:

BYTE *inptr = P4.img, *outptr = P5.img, mask = 0x80;

for (int i=0; i < Npixels; i++){
*outptr++ = (*inptr & mask) ? 255 : 0;
mask >>= 1;
if (mask == 0) {
mask = 0x80;
inptr++;
}
}



David,

Thanks for the input. Your code actually fixed my problem. And the
code is much more elegant. Thanks mate.!!

Cheers!!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top