バイナリデータを画像に変換

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
黒い影
記事: 5
登録日時: 11年前

バイナリデータを画像に変換

#1

投稿記事 by 黒い影 » 11年前

現在ppmという拡張子のファイル(画像)をbmpまたはjpegに変換するプログラムを作成しています。
開発環境は、Borland C++ compilerを用いて、Cpadでコードを書いています。

ppmファイルから画像のサイズ等は取得でき、
画像部分のデータも文字の3次元配列として取得できたのですが、
それから画像を生成する方法がわかりません。

c#で書いたときはsetPxcelでできましたが、
c++での方法がわかりません。

使用するAPI等を教えていただけるとありがたいです。

以下現在のコードです。

コード:

#include <iostream>
#include <cstdio>
#include <fstream>
#include <string>
#include <cstdio>

#define sscanf_s sscanf
#define buffer line

using namespace std;

int main(void) 
{
    int x, y, color;
 
    std::ifstream file;
    
	// 画像格納配列
    static unsigned char image[1050][1050][3];
	
    // 読み込んだ画像の解像度
    int width = 0;
    int height = 0;
	
    // 読み込んだ画像の諧調数
    int max_gray = 0;
 
    // 画像のpath
    const char* name = "test.ppm";
 
   file.open(name,file.in | file.binary);
 
    // 画像の形式の取得
    std::string line;
    getline(file, line);
 
    // 画像の解像度の取得
    while ( width == 0 || height == 0 )
	{
        std::string line;
        std::getline(file, line);
		
        //コメント行を飛ばす
        if ( line.at(0) != '#' ) 
		{
            sscanf_s( line.c_str(), "%d %d", &width, &height );
        }
    }
 
    // 画像の諧調数の取得
    while (max_gray == 0)
	{
        std::string line;
        std::getline(file, line);
        if ( buffer[0] != '#' )
		{
            sscanf_s( line.c_str(), "%d", &max_gray );
        }
    }
 
    // 画像データの取得
    for(y=0; y<height; y++)
	{
        for(x=0; x<width; x++)
		{
            for(color=0; color<3; color++)
			{
                file.read(reinterpret_cast<char*>(&image[x][y][color]), 1);
            }
        }
    }
 
    printf("line = %s\n",line.c_str());
    printf("width = %d, height = %d\n",width, height);
    printf("max_gray = %d\n", max_gray);
    puts("image data:");
    for(y=0;y<height;y++) 
	{
        for(x=0;x<width;x++) 
		{
            for(color=0;color<3;color++) 
			{
				if(x+1==width && color+1==3)
				{
					printf("%3d\n", image[x][y][color]);
				}
				else
				{
					printf("%3d ", image[x][y][color]);
				}
            }
        }
    }
    return 0;
}

アバター
h2so5
副管理人
記事: 2212
登録日時: 14年前
住所: 東京
連絡を取る:

Re: バイナリデータを画像に変換

#2

投稿記事 by h2so5 » 11年前

C++に画像出力用のAPIは標準で存在しないので出力コードを自作するか外部ライブラリを使う必要があります。

黒い影
記事: 5
登録日時: 11年前

Re: バイナリデータを画像に変換

#3

投稿記事 by 黒い影 » 11年前

h2so5 さんが書きました:C++に画像出力用のAPIは標準で存在しないので出力コードを自作するか外部ライブラリを使う必要があります。
h2so5さん、返信ありがとうございます。
openCVを用いればできるでしょうか?
openCVは今まで使ったことがないので、もしopenCVで可能ならば、
そちらについて少しでもご教授いただけるとありがたいです。

アバター
h2so5
副管理人
記事: 2212
登録日時: 14年前
住所: 東京
連絡を取る:

Re: バイナリデータを画像に変換

#4

投稿記事 by h2so5 » 11年前

OpenCVでも可能です。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: バイナリデータを画像に変換

#5

投稿記事 by softya(ソフト屋) » 11年前

Libjpegや、WindowsならGDI+とか、bmpなら全部自分でバイナリ出力しても良いですし手はいくらでもあります。
課題なら何らかの制限があるはずですけどね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

黒い影
記事: 5
登録日時: 11年前

Re: バイナリデータを画像に変換

#6

投稿記事 by 黒い影 » 11年前

h2so5さん、ソフト屋さんありがとうございます。
これは、課題ではなく、部内の活動で使うのですが、周りにC/C++使いがあまりいなくて...

とりあえず、bmpで頑張ってみます!

黒い影
記事: 5
登録日時: 11年前

Re: バイナリデータを画像に変換

#7

投稿記事 by 黒い影 » 11年前

掲示板の過去ログをもとにして作ることができました。
以下コードです。
(ごちゃごちゃして、読みにくくすみません)

コード:

#include <iostream>
#include <cstdio>
#include <fstream>
#include <string>
#include <cstdio>
#include <windows.h>

#define sscanf_s sscanf
#define buffer line

using namespace std;

struct imageFile
{
	int width, height;
};
 
struct RGB
{
    BYTE red, green, blue;
};

imageFile ppmRead(const char *FileName);
void  bmpCreate(const char *FileName, imageFile ppm);

void InitBitmapFileHeader(BITMAPFILEHEADER *fileHeader, int width, int height);
void InitBitmapInfoHeader(BITMAPINFOHEADER *infoHeader, int width, int height);
void InitBitmapHeader(BITMAPFILEHEADER *fileHeader, BITMAPINFOHEADER *infoHeader, int width, int height);
void WriteBitmapHeader(FILE *fp, BITMAPFILEHEADER fileHeader, BITMAPINFOHEADER infoHeader);
void WriteBitmapLine(FILE *fp, imageFile ppm);

