C Read Ppm File Header How to Deal With Whitespace
-
11-xxx-2014 #one
Registered User
Assist parsing ppm in C
-
11-30-2014 #two
Registered User
Definitely post the code not the screenshot of the code, I can barely see something.
-
11-thirty-2014 #3
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); } }
-
12-01-2014 #4
Registered User
Everyone? I just need aid figuring out why the image wont load. Am i using my getc functions right?
-
12-01-2014 #5
and the hat of int overfl
> 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().
-
12-01-2014 #6
Ticked and off
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():
Originally Posted by Salem
Using the in a higher place, you can read and verify a PPM prototype header thus: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; }
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.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 <= 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 width�tiptop 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.
-
12-02-2014 #vii
Registered User
This is my attempt to read the header of an PBM/PGM/PPM.
You can come across i simply use 'fgets()' and 'sscanf()'. Not playing around with 'getc()' and 'ungetc()'.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); [�]Last edited past WoodSTokk; 12-02-2014 at 01:eighteen AM.
-
12-02-2014 #8
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;
-
12-02-2014 #nine
Ticked and off
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.
Originally Posted by WoodSTokk
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.
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.
Originally Posted by WoodSTokk
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.
-
12-02-2014 #ten
Registered User
Oh, i take interpret the spec that a annotate can only be on a line without other thinks.
Originally Posted past Nominal Brute
But this is unproblematic to ready @ line 31:
Code:
// comment fix if(char_tmp[0] == '#') break;
I know, information technology should be named 'max_brightness' or 'max_value', but it works.
Originally Posted by Nominal Fauna
Thanks
Originally Posted by Nominal Beast
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
-
12-02-2014 #11
Registered User
give thanks yous guys so much this all helped a lot
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"