Skip to content Skip to sidebar Skip to footer

C Read Ppm File Header How to Deal With Whitespace

  1. #one

    bgibs24 is offline

    Registered User


    Assist parsing ppm in C


  2. #two

    MartinR is offline

    Registered User MartinR's Avatar


    Definitely post the code not the screenshot of the code, I can barely see something.


  3. #3

    bgibs24 is offline

    Registered User


    Code:

    int  chief (int argc, char *argv[])  {           // declarations hither             // open input file          FILE *input;         input= fopen(argv[two],"r");               // parseHeader office call here         parseHeader(input);           // malloc infinite for the array (example given in assignment write-up)         struct pixel *image =          (struct pixel *) malloc(sizeof(struct pixel) * g_width * g_height);           // parseImage function call hither         parseImage( input , image );             // close input file          fclose(input);             // manipulate the paradigm according to command-line parameter         //              1: mirror image         //              2: upside downward image         //              3: rotate to the correct 90 degrees   switch (*argv[1]) {         case '1':                 mirror(paradigm);                 break;         case '2':                 flip(image);                 intermission;         case 'three':                 rotate(image);                 break;         default:                 printf("Invalid argument\north");                 break; }               return 0; }

    Code:

    void parseHeader(FILE *input) { char c; int rgbComp=255;   //bank check for comments c= getc(input); while (c=='#') {         while (getc(input) != '\n')         c= getc(input); }   ungetc(c,input);   //get meridian and width if(fscanf(input,"P6 %d %d",&g_width,&g_height) != ii) { printf("Cannot read paradigm size\northward"); }   //get rgb component if(fscanf(input,"%d\n",&rgbComp) !=one) { printf("Cannot read RGB\n");   }   //read depth if(rgbComp != RGB_COMPONENT_COLOR) { printf("Invalid RGB\due north");; }   }     void parseImage(FILE *input, struct pixel *theArray) { int i; int numPixels;   numPixels=g_height*g_width; //read in pixel data for (i=0;i<numPixels;i++) {    fscanf(input,"%c%c%c",&theArray[i].r,&theArray[i].g,&theArray[i].b); } }


  4. #4

    bgibs24 is offline

    Registered User


    Everyone? I just need aid figuring out why the image wont load. Am i using my getc functions right?


  5. #5

    Salem is online now

    and the hat of int overfl Salem's Avatar


    > if(fscanf(input,"%d\n",&rgbComp) !=ane)
    The abaft \n doesn't consume a unmarried newline.
    It will eat any whitespace subsequently newline too, mayhap part of your image data.

    FWIW, you're better off reading each header line with fgets() than fscanf()

    > fscanf(input,"%c%c%c",&theArray[i].r,&theArray[i].m,&theArray[i].b);
    Read each character using fgetc().


  6. #6

    Nominal Animal is offline

    Ticked and off


    Quote Originally Posted by Salem View Post

    FWIW, yous're meliorate off reading each header line with fgets() than fscanf()

    Actually, the PPM format is a scrap funny; it allows comments in the header part, prior to the maxval component. For example, GIMP adds 1 (just prior to width). You really only need getc() and a helper function I call getnni():

    Lawmaking:

    #include <stdio.h> #include <errno.h>  /** getnni() - Parse a nonnegative integer  * @input - Input stream  *  * This function skips all leading whitespace,  * including comments (to the end of the line) following a #,  * and so parses a nonnegative decimal integer.  * The graphic symbol following the number is left in the stream  * (via ungetc()).  *  * The function returns the nonnegative number,  * or -one with errno prepare if an fault occurs:  *     ERANGE   The value is also large to fit in an integer  *     ENOENT   Premature end of file  *     EDOM     Not a nonnegative integer  *  * Use this code in whatever way you wish at your ain chance,  * just don't blame the author if it doesn't work. */ static int getnni(FILE *const input) {     int c;      c = getc(input);      while (c == '\t' || c == '\n' || c == '\v' ||            c == '\f' || c == '\r' || c == ' ' ||            c == '#')         if (c == '#') {             while (c != EOF && c != '\n' && c != '\r')                 c = getc(input);         } else             c = getc(input);      if (c >= '0' && c <= 'nine') {         int five = 0;          while (c >= '0' && c <= '9') {             const int o = v;             5 = 10 * v + c - '0';             if ((int)(v / ten) != o || five < 0)                 render errno = ERANGE;             c = getc(input);         }          if (c != EOF)             ungetc(c, input);          return v;     }      if (c == EOF)         errno = ENOENT;     else         errno = EDOM;      return -1; }
    Using the in a higher place, you can read and verify a PPM prototype header thus:

    Lawmaking:

                          FILE *input;     int c, width, summit, maxval;      /* Assuming input has been opened via      *   input = fopen("filename", "rb");      * or similar, and that you've checked that      *   input != NULL     */      c = getc(input);     if (c != 'P')         NOT_A_PPM_IMAGE();      c = getc(input);     if (c != '6')         NOT_A_BINARY_PPM_IMAGE();      width = getnni(input);     if (width <= 0)         INVALID_PPM_WIDTH();      pinnacle = getnni(input);     if (height <= 0)         INVALID_PPM_HEIGHT();      maxval = getnni(input);     if (maxval <= 0 || maxval >= 65536)         INVALID_PPM_MAXVAL();
    If maxval >= 256, then each pixel is composed of a sextet of characters: RH R50 GH GFifty BH BL , with scarlet = RH �256 + RL , greenish = GH �256 + GFifty , and blue = BH �256 + BL , and 0 <= carmine, green, blue <= maxval.

    If maxval <= 255, and so each pixel is composed of a triplet of characters: R Thousand B, with 0 <= R, Thousand, B <= maxval.

    In both cases, you tin use fgetc() or getc() to read the characters. There is no padding, merely widthtiptop triplets/sextets of raw characters. (That is, the data is non even a string, simply raw character information.)

    (PGM format is very like; instead of red-light-green-blue triplets, yous take just i character (maxval <= 255; a pair of characters if maxval >= 256) indicating greyness levels: 0 is black, and maxval white. The magic value is P5, i.e. '5' instead of '6' above.)

    Although PPM (and PGM) is not compressed, information technology is one of the rare lossless formats that does make information technology easy to admission/generate high dynamic range images (up to 65535:one or 65536:1, depending on how you lot define the ratio). Although information technology's perfectly okay to only support maxval <= 255 PPM images for student work, if you get interested in image filters and then on, using the extra bits and chaining your filter programs makes for really powerful imaging tools. And then, please don't just assume the six-graphic symbol color format is never used.


  7. #vii

    WoodSTokk is offline

    Registered User


    This is my attempt to read the header of an PBM/PGM/PPM.

    Code:

    #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <cord.h>  #define MAX_LEN 1024 #define PPM_DELIM "\r\north\t "  typedef struct ppm_t {     uint8_t magic;     uint16_t width;     uint16_t elevation;     uint16_t brightness;     void *data; } ppm;  int parseHeader(ppm *picture, FILE *input) {      char line[MAX_LEN] = {0}, *char_tmp;     int ppm_magic = -1, ppm_width = -1, ppm_height = -ane, ppm_brightness = -1, ppm_header = 1;      while(ppm_header) {          fgets(line, MAX_LEN, input);  //bank check for comments         if (line[0] == '#') continue;          char_tmp = strtok(line, PPM_DELIM);         while (char_tmp) {  // get PPM format             if(ppm_magic < 0) {                 if(char_tmp[0] == 'P') {                     if ((sscanf(++char_tmp, "%d", &ppm_magic)) != i) {                         fprintf(stderr, "could not read magic number. exit.\north");                         return -1;                     }                     else if(ppm_magic < 1 || ppm_magic > 6) {                         fprintf(stderr, "invalid magic number. get out.\n");                         render -1;                     }                 }                 else {                     fprintf(stderr, "no magic number found. is it really a PPM? exit.\n");                     return -1;                 }             }              else { // get width                 if (ppm_width < 0) {                     if ((sscanf(char_tmp, "%d", &ppm_width)) != 1) {                         fprintf(stderr, "could non read width. exit.\n");                         return -1;                     }                 }  // become hight                 else if (ppm_height < 0) {                     if ((sscanf(char_tmp, "%d", &ppm_height)) != 1) {                         fprintf(stderr, "could non read height. exit.\due north");                         render -i;                     }                 }  // get brightness                 else if (ppm_brightness < 0) {                     if ((sscanf(char_tmp, "%d", &ppm_brightness)) != 1) {                         fprintf(stderr, "could not read brightness. get out.\due north");                         return -1;                     }                 }              }             char_tmp = strtok(Cipher, PPM_DELIM);         }         if (ppm_magic > 0 && ppm_width > 0 && ppm_height > 0 && ppm_brightness > 0) ppm_header = 0;     }      picture->magic = ppm_magic;     picture->width = ppm_width;     movie->height = ppm_height;     moving-picture show->effulgence = ppm_brightness;     movie->data = Zip;      return 0; }  int main (int argc, char *argv[]) {      FILE *input = Nil;     ppm my_picture;      if (argc < 2) {         fprintf(stderr, "too few arguments.\n");         fprintf(stderr, "usage: %s <filename>\due north", argv[0]);         return EXIT_FAILURE;     }      if ((input = fopen(argv[1], "r")) == NULL) {         fprintf(stderr, "could non open file '%s'.\n", argv[one]);         return EXIT_FAILURE;     }      if (parseHeader(&my_picture, input) < 0) {         fprintf(stderr, "something went wrong.\n");         return EXIT_FAILURE;     }      printf("--- picture data ---\n");     printf("Format    : %d\n", my_picture.magic);     printf("Width     : %d\n", my_picture.width);     printf("Height    : %d\north", my_picture.height);     printf("Brightness: %d\northward", my_picture.brightness);  [�]
    You can come across i simply use 'fgets()' and 'sscanf()'. Not playing around with 'getc()' and 'ungetc()'.
    Last edited past WoodSTokk; 12-02-2014 at 01:eighteen AM.


  8. #8

    WoodSTokk is offline

    Registered User


    Ooop, an Bitmap have no effulgence.
    BugFix @ line 74:

    Code:

    // bitmap have no brightness                            if (ppm_magic == i || ppm_magic == 4) ppm_brightness = one;


  9. #nine

    Nominal Animal is offline

    Ticked and off


    Quote Originally Posted by WoodSTokk View Post

    Code:

    #define MAX_LEN 1024 #ascertain PPM_DELIM "\r\northward\t "
    Well, actually, at that place is no length limit on the comments, nor practice the comments need to start at the outset of the line. That's why I said the format is slightly funny.

    Your code should exist able to read typical ppm headers -- which typically take the comment immediately after the P6 format specifier --, but the PPM spec is quite a flake more than relaxed.

    The component maximum is likewise not really brightness, but a maximum component value. That is, r=255,thousand=255,b=255 with maxval=255 is just as bright white equally r=forty,g=40,b=40 is with maxval=40.

    Aside from those nitpicks, there'south not much to comment; your code should work fine in real life.

    Quote Originally Posted by WoodSTokk View Post

    You can see i only employ 'fgets()' and 'sscanf()'. Non playing around with 'getc()' and 'ungetc()'.

    Y'all might think using getc() and ungetc() is "playing around", but they're perfectly standard and reliable functions, and in this instance, the getnni() function actually performs the right nonnegative integer parsing and whitespace/annotate handling used in PPM, PGM, and PGM formats, without calculation any arbitrary restrictions like line length limits.

    The funny thing here is not the fashion getnni() is implemented, but the fact that correctly parsing PPM/PGM/PBM files, without arbitrary restrictions, kinda sorta requires a function much like it.


  10. #ten

    WoodSTokk is offline

    Registered User


    Quote Originally Posted past Nominal Brute View Post

    Well, actually, there is no length limit on the comments, nor practise the comments need to start at the beginning of the line. That's why I said the format is slightly funny.

    Your lawmaking should exist able to read typical ppm headers -- which typically accept the comment immediately afterward the P6 format specifier --, simply the PPM spec is quite a scrap more relaxed.

    Oh, i take interpret the spec that a annotate can only be on a line without other thinks.
    But this is unproblematic to ready @ line 31:

    Code:

    // comment fix             if(char_tmp[0] == '#') break;

    Quote Originally Posted by Nominal Fauna View Post

    The component maximum is also non really brightness, just a maximum component value. That is, r=255,g=255,b=255 with maxval=255 is just as bright white as r=40,grand=40,b=40 is with maxval=twoscore.

    I know, information technology should be named 'max_brightness' or 'max_value', but it works.

    Quote Originally Posted by Nominal Beast View Post

    Aside from those nitpicks, there'southward not much to annotate; your code should work fine in real life.

    Thanks

    This code is not perfect, just nowadays idears to bgibs24 to show in that location are other ways to read the header.
    You are right, the line length can be a trouble.

    Other accept classes, we are form


  11. #11

    bgibs24 is offline

    Registered User


    give thanks yous guys so much this all helped a lot


stewartlifivend.blogspot.com

Source: https://cboard.cprogramming.com/c-programming/165123-help-parsing-ppm-c.html

Post a Comment for "C Read Ppm File Header How to Deal With Whitespace"