简体   繁体   中英

How do you read pixel data from a PPM (P3) image into a Matrix in C?

I would like a matrix with each row corresponding to a pixel and each column being an RGB value from a PPM P3 image.

I attempted to create a Matrix with [imageWidth * imageHeight] [3] as the size then populate that but it seems to be taking forever. I think I have missed something, can anyone explain where I went wrong or perhaps suggest a better way to do this?

  int  pixels [imageSize] [3];

while(fgets(line,70,fd) != NULL){
  for ( column = 0; column < (imageSize); column++){
    for ( row = 0; row < 1; row++){
      sscanf(line, "%d %d %d", &r, &g, &b );
      pixels [column] [row] = r;
      pixels [column] [row + 1] = g;
      pixels [column] [row + 2] = b;
     }
  }
}

Line refers to the line read in by the fgets function.

The problem is clear in your revised code: you try to read all pixels of the image from each raster line. This won't run forever unless the fgets() blocks indefinitely, but if the raster dimensions are large and the file is organized with many lines of pixels then it may take a very long time. In any case, it's wrong , for on each iteration of the outermost loop -- that is, for each line read -- it overwrites all previously assigned pixel values.

Furthermore, your innermost loop, though not actually wrong, is highly obfuscatory. It always performs exactly one iteration; its iteration variable row in fact indexes pixel components (as opposed to rows of the raster), and row anyway has the value 0 on every iteration. It would be better to just remove it.

Overall, you're making this much harder than it needs to be. The PPM P3 format is designed in a way that makes it amenable to input via much simpler code. Each sample in a valid PPM P3 file is guaranteed to have whitespace before and after. On the other hand, the position and width of the fields and the number of them per line is not fixed. Together, those characteristics makes this one of the comparatively rare cases in which fscanf() is actually a better choice than fgets() + sscanf() . The line length limit makes the latter pretty good too, but you don't need the extra complication that brings.

Given that you want to read imageSize pixels from the FILE designated by fd , with that FILE initially positioned at the first character of the first line of the raster, this will do the trick:

for (pixel = 0; pixel < imageSize; pixel++) {
    int numScanned = fscanf(fd, "%d %d %d",
            &pixels[pixel][0],
            &pixels[pixel][1],
            &pixels[pixel][2]);
    if (numScanned < 3) {
        // ... handle file format or I/O error ...
        break;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM