画像処理入門

~画像(Bitmap)の入出力(2)~

―――――――――――――――――――――――――――――――――

画像処理のために最初にすること、画像の読み込みと書き込みについてです。

HOME | 前へ | 次へ

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

ここではカラーBitmap画像を読み込み、モノクロに変換後にBitmap画像を出力するプログラムを紹介します。

 

  ↓

 

     Visual Studio 2008にて開発しています。

stdafx.hのインクルード、main関数の引数など、ご自分の開発環境に合わせてご利用ください。

 

 

 

#include "stdafx.h"

#include <stdlib.h>

 

//ファイルヘッダーの構造体

typedef struct  {

  char                          bfType[2];              //2 byte -> データのタイプ

  int                           bfSize;                 //4 byte -> ファイルのサイズ

  short int                     bfReserved1;            //2 byte -> 予約

  short int                     bfReserved2;            //2 byte -> 予約

  int                           bfOffBits;              //4 byte -> 画像データ間でのオフセット

} BmpFileHeader;

 

//情報ヘッダーの構造体

typedef struct {

    int                         biSize;                 //4 byte -> 情報ヘッダーのサイズ

    int                         biWidth;                //4 byte -> 画像の横幅

    int                         biHeight;               //4 byte -> 画像の縦幅

    short int                   biPlanes;               //2 byte

    short int                   biBitCount;             //2 byte -> 1 pixelのサイズ

    int                         biCompression;          //4 byte

    int                         biSizeImage;            //4 byte

    int                         biXPixPerMeter;         //4 byte

    int                         biYPixPerMeter;         //4 byte

    int                         biClrUsed;              //4 byte

    int                         biClrImporant//4 byte

} BmpInfoHeader;

 

//Bitmapの構造体

typedef struct {

        unsigned char   **r;    //赤成分

        unsigned char   **g;    //緑成分

        unsigned char   **b;    //青成分

        int             width;

        int             height;

} BmpImg;

 

//動的メモリの確保

unsigned char **memory2Duc(int x_size, int y_size)

{

    int i// 制御変数

    unsigned char **tmp;

  

    if((tmp = (unsigned char **) calloc(x_size, sizeof(unsigned char *))) == NULL) {

                fprintf(stderr,"Err memory2Duc\n");

                exit(1);

        }

 

    for(i = 0; i < x_size; i++)

        if((tmp[i] = (unsigned char *) calloc(y_size, sizeof(unsigned char))) == NULL) {

                fprintf(stderr,"Err memory2Duc\n");

                exit(1);

                }

    return tmp;

}

//動的メモリの開放

void Free2Duc(unsigned char **tmp,int col)

{

        int i;

        for(i=0;i<col;i++)

                free(tmp[i]);

        free(tmp);

}

 

//Bitmapの読み込み

BmpImg BmpRead(char *fname)

{      

        BmpImg img;

        int x,y;

        unsigned char **r,**g,**b;

        FILE *fp=NULL;

        BmpFileHeader filehead;

        BmpInfoHeader infohead;

       

 

        //ビットマップファイルオープン

        fp = fopen(fname,"rb");

        if(fp==NULL){

                fprintf(stderr,"can not open : %s\n",fname);

                exit(1);

        }

 

        //ファイルヘッダ読み込み

        fread(&filehead.bfType,2,1,fp);

        fread(&filehead.bfSize,4,1,fp);

        fread(&filehead.bfReserved1,2,1,fp);

        fread(&filehead.bfReserved2,2,1,fp);

        fread(&filehead.bfOffBits,4,1,fp);

 

        //Bitmapでなければ終了

        if(filehead.bfType[0]!='B' || filehead.bfType[1]!='M')

        {

                fprintf(stderr,"This file is not bitmap format.\n");

                exit(2);

        }

 

        //情報ヘッダ読み込み

        fread(&infohead.biSize,4,1,fp);

        fread(&infohead.biWidth,4,1,fp);

        fread(&infohead.biHeight,4,1,fp);

        fread(&infohead.biPlanes,2,1,fp);

        fread(&infohead.biBitCount,2,1,fp);

        fread(&infohead.biCompression,4,1,fp);

        fread(&infohead.biSizeImage,4,1,fp);

        fread(&infohead.biXPixPerMeter,4,1,fp);

        fread(&infohead.biYPixPerMeter,4,1,fp);

        fread(&infohead.biClrUsed,4,1,fp);

        fread(&infohead.biClrImporant,4,1,fp);

 

        //24bitでなければ終了

        if(infohead.biBitCount!=24)

        {

                fprintf(stderr,"This file is not 24 bit-bitmap format.\n");

                exit(2);

        }

 

        //配列を準備する

        r = memory2Duc(infohead.biHeight, infohead.biWidth);

        g = memory2Duc(infohead.biHeight, infohead.biWidth);

        b = memory2Duc(infohead.biHeight, infohead.biWidth);

 

        //配列に画像データを格納する

        for(y=infohead.biHeight-1; y>=0; y--)

        {

                for(x=0; x<infohead.biWidth; x++)

                {

                        fread(&b[y][x],1,1,fp);

                        fread(&g[y][x],1,1,fp);

                        fread(&r[y][x],1,1,fp);

                }

                fseek( fp, infohead.biWidth%4, SEEK_CUR);

        }

 

        //BmpImgへのデータの格納

        img.r = r;

        img.g = g;

        img.b = b;

        img.width = infohead.biWidth;

        img.height = infohead.biHeight;

 

        fclose(fp);

 

        //BmpImgデータを返す

        return img;

}

 

