Reputation: 23
So I have to read this image in a PPM format, and then write it to another file. It works, however if the image has comments it stops working. If the image is like this:
P3
3 2
255
255 0 0
0 255 0
0 0 255
255 255 0
255 255 255
0 0 0
It works, but if the image is like this:
P3
3 2
255
# "3 2" is the width and height of the image in pixels
# "255" is the maximum value for each color
# The part below is image data: RGB triplets
255 0 0 # red
0 255 0 # green
0 0 255 # blue
255 255 0 # yellow
255 255 255 # white
0 0 0 # black
It stops working. I really don't know why since I have programmed to ignore comments. I will leave the code below, maybe someone can help.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
typedef struct pixel {
unsigned int r,g,b;
} pixel;
typedef struct imagem{
int cols,rows;
char mnumber[2];
int maxcolor;
pixel *matrix;
}imagem;
static imagem read(const char *filename)
{
imagem img;
FILE *f;
f = fopen(filename,"rb");
if(f == NULL) {
scanf("%c %c",&img.mnumber[0],&img.mnumber[1]);
scanf("%d %d",&img.cols,&img.rows);
scanf("%d",&img.maxcolor);
img.matrix = (pixel*) malloc(img.cols*img.rows*sizeof(pixel));
for(int i = 0; i < img.cols*img.rows;i++)
{
scanf("%u %u %u",&img.matrix[i].r,&img.matrix[i].g,&img.matrix[i].b);
}
} else {
int i = 0;
while(i != 2)
{
img.mnumber[i] = getc(f);
//printf("%c\n",(char) img.mnumber[i]);
i++;
}
int c = getc(f);
while (c == '#') {
while (getc(f) != '\n') {
getc(f);
}
c = getc(f);
}
ungetc(c, f);
fscanf(f,"%d %d",&img.cols,&img.rows);
fscanf(f,"%d",&img.maxcolor);
img.matrix = (pixel*)malloc(img.cols * img.rows* sizeof(pixel));
for(int i = 0; i < img.cols*img.rows;i++)
{
fscanf(f,"%u %u %u",&img.matrix[i].r,&img.matrix[i].g,&img.matrix[i].b);
}
fclose(f);
return img;
}
return img;
}
Upvotes: 1
Views: 1044
Reputation: 22022
I would write it as something like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
typedef struct pixel {
unsigned int r,g,b;
} pixel;
typedef struct imagem{
int cols, rows;
char mnumber[2];
int maxcolor;
pixel *matrix;
} imagem;
static imagem read(const char *filename)
{
imagem img;
FILE *f;
int i;
char buf[BUFSIZ];
if (filename == NULL) {
f = stdin;
} else {
f = fopen(filename, "r");
if (f == NULL) {
fprintf(stderr, "Can't open %s\n", filename);
exit(1);
}
}
if (fgets(buf, sizeof buf, f) == NULL) {
fprintf(stderr, "Can't read data\n");
exit(1);
}
for (i = 0; i < 2; i++) {
img.mnumber[i] = buf[i];
}
if (fgets(buf, sizeof buf, f) == NULL) {
fprintf(stderr, "Can't read data\n");
exit(1);
}
sscanf(buf, "%d %d", &img.cols, &img.rows);
if (fgets(buf, sizeof buf, f) == NULL) {
fprintf(stderr, "Can't read data\n");
exit(1);
}
sscanf(buf, "%d", &img.maxcolor);
img.matrix = malloc(img.cols * img.rows * sizeof(pixel));
if (img.matrix == NULL) {
fprintf(stderr, "malloc failed\n");
exit(1);
}
i = 0;
while (fgets(buf, sizeof buf, f) != NULL) {
if (buf[0] == '#') continue;
else {
sscanf(buf, "%u %u %u", &img.matrix[i].r, &img.matrix[i].g, &img.matrix[i].b);
i++;
}
} fclose(f);
return img;
}
fgets()
and
sscanf()
rather than fscanf()
especially when we need to handle irregular lines.stdin
when the
filename is omitted. Just assign the file pointer f
to stdin
.read()
to something else
as it conflicts with the existing system call function read(2)
.Upvotes: 1