Chinaunix首页 | 论坛 | 博客
  • 博客访问: 468523
  • 博文数量: 150
  • 博客积分: 2706
  • 博客等级: 少校
  • 技术积分: 1200
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-09 11:41
文章分类

全部博文(150)

文章存档

2012年(7)

2011年(6)

2010年(68)

2009年(69)

我的朋友

分类:

2010-02-01 12:09:59

PGM文件格式

PGM----Portable Graymap Format.
pgm格式是灰度文件格式的最低标准.

PGM文件的格式定义如下:
一个PGM文件由一个或多个PGM图象组成. 在多副图象之间,之前或之后没有任何数据存在. 每一个PGM 图像由以下部分组成:

- 一个"magic number",它是用来标定文件格式的. pgm的magic number是"P5".
- 空白区域(空格,TAB,回车,换行)
- 图象宽, 十进制ASCII码
- 空白区域
- 图象高, 十进制ASCII码
- 空白区域
- 最大灰度值(Maxval), 十进制ASCII码.必须小于65536
- 新一行或另一个空白区域符
- 空栅化的一副宽*高的灰度值图象. 每个灰度值取值是从0到Maxval, 0表示黑,而Maxval表示白.每个灰度值用1-2个字节表示.如果
     Maxval小于256,那行就是一个字节,否则为两个字节.最大字节(most significant byte)开始
- 每个灰度值是表示当前象素值在CIE Rec.709伽马校正之后的密度值. 
- 一个很普遍的PGM格式替代格式就是线性灰度值(不经过伽马校正), pnmgamma以这样的一个pgm文件为输入,输出一个标准的pgm文件
- #符号之后的一行为注释行,会被省略.
- 每个象素的光栅值表示为一个十进制ASCII码值.
- 每个象素的光栅值前后各有一个空格. 这样两个象素之间将有大于等于1个空格.
- 每行不超过70个字.

PGM文件示例:

P5
24 7
15
0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0
0    3    3    3    3    0    0    7    7    7    7    0    0   11   11   11   11    0    0   15   15   15   15    0
0    3    0    0    0    0    0    7    0    0    0    0    0   11    0    0    0    0    0   15    0    0   15    0
0    3    3    3    0    0    0    7    7    7    0    0    0   11   11   11    0    0    0   15   15   15   15    0
0    3    0    0    0    0    0    7    0    0    0    0    0   11    0    0    0    0    0   15    0    0    0    0
0    3    0    0    0    0    0    7    7    7    7    0    0   11   11   11   11    0    0   15    0    0    0    0
0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0    0
下面是一个读取PGM文件并存储为BMP文件的程序:
// PGM2BMP.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include
#include
#include
using namespace std;
class CPGMFile
{
private:
 string m_sFileName;
 int m_nWidth,m_nHeight;
 BYTE *m_bPData;
 int m_nMaxValue;
public:
 CPGMFile(const string &fileName):m_sFileName(fileName),m_nWidth(0),m_nHeight(0),m_bPData(0),m_nMaxValue(0)
 {
 }
 ~CPGMFile()
 {
  if(m_bPData != 0)
  {
   delete []m_bPData;
   m_bPData = 0;
  }
 }
 bool ReadImage()
 {
  FILE *fp = fopen(m_sFileName.c_str(),"r");
  if(!fp)
  {
   cout<<"open file failed!\n";
   return false;
  }
  const int bufferSize = 256;
  char buffer[bufferSize];
  fgets(buffer,bufferSize,fp);
  if (buffer[0] != 'P' || buffer[1] != '5')//"P5"
  {
   cout<<"This is not a PGM file!\n";
   return false;
  }
  fgets(buffer,bufferSize,fp);
  sscanf(buffer, "%d %d",&m_nWidth,&m_nHeight); //width and height
  
  fgets(buffer,bufferSize,fp);
  sscanf(buffer, "%d",&m_nMaxValue); //max value (In general it is equal to 255)
  m_bPData = new BYTE[m_nWidth*m_nHeight]; //allocate memory for image data
  if(!m_bPData)
  {
   cout<<"allocate memory failed\n";
   return false;
  }
  int count = fread(m_bPData,sizeof(BYTE),m_nWidth*m_nHeight,fp);
  fclose(fp);
  return true;
 }
 void SaveImage(const string &fileName)
 {
  FILE* fp=fopen(fileName.c_str(),"wb");
  if(!fp)
  {
   cout<<"open file failed!\n";
   return ;
  }
  int i,j,num;
  int p = (m_nWidth*3)%4;
  BYTE a0;
  BYTE a1;
  BYTE a2;
  BITMAPFILEHEADER bitmapFileHeader;
  BITMAPINFOHEADER bmpInfoHeaderPtr ;
  bitmapFileHeader.bfType = 0x4D42;
  bitmapFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); // 54
  bitmapFileHeader.bfSize = m_nWidth * m_nHeight + bitmapFileHeader.bfOffBits;
  bitmapFileHeader.bfReserved1 = 0;
  bitmapFileHeader.bfReserved2 = 0;
  bmpInfoHeaderPtr.biSize    = 40;
  bmpInfoHeaderPtr.biWidth   = m_nWidth;
  bmpInfoHeaderPtr.biHeight      = m_nHeight;
  bmpInfoHeaderPtr.biPlanes        = 1;
  bmpInfoHeaderPtr.biBitCount      = 24;
  bmpInfoHeaderPtr.biCompression   = 0;
  bmpInfoHeaderPtr.biSizeImage     = 0;
  bmpInfoHeaderPtr.biXPelsPerMeter = 512; //any digit maybe
  bmpInfoHeaderPtr.biYPelsPerMeter = 512; //any digit maybe
  bmpInfoHeaderPtr.biClrUsed       = 0;
  bmpInfoHeaderPtr.biClrImportant  = 0;
  fwrite((void*) &bitmapFileHeader, 1, sizeof(BITMAPFILEHEADER), fp);
  fwrite((void*) &bmpInfoHeaderPtr, 1, sizeof(BITMAPINFOHEADER), fp);
  for(j=m_nHeight-1;j>=0;j--)
  {
   for(i=0;i   {
    a0 = m_bPData[j*m_nWidth+i];
    a1 = a0;
    a2 = a0;
    fwrite(&a0,1,1,fp);
    fwrite(&a1,1,1,fp);
    fwrite(&a2,1,1,fp);
   }
   if(p!=0)
   {
    for(num=0;num<4-p;num++)
    {
     a0=0;
     fwrite(&a0,1,1,fp);
    }
   }
  }
  fclose(fp);
 }
};
int main(int argc, char* argv[])
{
 CPGMFile pgmFile("lena.pgm");
 if(pgmFile.ReadImage())
 {
  pgmFile.SaveImage("grot.bmp");
 }
 return 0;
}
阅读(1009) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~