//Bitmapの書き込み

void BmpWrite(char *fname, BmpImg img)

{      

        int i,x,y;

        FILE *fp = NULL;

        BmpFileHeader filehead;

        BmpInfoHeader infohead;

        int linesize;

        int remainder;

        unsigned char zero = 0;

       

 

        remainder = img.width%4;

 

        //ビットマップファイルオープン

        fp = fopen(fname,"wb");

        if(fp==NULL){

                fprintf(stderr,"can not open : %s\n",fname);

                exit(1);

        }

        //ファイルヘッダ書き込み

        filehead.bfType[0] = 'B';

        filehead.bfType[1] = 'M';

        filehead.bfSize = img.height * (img.width * 3+remainder)  + 14 + 40;

        filehead.bfReserved1 = 0;

        filehead.bfReserved2 = 0;

        filehead.bfOffBits = 14 + 40;

 

        fwrite(&filehead.bfType[0],1,1,fp);

        fwrite(&filehead.bfType[1],1,1,fp);

        fwrite(&filehead.bfSize,4,1,fp);

        fwrite(&filehead.bfReserved1,2,1,fp);

        fwrite(&filehead.bfReserved2,2,1,fp);

        fwrite(&filehead.bfOffBits,4,1,fp);

 

 

        //情報ヘッダ書き込み

        infohead.biSize = 40;

        infohead.biWidth = img.width;

        infohead.biHeight = img.height;

        infohead.biPlanes = 1;

        infohead.biBitCount = 24;

        infohead.biCompression = 0;

        infohead.biSizeImage = filehead.bfSize - 54;

        infohead.biXPixPerMeter = 3780;

        infohead.biYPixPerMeter = 3780;

        infohead.biClrUsed = 0;

        infohead.biClrImporant = 0;

 

        fwrite(&infohead.biSize,4,1,fp);

        fwrite(&infohead.biWidth,4,1,fp);

        fwrite(&infohead.biHeight,4,1,fp);

        fwrite(&infohead.biPlanes,2,1,fp);

        fwrite(&infohead.biBitCount,2,1,fp);

        fwrite(&infohead.biCompression,4,1,fp);

        fwrite(&infohead.biSizeImage,4,1,fp);

        fwrite(&infohead.biXPixPerMeter,4,1,fp);

        fwrite(&infohead.biYPixPerMeter,4,1,fp);

        fwrite(&infohead.biClrUsed,4,1,fp);

        fwrite(&infohead.biClrImporant,4,1,fp);

 

 

        //画像データ書き込み

        for(y=img.height-1; y>=0; y--)

        {

                for(x=0; x<img.width; x++)

                {

                        fwrite(&img.b[y][x],1,1,fp);

                        fwrite(&img.g[y][x],1,1,fp);

                        fwrite(&img.r[y][x],1,1,fp);

                }

                for(i=0; i<remainder; i++)

                        fwrite(&zero,1,1,fp);

        }

        fclose(fp);

}

 

 

int _tmain(int argc, _TCHAR* argv[])

{

        int i,j;

        int buf;

        BmpImg img;

 

        //Bitmap読み込み

        img = BmpRead("data.bmp");

 

        //カラー → モノクロ変換処理

        for(i=0;i<img.height;i++)

                for(j=0;j<img.width;j++){

                        buf = (int)(( img.r[i][j] + img.g[i][j] + img.b[i][j] ) / 3.0 );

                        img.r[i][j] = img.g[i][j] = img.b[i][j] = buf;

                }

        //Bitmap書き込み

        BmpWrite("data_mono.bmp",img);

 

        return 0;

}