Create/Save PPM-File from unsigned char* AND unsigned short* Pointers (RGB) (C++) [closed]

StackOverflow https://stackoverflow.com/questions/9282382

  •  29-04-2021
  •  | 
  •  

Question

I need help saving a PPM file in C/C++. I want to save an PPM image from the three basic color channels. The channels are represented as void * pointers (pRed, pGreen and pBlue). Those values are fixed so I cannot change them.

There is one more variable to decide how the void pointer has to be interpreted: this variable is:

bpp=1 the correct type is unsigned char *. Buffer elements are of type unsigned char

bpp=2 the correct type is unsigned short *. Buffer elements are of type unsigned short.

Now I would save an ppm file out of this three color channels.

The declarations regarding to the bpp variable are:

//bpp=1:
unsigned char* dRed = (unsigned char*)pImg->pRed;
unsigned char* dGreen = (unsigned char*)pImg->pGreen;
unsigned char* dBlue = (unsigned char*)pImg->pBlue;
unsigned char* dBw = (unsigned char*)pImg->pBw;

//bpp=2:
unsigned short* dRed = (unsigned short*)pImg->pRed;
unsigned short* dGreen = (unsigned short*)pImg->pGreen;
unsigned short* dBlue = (unsigned short*)pImg->pBlue;
unsigned short* dBw = (unsigned short*)pImg->pBw;

My code to write the ppm file:

ofstream output(fname, ios::binary|ios::out);

output << "P3"<< endl <<"# foreground "<<endl;
output << itoa(width, fname, 10);
output << " ";
output << itoa(height, fname, 10);
output << endl;
output << itoa(255, fname, 10) << endl;
...     
for(int i=0; i<(height*width); i++){
  if(bytesPerP==1){
    output << (unsigned char)((char*)dRed) << " ";
    output << (unsigned char)((char*)dGreen) << " ";
    output << (unsigned char)((char*)dBlue) << " ";
    dRed = dRed + (i * bytesPerP);
    dGreen = dGreen + (i * bytesPerP);
    dBlue = dBlue + (i * bytesPerP);
}else if(bytesPerP==2){
    output << ((unsigned short)((char*)dRed))%256 << " ";
    output << (unsigned short)((char*)dGreen)%256 << " ";
    output << (unsigned short)((char*)dBlue)%256 << " ";

    dRed = dRed + (i * bytesPerP);
    dGreen = dGreen + (i * bytesPerP);
    dBlue = dBlue + (i * bytesPerP);
}

Here is anywhere the error, because i get the right "structure" of the recorded image, but the colors are totally weird (psychodelic style) :) I have searched on the internet and tested many things, but none of them worked. Could someone point me in the right direction?

Was it helpful?

Solution

The problem is how you're outputting the bytes from your image buffers ... you need to dereference pointer to get at the actual data information, not output the actual pointer-value itself.

For instance, this:

output << (unsigned char)((char*)dRed) << " ";

outputs the 4 or 8-byte pointer value dRed cast to an unsigned char ... you want the value that the pointer dRed is pointing to, which would be done like this:

output << *dRed << " ";

Secondly, if the data for each color-channel is stored in a separate continuous linear array (i.e, red points to only red-pixels, green points to only green-pixels, vs. a buffer where it's a red-pixel, then green-pixel, then blue-pixel), then you're not incrementing the values correctly in your 16-bit-per-channel case. If the buffers are a linear array, you could simply do the following:

 output << " " << dRed[i] << " " << dGreen[i] << " " << dBlue[i] << endl;

where the extra white-space is to conform to the PPM standard where pixel value samples should be surrounded by white-space characters.

Finally, in the "plain" PPM format you're outputting, no row should be longer than 70 characters ... you're definitely going over that limit ...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top