//画像データ
RGB images[1050][1050];
int main(void) 
{
	imageFile ppm;
	
	//ppm読み込み
	ppm = ppmRead("test.ppm");
	
	bmpCreate("test.bmp", ppm);
	
    return 0;
}

imageFile ppmRead(const char *FileName)
{
	int x, y, color;
 
    ifstream file;
	
    // 読み込んだ画像の解像度
    int width = 0;
    int height = 0;
	
	imageFile ppm;
	
    // 読み込んだ画像の諧調数
    int max_gray = 0;
 
    file.open(FileName ,file.in | file.binary);
 
    // 画像の形式の取得
    string line;
    getline(file, line);
 
    // 画像の解像度の取得
    while ( width == 0 || height == 0 )
	{
        string line;
        getline(file, line);
		
        //コメント行を飛ばす
        if ( line.at(0) != '#' ) 
		{
            sscanf_s( line.c_str(), "%d %d", &width, &height );
        }
    }
	
	ppm.width = width;
	ppm.height = height;
 
    // 画像の諧調数の取得
    while (max_gray == 0)
	{
        std::string line;
        std::getline(file, line);
        if ( buffer[0] != '#' )
		{
            sscanf_s( line.c_str(), "%d", &max_gray );
        }
    }
 
    // 画像データの取得
    for(y=0; y<height; y++)
	{
        for(x=0; x<width; x++)
		{
			file.read(reinterpret_cast<char*>(&images[x][y].red),   1);
        	file.read(reinterpret_cast<char*>(&images[x][y].green), 1);
			file.read(reinterpret_cast<char*>(&images[x][y].blue),  1);
		}
    }
/*
	printf("line = %s\n",line.c_str());
    printf("width = %d, height = %d\n",width, height);
    printf("max_gray = %d\n", max_gray);
    puts("image data (press key):");
	getchar();
    for(y=0;y<height;y++) 
	{
        for(x=0;x<width;x++) 
		{
			if(x+1==width)
			{
				printf("%3d %3d %3d\n", images[x][y].red, images[x][y].green, images[x][y].red);
			}
			else
			{
				printf("%3d %3d %3d ", images[x][y].red, images[x][y].green, images[x][y].red);
			}
        }
    }
	*/
	return ppm;
}

//BMPファイルに書き出す
void  bmpCreate(const char *FileName, imageFile ppm)
{
	BITMAPFILEHEADER fileHeader;
    BITMAPINFOHEADER infoHeader;
	
    FILE *fp = fopen(FileName, "wb");
 	imageFile FileData = ppm;
 	
    InitBitmapHeader(&fileHeader, &infoHeader, FileData.width, FileData.height); // ヘッダを作成
	
    WriteBitmapHeader(fp, fileHeader, infoHeader); // ヘッダを出力
 	
	WriteBitmapLine(fp, FileData);
	
    fclose(fp);
}

//BITMAPFILEHEADERを引数に従って初期化
void InitBitmapFileHeader(BITMAPFILEHEADER *fileHeader, int width, int height)
{
    int headerSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); // BITMAPINFOHEADERと共に使用されることを前提
 
    fileHeader->bfType      = 'B' + 'M' * 0x100;
    fileHeader->bfSize      = width * height * 3 + headerSize;
    fileHeader->bfReserved1 = fileHeader->bfReserved2 = 0;
    fileHeader->bfOffBits   = headerSize;
}
 
//BITMAPINFOHEADERを引数に従って初期化
void InitBitmapInfoHeader(BITMAPINFOHEADER *infoHeader, int width, int height)
{
    memset(infoHeader, 0, sizeof(BITMAPINFOHEADER));
    infoHeader->biSize              = 40;
    infoHeader->biWidth             = width;
    infoHeader->biHeight            = height;
    infoHeader->biPlanes            = 1;
    infoHeader->biBitCount          = 32; // true color(4byte)
}
 
//BITMAPFILEHEADERとBITMAPINFOHEADERを引数に従って初期化
void InitBitmapHeader(BITMAPFILEHEADER *fileHeader, BITMAPINFOHEADER *infoHeader, int width, int height)
{
    InitBitmapFileHeader(fileHeader, width, height);
    InitBitmapInfoHeader(infoHeader, width, height);
}
 
//ビットマップヘッダをファイルに書き出す
void WriteBitmapHeader(FILE *fp, BITMAPFILEHEADER fileHeader, BITMAPINFOHEADER infoHeader)
{
    fwrite(&fileHeader, sizeof(BITMAPFILEHEADER), 1, fp);
    fwrite(&infoHeader, sizeof(BITMAPINFOHEADER), 1, fp);
}

//RGBデータをファイルに出力
void WriteBitmapLine(FILE *fp, imageFile ppm)
{
    BYTE padding = 0;
 
    for (int y = 0; y < ppm.height; y++)
    {
		for (int x = 0; x < ppm.width; x++)
		{
        	fwrite(&images[x][y].blue,  sizeof(BYTE), 1, fp);
        	fwrite(&images[x][y].green, sizeof(BYTE), 1, fp);
        	fwrite(&images[x][y].red,   sizeof(BYTE), 1, fp);
        	fwrite(&padding,      sizeof(BYTE), 1, fp);
		}
	}
}

黒い影
記事: 5
登録日時: 11年前

Re: バイナリデータを画像に変換

#8

投稿記事 by 黒い影 » 11年前

解決忘れてました

閉鎖

“C言語何でも質問掲示板” へ戻る