| ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
|
Windows関連 Solaris関連 画像入出力 その他アルゴリズムなど |
アイコンファイルの形式
概観
ICONDIR構造体
ICONDIRENTRY構造体
ICONIMAGE構造体
イメージの形式
BITMAPINFOHEADER構造体
RGBQUAD構造体
イメージのバイト配列
マスクのバイト配列
例のごとく
#include <windows.h>
#include <stdio.h>
typedef struct{
BYTE bWidth; // イメージの幅(ピクセル数)
BYTE bHeight; // イメージの高さ(ピクセル数)
BYTE bColorCount; // イメージの色数(256色より多い場合は0)
BYTE bReserved; // Reserved ( must be 0)
WORD wPlanes; // Color Planes
WORD wBitCount; // 一ピクセルあたりのビット数
DWORD dwBytesInRes; // イメージに使用しているバイト数
DWORD dwImageOffset; // ファイル中の何バイト目から記録されているか。
} ICONDIRENTRY, *LPICONDIRENTRY;
// ファイルの先頭に存在する。
// リソースの型、イメージの数、ICONDIRENTRY構造体の配列を保持している
typedef struct{
WORD idReserved; // Reserved (must be 0)
WORD idType; // リソースの型 ICOの場合は1
WORD idCount; // 含まれているイメージの数
ICONDIRENTRY idEntries[1]; // ICONDIRENTRY構造体の配列
} ICONDIR, *LPICONDIR;
typedef struct{
BITMAPINFOHEADER icHeader; // DIBヘッダ
RGBQUAD icColors[1]; // カラーテーブル
BYTE icXOR[1]; // イメージ
BYTE icAND[1]; // マスク
} ICONIMAGE, *LPICONIMAGE;
BOOL ReadIcoFile(
const char *FileName, ICONDIR **ppIconDir, ICONIMAGE ***ppvImgList
);
void FreeIco( ICONDIR* pIcoDir, ICONIMAGE **pvImg );
BOOL OptIco(
const char *FileName, ICONDIR* pIcoDir, ICONIMAGE **pvImg
);
BOOL OptIco1( FILE *outfile, ICONIMAGE *pImg, int ColorCount );
BYTE* OptImage1(
FILE *outfile, BYTE *pByte, int width, int height, int bpp, RGBQUAD *pRGB
);
BYTE* OptImage24(
FILE *outfile, BYTE *pByte, int width, int height
);
int pad( int width, int bpp );
int main( int argc, char *argv[] )
{
ICONDIR *pIcoDir;
ICONIMAGE **vpIcoImage;
if ( argc <= 2 ) return -1;
if ( !ReadIcoFile( argv[1], &pIcoDir, &vpIcoImage ) )
return -1;
OptIco( argv[2], pIcoDir, vpIcoImage );
FreeIco( pIcoDir, vpIcoImage );
return 0;
}
// 通称:*.icoファイルを読み込む
// 引数:FileName : [入力]ファイル名
// ppIconDir : [出力]ICONDIR構造体へのポインタ
// ppvImgList : [出力]ICONIMAGE構造体へのポインタの配列のアドレス
// 機能:ICOファイルを読み込み、
// ICONDIR構造体を確保し、そのアドレスをppIconDirが示すアドレスに返す
// ICONIMAGE構造体を確保、そのアドレスを保持するポインタの配列を確保、
// ppvImgListが示すアドレスに返す。
BOOL ReadIcoFile(
const char *FileName,
ICONDIR **ppIconDir,
ICONIMAGE ***ppvImgList
)
{
FILE *infile = NULL;
ICONDIR *pIco = NULL;
ICONIMAGE **pvImg = NULL;
int i;
infile = fopen( FileName, "rb" ); // ファイルを開く
if ( NULL == infile ) return FALSE;
pIco = (ICONDIR*)malloc( sizeof( ICONDIR ) ); // ICONDIR構造体を確保
if ( NULL == pIco ) return FALSE;
// ファイルの先頭に存在するICONDIRを読み込む
fread( &(pIco->idReserved), sizeof( WORD ), 1, infile );
fread( &(pIco->idType), sizeof( WORD ), 1, infile );
fread( &(pIco->idCount), sizeof( WORD ), 1, infile );
if ( 1 != pIco->idType ) goto ERR_EXIT;
// ICONDIRENTRY構造体を記録する領域を確保する
// (上記領域はICONDIR構造体の中に含まれる)
pIco = (ICONDIR*)realloc(
pIco, sizeof( ICONDIR ) + ( sizeof( ICONDIRENTRY ) * pIco->idCount )
);
if ( NULL == pIco ) goto ERR_EXIT;
// ICONDIRENTRY構造体を読み込む
fread( pIco->idEntries, sizeof( ICONDIRENTRY ), pIco->idCount, infile );
// ICONIMAGE構造体のポインタの配列を確保する
pvImg = (ICONIMAGE**)calloc( sizeof( ICONIMAGE* ), pIco->idCount );
if ( NULL == pvImg ) goto ERR_EXIT;
// ICONIMAGE構造体を読み込む
for ( i = 0; i < pIco->idCount; i++ ) {
// ICONIMAGE構造体の領域を確保する
pvImg[i] = (ICONIMAGE*)malloc( pIco->idEntries[i].dwBytesInRes );
if ( NULL == pvImg[i] ) goto ERR_EXIT;
// シークして、読む
fseek( infile, pIco->idEntries[i].dwImageOffset, SEEK_SET );
fread( pvImg[i], 1, pIco->idEntries[i].dwBytesInRes, infile );
}
fclose ( infile );
(*ppIconDir) = pIco;
(*ppvImgList) = pvImg;
return TRUE;
ERR_EXIT:
fclose ( infile );
FreeIco( pIco, pvImg );
return FALSE;
}
// 通称:ReadIcoFile関数で確保されたメモリ領域を開放する
void FreeIco( ICONDIR* pIcoDir, ICONIMAGE **pvImg )
{
int i;
for ( i = 0; i < pIcoDir->idCount; i++ ) {
free( pvImg[i] );
}
free( pvImg );
free ( pIcoDir );
}
// 通称:アイコンのイメージをHTMLで出力する
// 機能:ファイルを開き、イメージを一つずつ出力させる
BOOL OptIco( const char *FileName, ICONDIR* pIcoDir, ICONIMAGE **pvImg )
{
FILE *outfile;
int i;
outfile = fopen( FileName, "w" ); // ファイルを開く
if ( NULL == outfile ) return FALSE;
// HTMLのヘッダを出力
fprintf( outfile, "<html><body>\n" );
for ( i = 0; i < pIcoDir->idCount; i++ ) { // イメージの個数分
// 出力する
if ( !OptIco1( outfile, pvImg[i], pIcoDir->idEntries[i].bColorCount ) ) {
// 失敗したら終了する
fclose( outfile );
return FALSE;
}
fprintf( outfile, "\n" ); // 横線
}
fprintf( outfile, "</body></html>" );
fclose( outfile ); // 閉じる
return TRUE;
}
// 通称:一つ分のイメージを出力する
BOOL OptIco1( FILE *outfile, ICONIMAGE *pImg, int ColorCount )
{
RGBQUAD *pRGB = pImg->icColors; // カラーテーブルの開始位置をポイントする
int ColorCnt; // カラーテーブルの要素数を保持する
BYTE *pXOR; // イメージのバイト配列をポイントする
RGBQUAD MaskColor[ 2 ] = { // マスク用のカラーパレット
{ 0, 0, 0, 0 },
{ 0xFF, 0xFF, 0xFF, 0xFF }
};
const int bpp = pImg->icHeader.biBitCount; // 一ピクセルあたりのビット数
const int width = pImg->icHeader.biWidth; // 幅(ピクセル数)
const int height = pImg->icHeader.biHeight / 2; // 高さ(ピクセル数)
// (biHeightには本来のイメージとマスクの分を合計した高さが記録されている)
// イメージの情報とテーブルのヘッダを出力
fprintf( outfile, "Width = %d Height = %d BitPerPixel = %d\n",
width, height, bpp );
fprintf( outfile,
"<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" >\n" );
// 本来のイメージの部分を出力
if ( pImg->icHeader.biBitCount < 24 ) {
// 1,2,4,8ビットカラーのイメージを出力
ColorCnt = 0x1 << pImg->icHeader.biBitCount; // 色数を算出
pXOR = (BYTE*)( pRGB + ColorCnt ); // イメージのバイト配列のアドレスを算出
pXOR = OptImage1( outfile, pXOR, width, height, bpp, pRGB );
}
else {
// 24ビットカラーのイメージを出力
pXOR = (BYTE*)pRGB; // 24ビットカラーの場合、カラーパレットは存在しない
pXOR = OptImage24( outfile, pXOR, width, height );
}
// マスク用のイメージを出力する(マスクイメージは1ビットカラーである)
pXOR = OptImage1( outfile, pXOR, width, height, 1, MaskColor );
// テーブルのフッタを出力
fprintf( outfile, "</TABLE>\n" );
return TRUE;
}
// 通称:1,2,4,8ビットカラーを出力
// 戻り値:pByteから、出力した分だけスキップしたポインタを返す
BYTE* OptImage1(
FILE *outfile,
BYTE *pByte,
int width,
int height,
int bpp,
RGBQUAD *pRGB
)
{
int i, j, k, l;
const int BitMask = ( 0x1 << bpp ) - 1;
for ( i = 0; i < height; i++ ) {
// 行の開始を示すタグを出力
fprintf( outfile, "<tr>\n" );
for ( j = 0; j < width / ( 8 / bpp ); j++ ) {
// (1バイトが複数ピクセルとして使用されている)
for ( l = 8 / bpp - 1; l >= 0; l-- ) {
// 1ピクセル分の値を取得
k = ( (*pByte) >> bpp * l ) & BitMask;
// 一升分のタグを出力
fprintf( outfile,
"<TD width=\"1\" height=\"1\" bgcolor=\"%02X%02X%02X\" ></TD>\n",
pRGB[k].rgbRed, pRGB[k].rgbGreen, pRGB[k].rgbBlue
);
}
pByte++; // 次のバイトへ
}
// パディングをスキップする
for ( j = 0; j < pad( width, bpp ); j++ )
pByte++;
// 行の終わりを示すタグを出力する
fprintf( outfile, "</TR>\n" );
}
return pByte;
}
// 通称:24ビットカラーのイメージを出力
// 戻り値:pByteから出力した分だけスキップしたポインタを返す
BYTE* OptImage24( FILE *outfile, BYTE *pByte, int width, int height )
{
int i, j;
for ( i = 0; i < height; i++ ) {
// 行の開始を示すタグを出力
fprintf( outfile, "<tr>\n" );
for ( j = 0; j < width; j++ ) {
// 一升分のタグを出力
fprintf( outfile,
"<TD width=\"1\" height=\"1\" bgcolor=\"%02X%02X%02X\" border=\"0\" ></TD>\n",
pByte[2], pByte[1], pByte[0]
); // バイト配列中にはBGRの順に記録されている
// 1ピクセルで3バイト使用する
pByte += 3;
}
// パディングをスキップ
for ( j = 0; j < pad( width, 24 ); j++ )
pByte++;
// 行の終わりを示すタグを出力
fprintf( outfile, "</TR>\n" );
}
return pByte;
}
// パディング長(バイト数)を算出
// width : 画像の幅
// bpp : 一ピクセルあたりのビット数
int pad( int width, int bpp )
{
int r = 4 - ( width * bpp % 32 ) / 8;
if ( r < 4 )
return r;
else
return 0;
}
|
|||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||