PPM Image Parse
PPM image parser
References: https://netpbm.sourceforge.net/doc/ppm.html
Example format
code snippet start
P3
# feep.ppm
4 4
15
0 0 0 0 0 0 0 0 0 15 0 15
0 0 0 0 15 7 0 0 0 0 0 0
0 0 0 0 0 0 0 15 7 0 0 0
15 0 15 0 0 0 0 0 0 0 0 0
code snippet end
P3 is identifier it can be P3 or P6. Just like version Number
4 4 is the image width and height
15 is the maximum color depth for each RGB. For morden PC, it should be 255 now.
Other below are the RGB value split by space
code snippet start
0 0 0 0 0 0 0 0 0 15 0 15
code snippet end
For example there have a four pixel, first three all the zero means all the black. Last is 15 0 15 -> Red is 15, Green is 0 and Blue is 15.
We can use GIMP to export the jpg and png normal image into ppm format.
Use xxd to check the binary:
code snippet start
> ~/ $ xxd bafff.ppm | head
00000000: 5036 0a23 2043 7265 6174 6564 2062 7920 P6.# Created by
00000010: 4749 4d50 2076 6572 7369 6f6e 2033 2e30 GIMP version 3.0
00000020: 2e36 2050 4e4d 2070 6c75 672d 696e 0a32 .6 PNM plug-in.2
00000030: 3132 2032 3337 0a32 3535 0a26 2626 2626 12 237.255.&&&&&
00000040: 2626 2626 2626 2626 2626 2626 2626 2626 &&&&&&&&&&&&&&&&
00000050: 2626 2627 2727 2727 2727 2727 2727 2727 &&&'''''''''''''
00000060: 2727 2727 2727 2727 2727 2728 2828 2929 '''''''''''((())
00000070: 2929 2929 2929 292a 2a2a 2a2a 2a2b 2b2b )))))))******+++
00000080: 2b2b 2b28 2828 2929 2929 2929 2929 292a +++((()))))))))*
00000090: 2a2a 2a2a 2a2b 2b2b 2b2b 2b2b 2b2b 2b2b *****+++++++++++
code snippet end
Simple ppm parser using SDL:
c code snippet start
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <SDL2/SDL.h>
#include <string.h>
int main(void) {
FILE *in = stdin;
char *pt = malloc(1024);
char identifier[1024];
int width = 0;
int height = 0;
int depth = 0;
fgets(pt, 1024, in);
sscanf(pt, "%s\n", identifier);
// Lazy format check
if (!(strcmp(identifier, "P3") == 0 || strcmp(identifier, "P6") == 0)) {
printf("The ppm image format is not valid.\n");
return 0;
}
printf("Magic Number: %s\n", identifier);
// Skip the comment line
fgets(pt, 1024, in);
// Get the height and width
fgets(pt, 1024, in);
sscanf(pt, "%d %d\n", &width, &height);
fgets(pt, 1024, in);
sscanf(pt, "%d\n", &depth);
free(pt);
// INFO
printf("Color depth: %d\n", depth);
printf("Image Heigh: %d\n", height);
printf("Image Width: %d\n", width);
SDL_Window *window = SDL_CreateWindow("ppm Image viewer", SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, width, height, 0);
SDL_Surface *surface = SDL_GetWindowSurface(window);
SDL_FillRect(surface, NULL, 0xFF0000FF);
Uint32 color = 0;
SDL_Rect pixel = (SDL_Rect) { 0, 0, 1, 1};
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
Uint8 r, g, b;
r = (char) getchar();
g = (char) getchar();
b = (char) getchar();
color = SDL_MapRGB(surface->format, r, g, b);
pixel.x = x;
pixel.y = y;
SDL_FillRect(surface, &pixel, color);
}
}
SDL_UpdateWindowSurface(window);
int is_running = 1;
while (is_running) {
SDL_Event event;
SDL_PollEvent(&event);
switch (event.type) {
case SDL_QUIT:
is_running = 0;
break;
case SDL_KEYDOWN:
if (event.key.keysym.sym == SDLK_ESCAPE) {
is_running = 0;
SDL_DestroyWindow(window);
SDL_Quit();
}
break;
}
}
return 0;
}c code snippet end