現在地 >> メニュー >> サンプルコード::OpenCV >> OpenCV::読み込みテスト >> OpenCV::読み込みテスト2

問題


tga画像を読み込む関数を作成し、OpenCVで表示せよ。
(※このwikiはtga画像はアップできないようです)

その他条件:
 未圧縮・RLE圧縮フルカラーの2つに対応していればよい。

答え

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cv.h>
#include <highgui.h>

using namespace std;

/*** [データ構造] ***/
typedef struct
{
unsigned char* imageData;
unsigned int bpp;
unsigned int width;
unsigned int height;
bool RLE_flag;
unsigned int imageSize;
unsigned int color_num;
}TGA_IMG;


char *tgafilename ="image.tga";


/************* [プロトタイプ宣言] *******************/
void LoadTGA(char *filename, TGA_IMG *texture);
void LoadUncompressedTGA(char *filename, FILE *fTGA, TGA_IMG *texture);
void LoadCompressedTGA(char *filename, FILE *fTGA, TGA_IMG *texture);
void SET_TGA_INFOMATION(TGA_IMG *texture,FILE *fTGA);


/**************** [メイン関数] *********************/
int main(int argc, char**argv)
{

TGA_IMG *tga_img;
tga_img = new TGA_IMG();

LoadTGA(tgafilename,tga_img);


IplImage *imgA;
CvSize window_size;

window_size.width = tga_img->width;
window_size.height= tga_img->height;
imgA = cvCreateImage(window_size,IPL_DEPTH_8U,3);
memcpy(imgA->imageData,tga_img->imageData,tga_img->width*tga_img->height*3);


if(tga_img->RLE_flag == true)
{
cvCvtColor(imgA, imgA, CV_RGB2BGR);
}

cvFlip(imgA,NULL,0);

delete [] tga_img->imageData;tga_img->imageData=NULL;
delete tga_img;tga_img=NULL;


cvNamedWindow("load tga image",CV_WINDOW_AUTOSIZE);
cvShowImage("load tga image",imgA);
cvWaitKey(0);
cvReleaseImage( & imgA);
cvDestroyAllWindows();



return 0;
}



/*************** ここから各種関数 ********************/
void LoadTGA(char *filename, TGA_IMG *texture)
{

FILE *fTGA;
fTGA = fopen(filename,"rb");
if(fTGA ==NULL)
{
puts("can't open file");
exit(0);
}

/** 最初の12バイトを読み込む **/
unsigned char tgaheader[12];
if(fread(&tgaheader, sizeof(tgaheader), 1, fTGA) == 0)
{
puts("can't read header");
exit(0);
}



unsigned char uTGAcompare[12] = {0,0, 2,0,0,0,0,0,0,0,0,0};
unsigned char cTGAcompare[12] = {0,0,10,0,0,0,0,0,0,0,0,0};
/** 圧縮か未圧縮かで場合分け **/
if(memcmp(uTGAcompare, &tgaheader, sizeof(tgaheader)) == 0)
{

puts("this file is uncompressed");
LoadUncompressedTGA(filename, fTGA,texture);

}
else if(memcmp(cTGAcompare, &tgaheader, sizeof(tgaheader)) == 0)
{

puts("this file is compressed");
LoadCompressedTGA(filename, fTGA,texture);

}
else
{
puts("wrong!");
}

fclose(fTGA);fTGA=NULL;
}





/**************** [未圧縮TGAの読み込み] *****************/
void LoadUncompressedTGA(char *filename, FILE *fTGA, TGA_IMG *texture)
{

texture->RLE_flag = false;

SET_TGA_INFOMATION(texture,fTGA); //ヘッダ情報取得

/** データ読み込み **/
if(fread(texture->imageData, 1, texture->imageSize, fTGA) != texture->imageSize)
{
puts("Error could not read image data");
fclose(fTGA);fTGA = NULL;
delete [] texture->imageData; texture->imageData =NULL;
exit(0);
}

}


