By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,885 Members | 1,252 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,885 IT Pros & Developers. It's quick & easy.

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

P: n/a
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[i]&0x80)) * 255;
BYTE bResult = (1-(P4.img[i]&0x40)) * 255;
BYTE cResult = (1-(P4.img[i]&0x20)) * 255;
BYTE dResult = (1-(P4.img[i]&0x10)) * 255;
BYTE eResult = (1-(P4.img[i]&0x08)) * 255;
BYTE fResult = (1-(P4.img[i]&0x04)) * 255;
BYTE gResult = (1-(P4.img[i]&0x02)) * 255;
BYTE hResult = (1-(P4.img[i]&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;
}

Sep 14 '06 #1
Share this Question
Share on Google+
3 Replies


P: n/a
On 13 Sep 2006 20:39:16 -0700 in comp.lang.c++, "Howler"
<Mr*******@gmail.comwrote,
My for loop is where I am having a problem.
....
> for (i=0; i < Npixels; i++){
BYTE aResult = (1-(P4.img[i]&0x80)) * 255;
BYTE bResult = (1-(P4.img[i]&0x40)) * 255;
BYTE cResult = (1-(P4.img[i]&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++;
}
}

Sep 14 '06 #2

P: n/a

David Harmon wrote:
On 13 Sep 2006 20:39:16 -0700 in comp.lang.c++, "Howler"
<Mr*******@gmail.comwrote,
My for loop is where I am having a problem.
...
for (i=0; i < Npixels; i++){
BYTE aResult = (1-(P4.img[i]&0x80)) * 255;
BYTE bResult = (1-(P4.img[i]&0x40)) * 255;
BYTE cResult = (1-(P4.img[i]&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++;
}
}
Sep 14 '06 #3

P: n/a

David Harmon wrote:
On 13 Sep 2006 20:39:16 -0700 in comp.lang.c++, "Howler"
<Mr*******@gmail.comwrote,
My for loop is where I am having a problem.
...
for (i=0; i < Npixels; i++){
BYTE aResult = (1-(P4.img[i]&0x80)) * 255;
BYTE bResult = (1-(P4.img[i]&0x40)) * 255;
BYTE cResult = (1-(P4.img[i]&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!!

Sep 14 '06 #4

This discussion thread is closed

Replies have been disabled for this discussion.