2

So ive already read a number of the questions that relate to this but none of them have solved my problem. Im currently attempting to read in a P6 ppm file (Its a binary file). My current code is

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

struct pixel {
    char red;
    char green;
    char blue;
};

int main(int argc, char **argv)
{
    char type[3];
    int numRow, numCol, maxNum;
    FILE *oldFile, *newFile;
    struct pixel currentPixel;
    char buffer[5];

    oldFile = fopen(argv[1], "rb");
    if(oldFile == NULL) {
        fprintf(stderr, "Could not open file %s for reading in binary", argv[1]);
        return 0;
    }
    fscanf(oldFile, "%2s", type);
    type[2] = '\0';
    if(strcmp(type, "P6") != 0) {  //Make sure we have a P6 file
        printf("This file is not of type P6");
        return 0;
    }

    newFile = fopen(argv[2], "wb");
    fprintf(newFile, "%s\n", type);
    /*Read number of columns
    rows and
    The max number that can represent a colour*/
    fscanf(oldFile, "%d", &numCol);
    fscanf(oldFile, "%d", &numRow);
    fscanf(oldFile, "%d", &maxNum);
    /*Print the information to newFile*/
    fprintf(newFile, "%d %d\n", numCol, numRow);
    fprintf(newFile, "%d\n", maxNum);
    fseek(oldFile, 1, SEEK_CUR);

    fread(&currentPixel, sizeof(struct pixel), 1, oldFile);
    printf("%c %c %c", currentPixel.red, currentPixel.green, currentPixel.blue);

    fclose(newFile);
    fclose(oldFile);
    return 0;
}

So the beginning works and my newFile contains the lines P6, 3 3, and 255. I then try to read in the actual pixels with the fread line. This is where it fails and im not sure why. It currently prints out two question marks inside of a diamond. I am currently only trying to read in the first three numbers which make up one pixel (one red component one green and one blue).

I also have a P3 file of the same picture and the P3 file looks like:

 P3

3 3

255

  0 255 255   0   0   0   0   0 255

255   0 255 100 100 100 255   0   0

255 255   0 255 255 255   0 255   0

So the binary file should be set up like this but just in binary format. When i type in

od -c binaryImage.ppm

I get

0000000   P   6  \n   3       3  \n   2   5   5  \n  \0 377 377  \0  \0
0000020  \0  \0  \0 377 377  \0 377   X   X   X 377  \0  \0 377 377  \0
0000040 377 377 377  \0 377  \0
0000046

Im not sure why my fread function is not working.Not sure if relevant but i am compiling on Linux Ubuntu with

gcc -Wall rotate.c -o rotate

TheQAGuy
  • 498
  • 7
  • 17
  • @WeatherVane The first three lines are regular text. Reading those with `fscanf` works fine but after that we need to read using `fread` since the rest of the file is written in binary – TheQAGuy Nov 08 '15 at 20:01
  • Why are you printing RGB values as characters (%c) instead as numbers (%d)? That's the reason you get strange symbols in the output. – Bruno Nov 08 '15 at 20:15
  • @BrunoBellucci Thats a good question. I changed my code so instead of red, green and blue being char i made them int's. It now prints out `16776960 0 -16711681` – TheQAGuy Nov 08 '15 at 20:17
  • No. Your pixel values should be char, but you need print them as integers. – Bruno Nov 08 '15 at 20:27
  • @BrunoBellucci That prints out `0 -1 -1` – TheQAGuy Nov 08 '15 at 20:31
  • Use `unsigned char` to cover the 0-255 range. –  Nov 08 '15 at 20:32
  • As @WumpusQ.Wumbley said, use `unsigned char` or do a `cast` when using the value. I updated the answer with more details. – Bruno Nov 08 '15 at 20:38
  • @BrunoBellucci Okay so that works thank you very much for your help. Is there any way you could give me a quick explanatioon of why it works? Im a little bit confused. Nevermind just saw your answer :) – TheQAGuy Nov 08 '15 at 20:40

1 Answers1

2

You are printing RGB values as characters instead as numbers. Keep them as unsigned char (because they have values between [0-255]) in the structure, but use %d when printing. You should use printf as follows:

printf("%d %d %d", currentPixel.red, currentPixel.green, currentPixel.blue);

Also I recommend do not use a structure to read the RGB values because the compiler will probably add a padding byte to align the structure to the machine word (e.g. 32 bits). In 32 bits systems, you will read 4 bytes. You can check this printing the sizeof(struct pixel). To read more about structure alignment you could check the Wikipedia article Data Structure Alignment.

Instead a struct, use a char array:

unsigned char currentPixel[3];
...
fread(currentPixel, 3, 1, oldFile);
printf("%d %d %d", currentPixel[0], currentPixel[1], currentPixel[2]);

Also, if you need to read the entire image, create an array of unsigned char with size number of pixels x 3. The 3 is the number of bytes for the RGB tuple. If the PPM format include some padding at the end of each line, you need to consider this too.

Bruno
  • 193
  • 4
  • Shouldnt the line `printf("%c %c %c", currentPixel[0], currentPixel[1], currentPixel[2]);` be `printf("%d %d %d", currentPixel[0], currentPixel[1], currentPixel[2]);`? – TheQAGuy Nov 08 '15 at 20:45