PGM图片格式与代码
这两天在搞神经网络,里面的一个人脸数据库的图片格式是PGM,事实上之前早就知道了这个图片格式,可是没去深究这个图片格式的数据究竟是什么安排的。搜索了下百度百科,发现介绍的真是简单,以下就自己来系统地整理一下。
PGM是Portable Gray Map的缩写。它是灰度图像格式中一种最简单的格式标准。另外两种与之相近的图片格式是PBM和PPM。它们分别相应着黑白图像和彩色图像。
PGM的数据存放方式相比于JPG来说是非常easy的,由于它不进行数据压缩。自然的PGM的图片的大小也就比較大了。一个120*128 8-bit的灰度图像,PGM的大小是44kb,而将这个图片转化为JPG格式后。大小仅为4kb。
所以。在日常各种网络应用中你是非常难见到PGM图片的,它太浪费流量了。
PGM的数据格式
就像上面说的,PGM是不进行数据压缩的,那么自然的。它的格式就非常直观了。你能够直接用一个记事本打开它,只是记事本打开后换行没了。不好看,以下用Sublime Text2打开:
看了上面的图示,我想大部分都能猜出来一些东西了。
PGM图片的数据:
首先。以一个“Magic Number”来标识图片格式,这个magic number是P2,不能是p2。或者P 2;
然后。第二行是图片宽度、图片高度,在上图中是128和120。
第三行是这个图片数据的最大值。上图中是146;
最后,就是图片的像素数据值了。这些数据是以“row-major order”存放的,即是说按行存放的。当然,你认真看上图的话会发现,从第4行開始,每行都仅仅有16个数据,默认情况下。每行长度不能超过70个字符,可是详细几个并没有要求,一种安全的做法是每行存放一个像素。
在有些PGM图片你可能会看到以#开头的行。这个是comment,比方说用#linjianmin.pgm来表示图片名称。
图片读取与创建代码:
#ifndef _PGM_ #define _PGM_ #include <stdio.h> #include <string.h> #include <stdlib.h> #define ROWS(img) ((img)->rows) #define COLS(img) ((img)->cols) #define NAME(img) ((img)->name) typedef struct { char *name; int rows, cols; int *data; } IMAGE; char *img_basename(char *filename) { char *newM, *part; int len, dex; len = strlen(filename); dex = len - 1; while (dex > -1) { if (filename[dex] == '/') { break; } else { dex--; } } dex++; part = &(filename[dex]); len = strlen(part); newM = (char *) malloc ((unsigned) ((len + 1) * sizeof (char))); strcpy(newM, part); return(newM); } IMAGE *img_alloc() { IMAGE *newM; newM = (IMAGE *) malloc (sizeof (IMAGE)); if (newM == NULL) { printf("IMGALLOC: Couldn't allocate image structure\n"); return (NULL); } newM->rows = 0; newM->cols = 0; newM->name = NULL; newM->data = NULL; return (newM); } IMAGE *img_creat(char *name, int nr, int nc) { int i, j; IMAGE *newM; newM = img_alloc(); newM->data = (int *) malloc ((unsigned) (nr * nc * sizeof(int))); newM->name = img_basename(name); newM->rows = nr; newM->cols = nc; for (i = 0; i < nr; i++) { for (j = 0; j < nc; j++) { img_setpixel(newM, i, j, 0); } } return (newM); } void img_free(IMAGE* img) { if (img->data) free ((char *) img->data); if (img->name) free ((char *) img->name); free ((char *) img); } void img_setpixel(IMAGE *img,int r, int c, int val) { int nc; nc = img->cols; img->data[(r * nc) + c] = val; } int img_getpixel(IMAGE *img, int r, int c) { int nc; nc = img->cols; return (img->data[(r * nc) + c]); } IMAGE *img_open(char *filename) { IMAGE *newM; FILE *pgm; char line[512], intbuf[100], ch; int type, nc, nr, maxval, i, j, k, found; newM = img_alloc(); if ((pgm = fopen(filename, "r")) == NULL) { printf("IMGOPEN: Couldn't open '%s'\n", filename); return(NULL); } newM->name = img_basename(filename); /*** Scan pnm type information, expecting P5 ***/ fgets(line, 511, pgm); sscanf(line, "P%d", &type); if (type != 5 && type != 2) { printf("IMGOPEN: Only handles pgm files (type P5 or P2)\n"); fclose(pgm); return(NULL); } /*** Get dimensions of pgm ***/ fgets(line, 511, pgm); sscanf(line, "%d %d", &nc, &nr); newM->rows = nr; newM->cols = nc; /*** Get maxval ***/ fgets(line, 511, pgm); sscanf(line, "%d", &maxval); if (maxval > 255) { printf("IMGOPEN: Only handles pgm files of 8 bits or less\n"); fclose(pgm); return(NULL); } newM->data = (int *) malloc ((unsigned) (nr * nc * sizeof(int))); if (newM->data == NULL) { printf("IMGOPEN: Couldn't allocate space for image data\n"); fclose(pgm); return(NULL); } if (type == 5) { for (i = 0; i < nr; i++) { for (j = 0; j < nc; j++) { img_setpixel(newM, i, j, fgetc(pgm)); } } } else if (type == 2) { for (i = 0; i < nr; i++) { for (j = 0; j < nc; j++) { k = 0; found = 0; while (!found) { ch = (char) fgetc(pgm); if (ch >= '0' && ch <= '9') { intbuf[k] = ch; k++; } else { if (k != 0) { intbuf[k] = '\0'; found = 1; } } } img_setpixel(newM, i, j, atoi(intbuf)); } } } else { printf("IMGOPEN: Fatal impossible error\n"); fclose(pgm); return (NULL); } fclose(pgm); return (newM); } int img_write(IMAGE *img, char *filename) { int i, j, nr, nc, k, val; FILE *iop; nr = img->rows; nc = img->cols; iop = fopen(filename, "w"); fprintf(iop, "P2\n"); fprintf(iop, "%d %d\n", nc, nr); fprintf(iop, "255\n"); k = 1; for (i = 0; i < nr; i++) { for (j = 0; j < nc; j++) { val = img_getpixel(img, i, j); if ((val < 0) || (val > 255)) { printf("IMG_WRITE: Found value %d at row %d col %d\n", val, i, j); printf(" Setting it to zero\n"); val = 0; } if (k % 10) { fprintf(iop, "%d ", val); } else { fprintf(iop, "%d\n", val); } k++; } } fprintf(iop, "\n"); fclose(iop); return (1); } #endif
本文地址:http://blog.csdn.net/linj_m/article/details/40477699
很多其它资源请关注 博客:LinJM-机器视觉 微博:林建民-机器视觉
Refs:
[1]http://netpbm.sourceforge.net/doc/pgm.html
[2]Netpbm format Wikipedia