博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
PGM图片格式与代码
阅读量:4660 次
发布时间:2019-06-09

本文共 5006 字,大约阅读时间需要 16 分钟。

这两天在搞神经网络,里面的一个人脸数据库的图片格式是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 
#include
#include
#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

本文地址:

很多其它资源请关注 博客:  微博:

Refs:

[1]http://netpbm.sourceforge.net/doc/pgm.html

[2]Netpbm format Wikipedia

转载于:https://www.cnblogs.com/cxchanpin/p/6816981.html

你可能感兴趣的文章
centos6(7) minimal 基本环境配置
查看>>
P2837晚餐队列安排
查看>>
DP专题
查看>>
UVa 1402 Runtime Error 伸展树
查看>>
笔记本安装SSD固态硬盘详细的优化设置
查看>>
批处理语法介绍
查看>>
FFmpeg 基础库(三)模块组成
查看>>
Linq 查询 与方法调用
查看>>
iOS开源项目(旧)
查看>>
winform的datagridview控件滚动更新数据
查看>>
java中Object类 源代码详解
查看>>
开源控Meteor的个人资料
查看>>
kafka在zookeeper中的存储结构
查看>>
linux上FTP服务器搭建
查看>>
centos7关闭防火墙
查看>>
《C#高级编程》 读书笔记 -索引
查看>>
session cookie原理及应用
查看>>
ID3算法详解
查看>>
BZOJ1925: [Sdoi2010]地精部落
查看>>
学习进度条第十一周
查看>>