I've written a program that takes a PGM image as input and converts it to a PBM file. However, the image I get as output is incorrect.
I determine if a pixel is white if its value is bigger than (max 1)/2 then use putchar() to place the character with the value 0 and if its black 1(ive also tried max instead of 1 and 255). However, I get a bunch of vertical lines as output. I'm running this in a Linux terminal with the command :
./prog < image1.pgm > image2.pbm
This is the function I'm using to read and transform the image (where size is height and width, and max is the max value of each pixel):
void p5_to_p4(int size, int max){
int g1,g2,g3;
int i;
for(i=0; i<size; i ){
g1=getchar();
g2=getchar();
g3=getchar();
if (g1>((max 1)/2)){
putchar(0);
putchar(0);
putchar(0);
}
else {
putchar(max);
putchar(max);
putchar(max);
}
}
}
this is the output image im getting(in jpeg form): output when this is what i should be getting correct output
CodePudding user response:
I've written a program that takes a PGM image as input and converts it to a PBM file. However, the image I get as output is incorrect.
Not surprising. Taking the function presented to be for converting a pixel raster from the format of NetPBM P5 ("PGM") to the pixel raster format of NetPBM P4 ("PBM"), the function has at least these issues:
PGM files can use either one-byte or two-byte samples, depending on the maximum sample value specified, but the function presented neither adapts to the maximum sample value nor assumes either of the two valid sample sizes. Instead, it assumes three-byte samples. Perhaps it is supposing three color channels, but PGM has only one.
PBM files use one byte per eight pixels, but the function outputs three bytes per one pixel.
So, first, read the samples correctly. In that regard, do note that if you have to handle two-byte samples then they are stored most-significant byte first, which is probably opposite to your machine's native byte order.
Second, you'll need to pack the output 8 one-bit samples per byte. Read the linked specs for details if you need them. Note that if the number of samples is not divisible by eight then you'll need to add one or more dummy bits to the last byte.
CodePudding user response:
- PBM file format packs 8 pixels into a byte in the order of msb first and lsb last.
- If the width of the image is not multiple of 8, the last odd pixels are packed into a byte without wrapping around to the next line. Then you need to let the function know width and height individually, not the total size.
Then the converter function will look like:
void p5_to_p4(int width, int height, int max)
{
int g, b; // g for gray, b for binary
int i, j, k;
for (i = 0; i < height; i ) {
for (j = 0; j < width / 8; j ) {
b = 0;
for (k = 0; k < 8; k ) { // process 8 pixels at a time
g = getchar();
if (max > 255) { // in case of 2 bytes per pixel pgm
g = (g << 8) getchar();
}
b <<= 1;
if (g < (max 1) / 2) {
b |= 1; // raise the bit for a dark pixel
}
}
putchar(b);
}
if (width % 8) { // handle odd pixels, if any
b = 0;
for (k = 0; k < width % 8; k ) {
g = getchar();
if (max > 255) {
g = (g << 8) getchar();
}
b <<= 1;
if (g < (max 1) / 2) {
b |= 1;
}
}
b <<= 8 - width % 8; // justify to the msb
putchar(b);
}
}
}