JPEG画像ファイルの読み込み(IDGライブラリ使用)

解説


   Independent JPEG Groupが提供しているJPEGライブラリを使用したJPEGファイルの読み込み。

   ライブラリ作成時はライブラリのソースファイルには一切変更を加えずにライブラリをビルドしlibjpeg.libを得る。
   ※ ヘッダーファイルに変更を加えれば「extern "C"」や「XMD_H」の定義、RGBの並び順変更などをライブラリ利用時に行なう必要がなくなる

   読み込んだ画像はCBitmap形式でCJpeg::m_lpcBitmapに保存される。

   グレースケールJPEGファイルなどには未対応。

使用例

//jpgファイルの読込
void	test(void)
{
	CJpeg	cJpeg;

	cJpeg.SimpleOpen("Dscf1998.jpg");
}


extern "C"
{
#define XMD_H				// INT32の再定義エラー防止
#include "Jpeglib.h"
#include "jerror.h"
}

#pragma	comment(lib,"libjpeg.lib")

#include "afxtempl.h"

class CJpeg  
{
public:
	CJpeg();
	virtual ~CJpeg();

	CBitmap*	m_lpcBitmap;

	static	void	_JpegError(j_common_ptr cinfo);

	bool	SimpleOpen(CString strFile);
};

CJpeg::CJpeg()
{
	m_lpcBitmap = new CBitmap;
}

CJpeg::~CJpeg()
{
	if(m_lpcBitmap != NULL)
		delete	m_lpcBitmap;
}

//
//		エラーハンドラ
//
void	CJpeg::_JpegError(j_common_ptr cinfo)
{
	AfxThrowUserException();
}


//
//		Jpegファイルの読込
//
//			※ マーカー情報の読込処理は未インプリメント
//
bool	CJpeg::SimpleOpen(CString strFile)
{
	m_lpcBitmap->DeleteObject();

	int			i;
	int			nJpegLineBytes;			//JPEG1ラインのバイト数
	long		nBmpLineBytes;			//Bitmap1ラインのバイト数

	BYTE*				lpbtBits;
	JSAMPLE*			pSample;
	FILE*				fp;
	BITMAPINFOHEADER	bmih;
	HBITMAP				hBmp;
	JSAMPROW			buffer[1];
	JSAMPLE				tmp;

	jpeg_decompress_struct		cInfo;
	jpeg_error_mgr				jError;

	fp = NULL;
	pSample = NULL;

	TRY
	{
		fp = fopen(strFile,"rb");
		if(fp == NULL)
			return	false;

		cInfo.err = jpeg_std_error(&jError);			//エラーハンドラ設定
		jError.error_exit = _JpegError;					//エラーハンドラ設定

		jpeg_create_decompress(&cInfo);					//
		jpeg_stdio_src(&cInfo,fp);						//読込ファイル設定
		jpeg_read_header(&cInfo,TRUE);					//ヘッダー読込
		jpeg_start_decompress(&cInfo);					//デコードスタート

		//DIBSECTION作成
		bmih.biSize			= sizeof(bmih);
		bmih.biWidth		= cInfo.output_width;
		bmih.biHeight		= cInfo.output_height;
		bmih.biPlanes		= 1;
		bmih.biBitCount		= 24;
		bmih.biCompression	= BI_RGB;
		bmih.biSizeImage	= 0;
		bmih.biXPelsPerMeter= 0;
		bmih.biYPelsPerMeter= 0;
		bmih.biClrUsed		= 0;
		bmih.biClrImportant	= 0;

		hBmp = ::CreateDIBSection(0,(BITMAPINFO*)&bmih,DIB_RGB_COLORS,(VOID**)&lpbtBits,0,0);
		if(hBmp == NULL)
		{
			jpeg_destroy_decompress(&cInfo);
			return	false;
		}

		nJpegLineBytes = cInfo.output_width * cInfo.output_components;		//JPEG 1ラインのバイト数
		nBmpLineBytes = (cInfo.output_width * 3 + 3) & 0xfffffffcL;			//Bitmap 1ラインのバイト数

		pSample = new JSAMPLE[nJpegLineBytes + 10];		// ラインバッファ確保
		buffer[0] = pSample;

		lpbtBits += cInfo.output_height * nBmpLineBytes;	//Bitmapの最下ラインにポインタ設定
		while(cInfo.output_scanline < cInfo.output_height)
		{
			jpeg_read_scanlines(&cInfo,buffer,1);		//Jpegを1ライン読み込む

			for(i = 0; i < nJpegLineBytes; i += 3)		//JPEGはBGRの順なのでRBG順に変換
			{
				tmp = buffer[0][i+0];
				buffer[0][i+0]	= buffer[0][i+2];
				buffer[0][i+2]	= tmp;
			}
			lpbtBits -= nBmpLineBytes;					//ポインタを1ライン分ずらす
			memcpy(lpbtBits,buffer[0],nBmpLineBytes);	//Jpegは上から下へラインが格納、Bitmapはライン順が逆
		}
		delete	pSample;

		jpeg_finish_decompress(&cInfo);		// 読み込み終了処理
		jpeg_destroy_decompress(&cInfo);
		fclose(fp);

		m_lpcBitmap->Attach(hBmp);			//結果のアタッチ

		return	true;
	}
	CATCH_ALL(e)
	{
		if(pSample != NULL)
			delete	pSample;
		if(fp != NULL)
			fclose(fp);
		return	false;
	}
	END_CATCH_ALL
}

カテゴリー「VC++ TIPS」 のエントリー