Thread: Reading Picture file into 2dimensional data array?

  1. #1
    Registered User
    Join Date
    Oct 2008
    Posts
    18

    Reading Picture file into 2dimensional data array?

    Greetings, I am new to the boards and am trying to read a pgm picture file into a 2 dimensional array, rows and columns, of the color of each pixel. the files look like... for a 4x20 pixel picture

    "
    P2
    #imagelr.pgm
    20 20
    255
    100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100
    100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100
    100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100
    100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100
    "

    My question is what is a good way to read past the 4th line (to the data) and save each number as an int in an array.

    I've tried scanning the whole file using fread, then going through the giant string for the values, but i run into the problem of 100 being the chars '1' '0' '0', and no guarantee of how many digits will be in each pixel, makes saving them as ints hard.

    it seems like fscanf or fread pixel by pixel would be smarter, but how do i do so, and only do so after the 4th line when data starts?

    Thank you much!
    Last edited by DiscoStu9; 08-24-2009 at 05:05 PM.

  2. #2
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    The file pointer you get from fopen() maintains it's position regardless of what you do. So you can open the file, pass the pointer to a function "process_header" which reads the first four lines, and then pass the file pointer to a different function which fscanf's the pixel data, since the file pointer will now be at the fourth line, if you code everything properly.
    Last edited by MK27; 08-24-2009 at 05:12 PM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  3. #3
    Registered User
    Join Date
    Oct 2008
    Posts
    18
    excellent idea, thank you.

    Is there a simple way to read a line and have it stop after a return key? '10' i believe? so i can read lines until 4th return, then begin to fscanf

  4. #4
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by DiscoStu9 View Post
    excellent idea, thank you.

    Is there a simple way to read a line and have it stop after a return key? '10' i believe? so i can read lines until 4th return, then begin to fscanf
    Because you are using fread(), you must find the newline yourself to do line oriented processing. Yep, ASCII 10 is the newline ('\n'). So these are equivalent:

    buffer[x] == 10;
    buffer[x] == '\n';

    I have never worked with pgm files, but if those first four lines are of a consistent form you may want to use fgets() (which reads up to a newline automatically) in your "process_header" function, then you can parse each line the way you want, maybe with a switch/case. In other words, the function has a char buffer big enough to hold a single line, you fgets() into that, and then using a counter you can use switch() to decide how to deal with the information in each of the four lines.
    Last edited by MK27; 08-24-2009 at 05:26 PM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  5. #5
    Registered User
    Join Date
    Oct 2008
    Posts
    18
    i see, well i am not married to fread, and yes they are always of the same header style....
    so I will most likely do fgets 4 times, then move to freads for the data

  6. #6
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300

    Thumbs up

    Quote Originally Posted by DiscoStu9 View Post
    i see, well i am not married to fread, and yes they are always of the same header style....
    so I will most likely do fgets 4 times, then move to freads for the data
    Just a suggestion. There is nothing wrong with fread(). You probably want fscanf() for the data portion tho.

    As I hope I implied, do this with loops in separate functions, eg:
    Code:
    void process_header (FILE *fp) {
        int i;
        char buffer[64];
        for (i=0; i<4; i++) {
              fgets(buffer,64,fp);
              switch (i) {
                    case (0): extract your data from the line in buffer for the first line
                    case (1): the second line
                    [etc]
              }
         }
    }
    If you are processing multiple files you could have this function return a struct with the data, so the prototype might be:
    Code:
    struct pgm_info *process_header (FILE *fp);
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  7. #7
    Registered User
    Join Date
    Oct 2008
    Posts
    18
    thanks MK, youve been a great help, im going to try that now...

    just curious, why did you chose to use the switch statements? why not a set of 4 instructions since we know that going in...with i<4

  8. #8
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by DiscoStu9 View Post
    just curious, why did you chose to use the switch statements? why not a set of 4 instructions since we know that going in...with i<4
    The switch statement would be 4 instructions. Eg: guessing that line 3 is the dimensions and that line 4 is the palette size (I'm probably wrong), you could do something like:
    Code:
           struct pgm_info thisimage = malloc(sizeof(struct pgm_info));
           [...all that other stuff...]
                   case (2): sscanf(buffer,"%d %d",thisimage.width, thisimage.height);
                                  break;
                   case (3): sscanf(buffer,"%d",thisimage.palette);
    You could just use a sequence of if(i==2) statements to accomplish the same thing.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  9. #9
    Registered User
    Join Date
    Oct 2008
    Posts
    18
    Greetings again, I got the header all sorted out, and now I am handling the data. I am confused on what fscanf does, how do I read a line from the file and separate each number into a separate int, until a NEWLINE is found?

    Or should I use fgets and grab the whole line, then try to use atoi step by step to get the data?

  10. #10
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by DiscoStu9 View Post
    Or should I use fgets and grab the whole line, then try to use atoi step by step to get the data?
    If you use fscanf like this:
    Code:
    int val;
    fscanf(fp, "%d%*c",&val);
    you could just continually loop thru, pulling one number at a time, and not worry about the lines, etc. "%*c" means ignore one character after the digit, which could be either a space or a '\n'.

    So how you do this depends much on what you are doing with the data. There may be an EOF issue here *but* I presume part of the header is the actual image size/length, which you could use that to set the loop length, so you grab exactly as much data as is in the file.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  11. #11
    Registered User
    Join Date
    Oct 2008
    Posts
    18
    Thanks MK,

    I just read in the values looping until the number of rows/cols read in from the header. everything works and prints out correctly now! Can't thank you enough

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Reading from file and printing double data
    By hammari in forum C Programming
    Replies: 4
    Last Post: 07-14-2009, 07:02 AM
  2. Please Help Reading Data From A File
    By NickHolmes in forum C Programming
    Replies: 5
    Last Post: 05-29-2005, 11:24 PM
  3. Possible circular definition with singleton objects
    By techrolla in forum C++ Programming
    Replies: 3
    Last Post: 12-26-2004, 10:46 AM
  4. Struct *** initialization
    By Saravanan in forum C Programming
    Replies: 20
    Last Post: 10-09-2003, 12:04 PM
  5. problems reading data into an array and printing output
    By serino78 in forum C Programming
    Replies: 4
    Last Post: 04-28-2003, 08:39 AM