/************ [RLE圧縮TGAの読み込み] *****************/
void LoadCompressedTGA(char *filename, FILE *fTGA, TGA_IMG *texture)
{

texture->RLE_flag = true;

SET_TGA_INFOMATION(texture,fTGA); //ヘッダ情報取得


/***** ここからデータ読み込み *******/
unsigned int pixelcount = texture->width * texture->height;//総ピクセル数
unsigned int currentpixel = 0;
unsigned int currentbyte = 0;
unsigned char* colorbuffer = new unsigned char[texture->color_num]; //1ピクセル分のメモリ確保


do
{
/** cunk headerを読む **/
unsigned char chunkheader = 0;
if(fread(&chunkheader, sizeof(unsigned char), 1, fTGA) == 0)
{
puts("wrong chunk");
fclose(fTGA);fTGA = NULL;
delete [] colorbuffer; colorbuffer = NULL;
delete [] texture->imageData; texture->imageData =NULL;
exit(0);
}

if(chunkheader < 128) //生データの場合
{

short counter;
chunkheader++;

for(counter = 0; counter < chunkheader; counter++) //(chunkheader)個分の生データを読む
{

if(fread(colorbuffer, 1, texture->color_num, fTGA) != texture->color_num)
{
puts("Error could not read image data");
fclose(fTGA);fTGA = NULL;
delete [] colorbuffer; colorbuffer = NULL;
delete [] texture->imageData; texture->imageData =NULL;
exit(0);
}


texture->imageData[currentbyte] = colorbuffer[2]; //red
texture->imageData[currentbyte + 1] = colorbuffer[1]; //green
texture->imageData[currentbyte + 2] = colorbuffer[0]; //blue
if(texture->color_num == 4)
{
texture->imageData[currentbyte + 3] = colorbuffer[3]; //alpha
}

currentbyte += texture->color_num;
currentpixel++;
if(currentpixel > pixelcount) //総ピクセル数より多く読みこんだらエラー
{
puts("Error too many pixels read");
fclose(fTGA);fTGA = NULL;
delete [] colorbuffer; colorbuffer = NULL;
delete [] texture->imageData; texture->imageData =NULL;
exit(0);
}
}

}else /******** [以降は、RLE圧縮データ部分] ***********/
{

short counter;
chunkheader -= 127;
if(fread(colorbuffer, 1, texture->color_num, fTGA) != texture->color_num)
{
printf("Error could not read from file");
fclose(fTGA);fTGA = NULL;
delete [] colorbuffer; colorbuffer = NULL;
delete [] texture->imageData; texture->imageData =NULL;
exit(0);
}

for(counter = 0; counter < chunkheader; counter++)
{
texture->imageData[currentbyte ] = colorbuffer[2];
texture->imageData[currentbyte + 1 ] = colorbuffer[1];
texture->imageData[currentbyte + 2 ] = colorbuffer[0];
if(texture->color_num == 4)
{
texture->imageData[currentbyte + 3] = colorbuffer[3];
}

currentbyte += texture->color_num;
currentpixel++;
if(currentpixel > pixelcount)
{
puts("Error too many pixels read");
fclose(fTGA);fTGA = NULL;
delete [] colorbuffer; colorbuffer = NULL;
delete [] texture->imageData; texture->imageData =NULL;
exit(0);
}

}//圧縮forループ終わり


}//未圧縮 or RLE圧縮 のif文の分岐終わり



}while(currentpixel < pixelcount); //全部のピクセルを回るまでループする

delete [] colorbuffer;colorbuffer = NULL;

}



/********** [ヘッダ情報を取得] **********************/
void SET_TGA_INFOMATION(TGA_IMG *texture,FILE *fTGA)
{

unsigned char tmp_headear[6];
if(fread(tmp_headear, sizeof(tmp_headear), 1, fTGA) == 0)//次の6バイトを読む
{
puts("can't read next header");
exit(0);
}


texture->width = tmp_headear[1] * 256 + tmp_headear[0];//幅
texture->height = tmp_headear[3] * 256 + tmp_headear[2];//高さ
texture->bpp = tmp_headear[4]; //24 or 32 bit
/** エラーチェック **/
if*1
{
puts("Wrong Data");
fclose(fTGA);fTGA = NULL;
exit(0);
}




/** 画像データ用のメモリ確保 **/
texture->color_num = (texture->bpp / 8);//色数(3 or 4)
texture->imageSize = (texture->color_num * texture->width * texture->height);
texture->imageData = new unsigned char[texture->imageSize];
if(texture->imageData == NULL)
{
puts("sorry can't get memory");
fclose(fTGA);fTGA = NULL;
delete [] texture->imageData; texture->imageData =NULL;
exit(0);
}
}

目次

― その他 ―

Wiki内検索

計測中...(07.10.8〜)

Save The World






▲よろしければ広告のクリックもお願いします


▲ランキングに参加しました

管理人/副管理人のみ編集できます