PGM圖片格式與代碼

這兩天在搞神經網絡,裏面的一我的臉數據庫的圖片格式是PGM,事實上以前早就知道了這個圖片格式,但是沒去深究這個圖片格式的數據到底是什麼安排的。搜索了下百度百科,發現介紹的真是簡單,如下就本身來系統地整理一下。                html

Jeremy Lin 數據庫

PGM是Portable Gray Map的縮寫。它是灰度圖像格式中一種最簡單的格式標準。另外兩種與之相近的圖片格式是PBM和PPM。它們分別相應着黑白圖像和彩色圖像。安全

PGM的數據存放方式相比於JPG來講是很是easy的,因爲它不進行數據壓縮。天然的PGM的圖片的大小也就比較大了。一個120*128 8-bit的灰度圖像,PGM的大小是44kb,而將這個圖片轉化爲JPG格式後。大小僅爲4kb。網絡

因此。在平常各類網絡應用中你是很是難見到PGM圖片的,它太浪費流量了。less


PGM的數據格式spa

就像上面說的,PGM是不進行數據壓縮的,那麼天然的。它的格式就很是直觀了。你可以直接用一個記事本打開它,只是記事本打開後換行沒了。很差看,如下用Sublime Text2打開:.net


看了上面的圖示,我想大部分都能猜出來一些東西了。code

PGM圖片的數據orm

首先。以一個「Magic Number」來標識圖片格式,這個magic number是P2,不能是p2。或者P 2;htm

而後。第二行是圖片寬度、圖片高度,在上圖中是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

相關文章
相關標籤/搜索