// SUSIEプラグイン対応画像ロードクラス // (C)2002,2003 Yutaka Wada, AirparkLab /* 使い方 // オブジェクトの確保 // ここでSUSIEプラグインはカレントディレクトリ、システムディレクトリ、 // ウインドウズディレクトリの順で検索されロードされる。 CLoadImage m_LoadImage; // 対応画像をファイルダイアログで取得する CString Loadable, Filter; m_LoadImage.GetLoadableExtention( &Loadable ); Filter.Format( "読込み可能ファイル(%s)|%s|全てのファイル(*.*)|*.*||", (LPCTSTR)Loadable, (LPCTSTR)Loadable ); CFileDialog dlg( TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, Filter ); // 画像ファイルのロード(読み込みとビットマップへの変換) if( dlg.DoModal() == IDOK ){ CString filename = dlg.GetPathName(); // ファイルのロード if( m_LoadImage.Load( filename, FALSE ) == TRUE ){ // 画像の描画 // m_LoadImage.GetImageHeader() と m_LoadImage.GetImageData() で // 画像のヘッダ(BITMAPINFO*)とデータ(BYTE*)にアクセスできる // CDrawImage クラスを使用するとこんな感じで描画可能 // m_DrawImage.Draw( pDC, &Rect, m_LoadImage.GetImageHeader(), m_LoadImage.GetImageData() ); } } パブリックメンバ関数は以下の通り。 // コンストラクタ CLoadImage() // 対応拡張子群の取得 BOOL GetLoadableExtention( CString *pExt ) 引数 拡張子群取得先 CString オブジェクトへのポインタ 戻値 TRUE // 対応拡張子数の取得 int GetLoadableExtention() 戻値 対応拡張子数 // 対応拡張子の取得 CString GetLoadableExtention( int n ) 引数 対応拡張子数インデックス 戻値 拡張子文字列 // ロード済みSPI数の取得 int GetSPICount() 戻値 ロード済みSPI数 // ロード済みSPI名の取得 BOOL GetSPIName( int n, CString *pName ) 引数 ロード済みSPI数インデックス、SPI名の取得先 CString オブジェクトへのポインタ 戻値 TRUE(成功)、FALSE(失敗) // ロード済みSPI情報の取得(ハンドルテーブル間接) int GetSPIInfo( int n, int infono, LPSTR buf, int buflen ) 引数 ロード済みSPI数インデックス、情報番号、取得先バッファアドレス、取得先バッファ長 戻値 GetPluginInfo() の戻値 ※SUSIEプラグイン関数 GetPluginInfo() を参照のこと // ロード済みSPI情報の取得(ハンドル直接) int GetSPIInfo( HMODULE hnd, int infono, LPSTR buf, int buflen ) 引数 対象SPIハンドル、情報番号、取得先バッファアドレス、取得先バッファ長 戻値 GetPluginInfo() の戻値 ※SUSIEプラグイン関数 GetPluginInfo() を参照のこと // ファイル対応確認 int IsSupported( CString FileName ) 引数 対象ファイル名 戻値 -1:非対応、0以上であれば対応(0:BMP, プラグインNo+1) // 画像ファイルの読み込みとロード BOOL Load( CString filename, BOOL message = TRUE, FARPROC CallBack = NULL, long lData = 0 ) 引数 CString filename ファイル名 BOOL message = TRUE 失敗の際にメッセージを表示するかしないかのフラグ FARPROC CallBack = NULL コールバック関数アドレス(NULLで指定なし) long lData = 0 コールバック関数への引数 戻値 TRUE(成功)、FALSE(失敗) // 画像ファイル名の取得 BOOL GetFileName( CString *pFileName ) 引数 ロード済み(失敗も含む)ファイル名の取得先 戻値 TRUE(成功)、FALSE(失敗) // 画像ファイルサイズの取得 int GetFileSize() 戻値 ロード済み(失敗も含む)ファイルのサイズ // 画像をロードしたSPIハンドルの取得 HMODULE GetHandle() 戻値 画像をロードしたSPIハンドル NULLの場合、未ロードかSPIを使用しなかった(BMP画像) // 画像サイズの取得 BOOL GetSize( CRect *pRect ) 引数 画像サイズの取得先 戻値 TRUE(成功)、FALSE(失敗) // 画像コメントの取得 BOOL GetComment( CString *pComment ) 引数 コメントの取得先 戻値 TRUE // SPI API形式の画像情報の取得(取得したアドレスの内容は変更禁止) SPI_PICTURE_INFO* GetPictureInfo() 戻値 SPI API形式の画像情報へのアドレス // 画像ヘッダアドレスの取得(取得したアドレスの内容は変更禁止) BITMAPINFO* GetImageHeader() 戻値 画像ヘッダアドレス // 画像データアドレスの取得(取得したアドレスの内容は変更禁止) BYTE* GetImageData() 戻値 画像データアドレス // ファイルイメージアドレスの取得(取得したアドレスの内容は変更禁止) BYTE* GetFileImage() 戻値 ファイルイメージアドレス // デストラクタ ~CLoadImage() */ #ifndef __LOAD_IMAGE_H__ #define __LOAD_IMAGE_H__ #pragma pack(1) struct SPI_PICTURE_INFO { long left; long top; long width; long height; WORD x_density; WORD y_density; short colorDepth; HLOCAL hInfo; }; #pragma pack() typedef int (WINAPI *GET_PLUGIN_INFO)( int, LPSTR, int ); typedef int (WINAPI *IS_SUPPORTED)( LPSTR, DWORD ); typedef int (WINAPI *GET_PICTURE_INFO)( LPSTR, long, unsigned int, SPI_PICTURE_INFO* ); typedef int (WINAPI *GET_PICTURE)( LPSTR, long, unsigned int, HLOCAL*, HLOCAL*, FARPROC, long ); typedef int (WINAPI *GET_PREVIEW)( LPSTR, long, unsigned int, HLOCAL*, HLOCAL*, FARPROC, long ); typedef int (CALLBACK *PROGRESS_CALLBACK)( int, int, long ); #define SPI_OK 0 // 正常終了 #define SPI_NA -1 // その機能はインプリメントされていない #define SPI_CANCEL 1 // コールバック関数が非0を返したので展開を中止した #define SPI_UNKNOWN_FORMAT 2 // 未知のフォーマット #define SPI_INVALID_DATA 3 // データが壊れている #define SPI_NO_MEMORY 4 // メモリーが確保出来ない #define SPI_MEMORY_ERROR 5 // メモリーエラー(Lock出来ない、等) #define SPI_FILE_READ_ERROR 6 // ファイルリードエラー #define SPI_RESERVE 7 // (予約) #define SPI_INTERNAL_ERROR 8 // 内部エラー #define LOAD_SPI_MAX 64 // SPIロード最大数 class CLoadImage { int nSPICount; // SPIロード数 HMODULE hSPI[LOAD_SPI_MAX]; // SPIハンドルの保存配列 CString SPIName[LOAD_SPI_MAX]; // SPI名の保存配列 CString LoadableExtention; // ロード可能拡張子群文字列 CStringArray LoadableExtentionArray; // ロード可能拡張子配列 CString FileName; // ファイル名 int nLength; // ファイルサイズ BYTE *pFileImage; // ファイル内容へのポインタ HMODULE hLoaded; // 読み込みに使用したSPIのハンドル(NULLの場合なし(未読込かBMP画像)) SPI_PICTURE_INFO PictureInfo; // SPI画像情報 HLOCAL hBMInfo; // SPIビットマップヘッダメモリブロックハンドル HLOCAL hBMData; // SPIビットマップデータメモリブロックハンドル BITMAPINFO *pBMInfo; // ビットマップヘッダへのポインタ BYTE *pBMData; // ビットマップデータへのポインタ char *pBMComment; // ビットマップコメントへのポインタ // ワークのクリア void Clear() { if( pFileImage ) delete [] pFileImage; pFileImage = NULL; FileName = "\0"; nLength = 0; if( hLoaded ){ if( hBMInfo ){ LocalUnlock( hBMInfo ); LocalFree( hBMInfo ); } if( hBMData ){ LocalUnlock( hBMData ); LocalFree( hBMData ); } if( PictureInfo.hInfo ){ LocalUnlock( PictureInfo.hInfo ); LocalFree( PictureInfo.hInfo ); } } hLoaded = NULL; hBMInfo = NULL; hBMData = NULL; memset( (char *)&PictureInfo, NULL, sizeof(SPI_PICTURE_INFO) ); pBMInfo = NULL; pBMData = NULL; pBMComment = NULL; } // SPIのロード void LoadSPI( char *path ) { HANDLE hFile; // 検索ハンドル WIN32_FIND_DATA data; // 発見ファイルデータを受け取る構造体 HMODULE hnd; GET_PLUGIN_INFO GetPluginInfo; char str[256]; char filename[MAX_PATH]; sprintf( filename, "%s*.spi", path ); hFile = FindFirstFile( filename, &data ); if( hFile != INVALID_HANDLE_VALUE ){ do{ // 既にロード済みであればパス BOOL loaded = FALSE; for( int i=0; i= LOAD_SPI_MAX ) break; } while( FindNextFile( hFile, &data ) ); // 次のファイルを検索 FindClose( hFile ); // 検索ハンドルの後始末 } if( nSPICount >= LOAD_SPI_MAX ) AfxMessageBox( "プラグインが多すぎます" ); } // ファイルの読み込み BOOL ReadFile() { // ファイルを読み出し専用で開く CFile File; CFileException FileException; if( File.Open( (LPCTSTR)FileName, CFile::modeRead, &FileException ) ){ // オープン成功 // ファイルイメージのメモリを確保しファイル内容の読み込む nLength = File.GetLength(); pFileImage = new BYTE[nLength]; if( pFileImage == NULL ){ // メモリ確保失敗 File.Close(); AfxMessageBox( "メモリが足りません" ); return( FALSE ); } // ファイル内容の読み込みとクローズ File.Read( pFileImage, nLength ); File.Close(); return( TRUE ); } else{ CString str; str.Format( "ファイルが開けませんでした[%s]", FileName ); AfxMessageBox( (LPCTSTR)str ); return( FALSE ); } } // SPIによる画像のロード BOOL LoadImage( FARPROC CallBack, long lData ) { // BMPファイルの場合 BITMAPFILEHEADER *pBMFileHeader = (BITMAPFILEHEADER *)pFileImage; if( pBMFileHeader->bfType == *((WORD *)"BM") ){ // コールバック関数があれば実行(最初で最後) if( CallBack != NULL ) ((PROGRESS_CALLBACK)CallBack)( 100, 100, lData ); // ファイルイメージから画像ヘッダと画像データのアドレスを直接取得 pBMInfo = (BITMAPINFO *)(pFileImage + sizeof( BITMAPFILEHEADER )); pBMData = (BYTE *)(pFileImage + pBMFileHeader->bfOffBits); // 画像情報の取得 BITMAPINFOHEADER *pBMInfoHeader = &(pBMInfo->bmiHeader); PictureInfo.left = 0; PictureInfo.top = 0; PictureInfo.width = pBMInfoHeader->biWidth; PictureInfo.height = pBMInfoHeader->biHeight; PictureInfo.x_density = (WORD)pBMInfoHeader->biXPelsPerMeter; PictureInfo.y_density = (WORD)pBMInfoHeader->biYPelsPerMeter; PictureInfo.colorDepth = pBMInfoHeader->biBitCount; PictureInfo.hInfo = NULL; pBMComment = "Windows Bitmap File"; hLoaded = NULL; return( TRUE ); } /* BMPファイルでない場合 */ else{ /* 対応プラグインの検索 */ int i, ret; IS_SUPPORTED IsSupported; GET_PICTURE_INFO GetPictureInfo; GET_PICTURE GetPicture; for( i=0; i n ){ str = LoadableExtentionArray[n]; } return( str ); } // ロード済みSPI数の取得 int GetSPICount() { return( nSPICount ); } // ロード済みSPI名の取得 BOOL GetSPIName( int n, CString *pName ) { if( n < 0 || n >= nSPICount ) return( FALSE ); *pName = SPIName[n]; return( TRUE ); } // ロード済みSPI情報の取得(ハンドルテーブル間接) int GetSPIInfo( int n, int infono, LPSTR buf, int buflen ) { GET_PLUGIN_INFO GetPluginInfo; int ret; if( n < 0 || n >= nSPICount ) ret = 0; else{ GetPluginInfo = (GET_PLUGIN_INFO)GetProcAddress( hSPI[n], "GetPluginInfo" ); if( GetPluginInfo != NULL ) ret = GetPluginInfo( infono, buf, buflen ); else ret = 0; } return( ret ); } // ロード済みSPI情報の取得(ハンドル直接) int GetSPIInfo( HMODULE hnd, int infono, LPSTR buf, int buflen ) { GET_PLUGIN_INFO GetPluginInfo; int ret; if( nSPICount == 0 ) ret = 0; else if( hnd == NULL ) ret = 0; else{ GetPluginInfo = (GET_PLUGIN_INFO)GetProcAddress( hnd, "GetPluginInfo" ); if( GetPluginInfo != NULL ) ret = GetPluginInfo( infono, buf, buflen ); else ret = 0; } return( ret ); } // ファイル対応確認 -1:非対応、0以上であれば対応(0:BMP, プラグインNo+1) int IsSupported( CString FileName ) { // ファイルを読み出し専用で開く CFile File; CFileException FileException; // オープン成功なら対応可能ファイルか確認するために先頭2KBだけ読み込む if( File.Open( (LPCTSTR)FileName, CFile::modeRead, &FileException ) ){ BYTE *pFileHeader = new BYTE[2048]; if( pFileHeader == NULL ){ // メモリ確保失敗 File.Close(); AfxMessageBox( "メモリが足りません" ); return( -1 ); } int nLength = File.Read( pFileHeader, 2048 ); File.Close(); // 2KBに満たない場合はゼロで埋める for( int i=nLength; i<2048; i++ ) pFileHeader[i] = 0; // 対応ファイルの確認 int type = -1; // BMPファイルの場合 BITMAPFILEHEADER *pBMFileHeader = (BITMAPFILEHEADER *)pFileHeader; if( pBMFileHeader->bfType == *((WORD *)"BM") ) type = 0; else { // 対応プラグインの検索 IS_SUPPORTED IsSupported; for( int i=0; i