ホーム 主筆 その他ソフト その他情報 Syuhitu.org English

Windows関連

スクリーンセーバー作成法

半透明ウインドウの性能

bootfont.bin

キャビネット形式

ウインドウスタイルをいじる

Java製ソフトをServiceに登録する

イベントログにメッセージを出力する

コントロールパネルにアイコンを追加する

スクリプトによる拡張1

スクリプトによる拡張2

ガジェットの作成

大容量メモリ

メモリ搭載量の下限に挑む

スパースファイルにする

表示されるアイコンの種類を調べてみた

メモリマップIOとエラー処理

ファイルを作る順番と速度の関係

Cryptography API: Next Generationを使う

Windows 10のアクセントカラー

iSCSIディスクにバックアップを取る

サーバプロセスを分離して実装する

サーバプロセスを分離して実装する - F#

レジストリに大量に書き込む

Solaris関連

OpenGL

Solaris設定

ディレクトリの読み込み

主筆プラグイン開発

マルチスレッドでの開発

door

音を出す

Blade100の正しい虐め方

パッケージの作成

画像入出力

BMPファイル

ICOファイル

ANIファイル

JPEGファイル

減色アルゴリズム

減色アルゴリズムの並列化

その他アルゴリズムなど

自由軸回転

Base64

文字列操作

CPU利用率の取得

正規表現ライブラリ

メタボールを作る

メタボールを作る2

正規表現とNFA・DFA

C言語の構文解析

液晶ディスプレイを解体してみた

iSCSIの理論と実装

単一フォルダにファイルを沢山作る

USB-HUBのカスケード接続

SafeIntの性能

VHDファイルのフォーマット

USBメモリに書き込み続けてみた

BmpIoLib.c

ビットマップファイルを読み込むためのプログラム。BmpIoLib.c

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <assert.h>

#if !defined( _MSC_VER )
#include <alloca.h>
#endif

#include "BmpIoLib.h"

// リトルエンディアンか否か
#define ISLITTLEENDIAN 1

// 各種データ型

#define WORD unsigned short
#define DWORD unsigned int
#define LONG int
#define BYTE unsigned char
#define BOOL int
#define FALSE 0
#define TRUE 1

typedef struct tagBITMAPFILEHEADER {
    WORD bfType;
    DWORD bfSize;
    WORD bfReserved1;
    WORD bfReserved2;
    DWORD bfOffBits;
} BITMAPFILEHEADER;

typedef struct tagBITMAPINFOHEADER {
    DWORD  biSize;
    LONG   biWidth;
    LONG   biHeight;
    WORD   biPlanes;
    WORD   biBitCount;
    DWORD  biCompression;
    DWORD  biSizeImage;
    LONG   biXPelsPerMeter;
    LONG   biYPelsPerMeter;
    DWORD  biClrUsed;
    DWORD  biClrImportant;
} BITMAPINFOHEADER;


// ピクセルのデータを読むためのバッファの構造体
typedef struct tagBuf
{
	union {
		unsigned int buf : 32;
		unsigned char vbuf[4];
	} BufU;
	int buflen;
} BUF;

#define BITMAPFILEHEADER_SIZE ( sizeof( WORD ) * 3 + sizeof( DWORD ) * 2 )
#define BITMAPINFOHEADER_SIZE ( sizeof( WORD ) * 2 + sizeof( DWORD ) * 5 + sizeof( LONG ) * 4 )


static int PixIdx( int w, int h, const IBMP *pBmp );


///////////////////////////////////////////////////////////////////////////////////
// 構築・破棄

// 構築
IBMP* BmpIO_CreateBitmap( int width, int height, int BitPerPixcel )
{
	IBMP *p = NULL;

	// ビット数の指定を確認する。
	assert( BitPerPixcel == 24 ||
		BitPerPixcel == 8 ||
		BitPerPixcel == 4 ||
		BitPerPixcel == 1 );
	if ( BitPerPixcel != 24 && BitPerPixcel != 8 &&
			BitPerPixcel != 4 && BitPerPixcel != 1 )
		return NULL;

	p = (IBMP*)malloc( sizeof( IBMP ) );
	if ( NULL == p ) return NULL;
	p->pColor = NULL;
	p->pPix = NULL;

	// 24Bitカラーの場合
	if ( 24 == BitPerPixcel ) {
		// p->pPixは使用せず、p->pColorにピクセルデータを格納する。
		p->pColor = (ICOLOR*)calloc( width * height, sizeof( ICOLOR ) );
		if ( NULL == p->pColor ) goto ERR_EXIT;
	}
	else {
		// p->pColorにはカラーテーブルを格納する。
		p->pColor = (ICOLOR*)calloc( ( 1 << BitPerPixcel ), sizeof( ICOLOR ) );
		p->pPix = (unsigned char*)calloc( width * height, sizeof( unsigned char ) );
		if ( NULL == p->pColor || NULL == p->pPix ) goto ERR_EXIT;
	}

	p->width = width;
	p->height = height;
	p->BitPerPix = BitPerPixcel;

	return p;

	// 失敗した場合
ERR_EXIT:
	free( p->pColor );
	free( p->pPix );
	free( p );
	return NULL;
}

// 破棄
void BmpIO_DeleteBitmap( IBMP *pBmp )
{
	if ( NULL == pBmp ) return ;
	if ( NULL != pBmp->pPix ) free( pBmp->pPix );
	if ( NULL != pBmp->pColor ) free( pBmp->pColor );
	free( pBmp );
}


int BmpIO_GetWidth( const IBMP *pBmp )
{
	assert( NULL != pBmp );
	return pBmp->width;
}

int BmpIO_GetHeight( const IBMP *pBmp )
{
	assert( NULL != pBmp );
	return pBmp->height;
}

int BmpIO_GetBitPerPixcel( const IBMP *pBmp )
{
	assert( NULL != pBmp );
	return pBmp->BitPerPix;
}

unsigned char BmpIO_GetR( int x, int y, const IBMP *pBmp )
{
	assert( NULL != pBmp && NULL != pBmp->pColor );

	if ( pBmp->BitPerPix == 24 )
		return pBmp->pColor[ PixIdx( x, y, pBmp ) ].r;
	else
		return BmpIO_GetColorTableR( BmpIO_GetPixcel( x, y, pBmp ), pBmp );
}

unsigned char BmpIO_GetG( int x, int y, const IBMP *pBmp )
{
	assert( NULL != pBmp && NULL != pBmp->pColor );

	if ( pBmp->BitPerPix == 24 )
		return pBmp->pColor[ PixIdx( x, y, pBmp ) ].g;
	else
		return BmpIO_GetColorTableG( BmpIO_GetPixcel( x, y, pBmp ), pBmp );
}

unsigned char BmpIO_GetB( int x, int y, const IBMP *pBmp )
{
	assert( NULL != pBmp && NULL != pBmp->pColor );

	if ( pBmp->BitPerPix == 24 )
		return pBmp->pColor[ PixIdx( x, y, pBmp ) ].b;
	else
		return BmpIO_GetColorTableB( BmpIO_GetPixcel( x, y, pBmp ), pBmp );
}


///////////////////////////////////////////////////////////////////////////////////
// 24bitビットマップ用

void BmpIO_SetR( int x, int y, IBMP *pBmp, unsigned char v )
{
	assert( NULL != pBmp && NULL != pBmp->pColor && pBmp->BitPerPix == 24 );
	pBmp->pColor[ PixIdx( x, y, pBmp ) ].r = v;
}

void BmpIO_SetG( int x, int y, IBMP *pBmp, unsigned char v )
{
	assert( NULL != pBmp && NULL != pBmp->pColor && pBmp->BitPerPix == 24 );
	pBmp->pColor[ PixIdx( x, y, pBmp ) ].g = v;
}

void BmpIO_SetB( int x, int y, IBMP *pBmp, unsigned char v )
{
	assert( NULL != pBmp && NULL != pBmp->pColor && pBmp->BitPerPix == 24 );
	pBmp->pColor[ PixIdx( x, y, pBmp ) ].b = v;
}


///////////////////////////////////////////////////////////////////////////////////
// 1,4,8bitビットマップ用

unsigned char BmpIO_GetColorTableR( int idx, const IBMP *pBmp )
{
	assert( NULL != pBmp && NULL != pBmp->pColor );
	assert( 1 == pBmp->BitPerPix ||
			4 == pBmp->BitPerPix ||
			8 == pBmp->BitPerPix );
	assert( idx >= 0 && idx < ( 1 << pBmp->BitPerPix ) );
	idx = idx % ( 1 << pBmp->BitPerPix );
	return pBmp->pColor[ idx ].r;
}

unsigned char BmpIO_GetColorTableG( int idx, const IBMP *pBmp )
{
	assert( NULL != pBmp && NULL != pBmp->pColor );
	assert( 1 == pBmp->BitPerPix ||
			4 == pBmp->BitPerPix ||
			8 == pBmp->BitPerPix );
	assert( idx >= 0 && idx < ( 1 << pBmp->BitPerPix ) );
	idx = idx % ( 1 << pBmp->BitPerPix );
	return pBmp->pColor[ idx ].g;
}

unsigned char BmpIO_GetColorTableB( int idx, const IBMP *pBmp )
{
	assert( NULL != pBmp && NULL != pBmp->pColor );
	assert( 1 == pBmp->BitPerPix ||
			4 == pBmp->BitPerPix ||
			8 == pBmp->BitPerPix );
	assert( idx >= 0 && idx < ( 1 << pBmp->BitPerPix ) );
	idx = idx % ( 1 << pBmp->BitPerPix );
	return pBmp->pColor[ idx ].b;
}

void BmpIO_SetColorTableR( int idx, const IBMP *pBmp, unsigned char v )
{
	assert( NULL != pBmp && NULL != pBmp->pColor );
	assert( 1 == pBmp->BitPerPix ||
			4 == pBmp->BitPerPix ||
			8 == pBmp->BitPerPix );
	assert( idx >= 0 && idx < ( 1 << pBmp->BitPerPix ) );
	idx = idx % ( 1 << pBmp->BitPerPix );
	pBmp->pColor[ idx ].r = v;
}

void BmpIO_SetColorTableG( int idx, const IBMP *pBmp, unsigned char v )
{
	assert( NULL != pBmp && NULL != pBmp->pColor );
	assert( 1 == pBmp->BitPerPix ||
			4 == pBmp->BitPerPix ||
			8 == pBmp->BitPerPix );
	assert( idx >= 0 && idx < ( 1 << pBmp->BitPerPix ) );
	idx = idx % ( 1 << pBmp->BitPerPix );
	pBmp->pColor[ idx ].g = v;
}

void BmpIO_SetColorTableB( int idx, const IBMP *pBmp, unsigned char v )
{
	assert( NULL != pBmp && NULL != pBmp->pColor );
	assert( 1 == pBmp->BitPerPix ||
			4 == pBmp->BitPerPix ||
			8 == pBmp->BitPerPix );
	assert( idx >= 0 && idx < ( 1 << pBmp->BitPerPix ) );
	idx = idx % ( 1 << pBmp->BitPerPix );
	pBmp->pColor[ idx ].b = v;
}

unsigned char BmpIO_GetPixcel( int x, int y, const IBMP *pBmp )
{
	assert( NULL != pBmp && NULL != pBmp->pColor && NULL != pBmp->pPix );
	assert( 1 == pBmp->BitPerPix ||
			4 == pBmp->BitPerPix ||
			8 == pBmp->BitPerPix );
	return pBmp->pPix[ PixIdx( x, y, pBmp ) ];
}

void BmpIO_SetPixcel( int x, int y, const IBMP *pBmp, unsigned char v )
{
	assert( NULL != pBmp && NULL != pBmp->pColor && NULL != pBmp->pPix );
	assert( 1 == pBmp->BitPerPix ||
			4 == pBmp->BitPerPix ||
			8 == pBmp->BitPerPix );
	assert( v < ( 1 << pBmp->BitPerPix ) );
	v = v % ( 1 << pBmp->BitPerPix );
	pBmp->pPix[ PixIdx( x, y, pBmp ) ] = v;
}

int BmpIO_TranseTo24BitColor( IBMP *pBmp )
{
	ICOLOR *wpColor;
	int PixCount;	// 総ピクセル数
	int i;

	assert( NULL != pBmp );

	// 24Bitカラーのデータが渡されたら、処理をせずに真を返す
	if ( 24 == pBmp->BitPerPix ) return TRUE;

	assert( NULL != pBmp->pColor && NULL != pBmp->pPix );
	assert( 1 == pBmp->BitPerPix ||
			4 == pBmp->BitPerPix ||
			8 == pBmp->BitPerPix );

	PixCount = pBmp->width * pBmp->height;

	// 24Bitカラーの画像を格納するための領域を確保
	wpColor = (ICOLOR*)calloc( PixCount, sizeof( ICOLOR ) );
	if ( NULL == wpColor ) return FALSE;

	// 各ピクセルに色を設定する
	for ( i = 0; i < PixCount; i++ )
		wpColor[i] = pBmp->pColor[ pBmp->pPix[i] ];

	// 構造体の中身を差し替える
	free( pBmp->pColor );
	free( pBmp->pPix );
	pBmp->pColor = wpColor;
	pBmp->pPix = NULL;
	pBmp->BitPerPix = 24;

	return TRUE;
}

///////////////////////////////////////////////////////////////////////////////////
// 内部処理

// インデックスを生成
static int PixIdx( int w, int h, const IBMP *pBmp )
{
	assert( w >= 0 && w < pBmp->width && h >= 0 && h <= pBmp->height );
	w = w % pBmp->width;
	h = h % pBmp->height;
	return h * pBmp->width + w;
}


///////////////////////////////////////////////////////////////////////////////////
// 入力用ルーチン

static BOOL LoadHeader(
	FILE *infile, unsigned int *ctsize, int *blen, int *pWidth, int *pHeight
);
static BOOL LoadBody1( FILE *infile, int BitLen, IBMP *pBmp );
static BOOL LoadBody24( FILE *infile, IBMP *pBmp );
static void FrushBuf_ipt( BUF *pBuf, FILE *infile );
static int ReadBuf( BUF *pBuf, int len, FILE *infile );
static size_t int_fread( void *buffer, size_t size, size_t count, FILE *stream );

// イメージ読み込み指示
IBMP* BmpIO_Load( FILE *infile )
{
	unsigned int ctsize;	// カラーテーブルのエントリ数
	int blen;		// 1ピクセルあたりビット長
	IBMP *pBmp;
	int w, h;
	BOOL r;

	// ファイルヘッダの入力、カラーテーブル長、
	// pixelsの領域長、ピクセルあたりのビット長を取得
	if ( !LoadHeader( infile, &ctsize, &blen, &w, &h ) ) return FALSE;

	// メモリ領域を確保
	pBmp = BmpIO_CreateBitmap( w, h, blen );
	if ( NULL == pBmp ) return NULL;

	// ピクセルあたりビット長別にファイルボディ部を読み込む
	if ( 24 != blen )
		r = LoadBody1( infile, blen, pBmp );
	else
		r = LoadBody24( infile, pBmp );

	if ( !r ) {
		// 失敗
		BmpIO_DeleteBitmap( pBmp );
		return NULL;
	}

	return pBmp;
}

// ヘッダ部を読む
static BOOL LoadHeader(
	FILE *infile,
	unsigned int *ctsize,
	int *blen,
	int *pWidth,
	int *pHeight
)
{
	BITMAPFILEHEADER bfh;
	BITMAPINFOHEADER bi;

	// 各構造体を入力
	if ( int_fread( &( bfh.bfType ), sizeof( bfh.bfType ), 1, infile ) < 1 )
		return FALSE;
	if ( int_fread( &( bfh.bfSize ), sizeof( bfh.bfSize ), 1, infile ) < 1 )
		return FALSE;
	if ( int_fread( &( bfh.bfReserved1 ), sizeof( bfh.bfReserved1 ), 1, infile ) < 1 )
		return FALSE;
	if ( int_fread( &( bfh.bfReserved2 ), sizeof( bfh.bfReserved2 ), 1, infile ) < 1 )
		return FALSE;
	if ( int_fread( &( bfh.bfOffBits ), sizeof( bfh.bfOffBits ), 1, infile ) < 1 )
		return FALSE;

	if ( int_fread( &( bi.biSize ), sizeof( bi.biSize ), 1, infile ) < 1 )
		return FALSE;
	if ( int_fread( &( bi.biWidth ), sizeof( bi.biWidth ), 1, infile ) < 1 )
		return FALSE;
	if ( int_fread( &( bi.biHeight ), sizeof( bi.biHeight ), 1, infile ) < 1 )
		return FALSE;
	if ( int_fread( &( bi.biPlanes ), sizeof( bi.biPlanes ), 1, infile ) < 1 )
		return FALSE;
	if ( int_fread( &( bi.biBitCount ), sizeof( bi.biBitCount ), 1, infile ) < 1 )
		return FALSE;
	if ( int_fread( &( bi.biCompression ), sizeof( bi.biCompression ), 1, infile ) < 1 )
		return FALSE;
	if ( int_fread( &( bi.biSizeImage ), sizeof( bi.biSizeImage ), 1, infile ) < 1 )
		return FALSE;
	if ( int_fread( &( bi.biXPelsPerMeter ), sizeof( bi.biXPelsPerMeter ), 1, infile ) < 1 )
		return FALSE;
	if ( int_fread( &( bi.biYPelsPerMeter ), sizeof( bi.biYPelsPerMeter ), 1, infile ) < 1 )
		return FALSE;
	if ( int_fread( &( bi.biClrUsed ), sizeof( bi.biClrUsed ), 1, infile ) < 1 )
		return FALSE;
	if ( int_fread( &( bi.biClrImportant ), sizeof( bi.biClrImportant ), 1, infile ) < 1 )
		return FALSE;
	// ファイルタイプを確認
	if ( bfh.bfType != 0x4D42 ) return FALSE;

	// 読み込んだ情報を返す
	(*blen) = bi.biBitCount;	// 1ピクセル当りのビット長
	(*ctsize) = bi.biClrUsed;	// 使用される色の数
	(*pWidth) = bi.biWidth;		// 幅
	(*pHeight) = bi.biHeight;	// 高さ

	return TRUE;
}

// カラーテーブルを使用するビットマップを読み込む
static BOOL LoadBody1( FILE *infile, int BitLen, IBMP *pBmp )
{
	int i, j;
	BUF buf;	// 読み込むためのバッファ
	int ctsize = ( 1 << BitLen );	// カラーテーブルの数

	// カラーテーブルを読む
	for ( i = 0; i < ctsize && !ferror( infile ) && !feof( infile ); i++ ) {
		pBmp->pColor[i].b = fgetc( infile );
		pBmp->pColor[i].g = fgetc( infile );
		pBmp->pColor[i].r = fgetc( infile );
		fgetc( infile );	// rgbReserved
	}
	if ( ferror( infile ) || feof( infile ) ) return FALSE;

	// バッファの内容を初期化する
	buf.BufU.buf = 0;
	buf.buflen = 0;
	FrushBuf_ipt( &buf, infile );

	for ( i = 0; i < pBmp->height && !feof( infile ) && !ferror( infile ); i++ ) {
		for ( j = 0; j < pBmp->width && !feof( infile ) && !ferror( infile ); j++ ) {
			int wIdx = PixIdx( j, i, pBmp );
			// 指定されたビット長のデータを取得
			pBmp->pPix[ wIdx ] = ReadBuf( &buf, BitLen, infile );
		}
		FrushBuf_ipt( &buf, infile );
	}

	return ( i == pBmp->height && j == pBmp->width );
}

// 24ビットカラービットマップを読む
static BOOL LoadBody24( FILE *infile, IBMP *pBmp )
{
	int PixCnt = pBmp->width * pBmp->height;	// ピクセル数
	int i, j;
	BUF buf;

	// バッファの内容を初期化する
	buf.buflen = 0;
	buf.BufU.buf = 0;
	FrushBuf_ipt( &buf, infile );

	for ( i = 0; i < pBmp->height && !feof( infile ) && !ferror( infile ); i++ ) {
		for ( j = 0; j < pBmp->width && !feof( infile ) && !ferror( infile ); j++ ) {
			// 色はBGRの順に記録されている
			BmpIO_SetB( j, i, pBmp, (unsigned char)ReadBuf( &buf, 8, infile ) );
			BmpIO_SetG( j, i, pBmp, (unsigned char)ReadBuf( &buf, 8, infile ) );
			BmpIO_SetR( j, i, pBmp, (unsigned char)ReadBuf( &buf, 8, infile ) );
		}
		FrushBuf_ipt( &buf, infile );
	}
	return ( i == pBmp->height && j == pBmp->width );
}

// バッファにデータを読み込む
static void FrushBuf_ipt( BUF *pBuf, FILE *infile )
{
	int i;

#if ISLITTLEENDIAN
	for ( i = 3; i >= 0; i-- )
#else
	for ( i = 0; i < 4; i++ )
#endif
		pBuf->BufU.vbuf[ i ] = getc( infile );
	pBuf->buflen = 32;
}

// バッファから指定したビット数分データを取得する
static int ReadBuf( BUF *pBuf, int len, FILE *infile )
{
	int r;
	if ( pBuf->buflen < len ) FrushBuf_ipt( pBuf, infile );
	r = ( ( ( ( 1 << len ) - 1 ) << ( 32 - len ) ) & pBuf->BufU.buf ) >> ( 32 - len );
	pBuf->BufU.buf <<= len;
	pBuf->buflen -= len;
	return r;
}

// エンディアンネスを吸収して、ファイルを読み込む
size_t int_fread( void *buffer, size_t size, size_t count, FILE *stream )
{
#if ISLITTLEENDIAN
	return fread( buffer, size, count, stream );
#else
	size_t i, j;
	size_t r;
	char *cbuf = (char*)buffer;

	// 読み込む
	r = fread( buffer, size, count, stream );
	if ( 1 == size ) return r;

	// 項目ごとにバイトオーダーを反転
	for ( i = 0; i < count; i++ ) {
		for ( j = 0; j < size / 2; j++ ) {
			int idx1 = i * size + j;
			int idx2 = i * size + ( size - j - 1 );
			char c = cbuf[ idx1 ];
			cbuf[ idx1 ] = cbuf[ idx2 ];
			cbuf[ idx2 ] = c;
		}
	}
	return r;
#endif
}

///////////////////////////////////////////////////////////////////////////////////
// 出力用ルーチン

static BOOL WriteHeader( FILE *outfile, const IBMP *pBmp );
static BOOL WriteBody1( FILE *outfile, const IBMP *pBmp );
static BOOL WriteBody24( FILE *outfile, const IBMP *pBmp );
static void FrushBuf_opt( BUF *pBuf, FILE *outfile );
static void WriteBuf( BUF *pBuf, int BitLen, unsigned char c, FILE *outfile );
static size_t int_fwrite( const void *buffer, size_t size, size_t count, FILE *stream );

// イメージを出力する
BOOL BmpIO_Save( FILE *outfile, const IBMP *pBmp )
{
	// ヘッダを出力する
	if ( !WriteHeader( outfile, pBmp ) ) return FALSE;

	// イメージのデータを出力する
	if ( 24 == pBmp->BitPerPix )
		return WriteBody24( outfile, pBmp );
	else
		return WriteBody1( outfile, pBmp );
}

// ヘッダ部を出力する
static BOOL WriteHeader( FILE *outfile, const IBMP *pBmp )
{
	BITMAPFILEHEADER bfh;
	BITMAPINFOHEADER bi;

	// 構造体に値を設定
	bfh.bfType = 0x4D42;
	bfh.bfSize = 0;
	bfh.bfReserved1 = 0;
	bfh.bfReserved2 = 0;
	bfh.bfOffBits = BITMAPFILEHEADER_SIZE + BITMAPINFOHEADER_SIZE;
      if ( pBmp->BitPerPix <= 8 )
		bfh.bfOffBits += 4 * ( 1 << pBmp->BitPerPix );
	bi.biSize = BITMAPINFOHEADER_SIZE;
	bi.biWidth = pBmp->width;
	bi.biHeight = pBmp->height;
	bi.biPlanes = 1;
	bi.biBitCount = pBmp->BitPerPix;
	bi.biCompression = 0L;
	bi.biSizeImage = 0;
	bi.biXPelsPerMeter = 1;
	bi.biYPelsPerMeter = 1;
	bi.biClrUsed = 0;
	bi.biClrImportant = 0;

	// 各構造体を出力
	if ( int_fwrite( &(bfh.bfType), sizeof( bfh.bfType ), 1, outfile ) < 1 )
		return FALSE;
	if ( int_fwrite( &(bfh.bfSize), sizeof( bfh.bfSize ), 1, outfile ) < 1 )
		return FALSE;
	if ( int_fwrite( &(bfh.bfReserved1), sizeof( bfh.bfReserved1 ), 1, outfile ) < 1 )
		return FALSE;
	if ( int_fwrite( &(bfh.bfReserved2), sizeof( bfh.bfReserved2 ), 1, outfile ) < 1 )
		return FALSE;
	if ( int_fwrite( &(bfh.bfOffBits), sizeof( bfh.bfOffBits ), 1, outfile ) < 1 )
		return FALSE;

	if ( int_fwrite( &(bi.biSize), sizeof( bi.biSize ), 1, outfile ) < 1 )
		return FALSE;
	if ( int_fwrite( &(bi.biWidth), sizeof( bi.biWidth ), 1, outfile ) < 1 )
		return FALSE;
	if ( int_fwrite( &(bi.biHeight), sizeof( bi.biHeight ), 1, outfile ) < 1 )
		return FALSE;
	if ( int_fwrite( &(bi.biPlanes), sizeof( bi.biPlanes ), 1, outfile ) < 1 )
		return FALSE;
	if ( int_fwrite( &(bi.biBitCount), sizeof( bi.biBitCount ), 1, outfile ) < 1 )
		return FALSE;
	if ( int_fwrite( &(bi.biCompression), sizeof( bi.biCompression ), 1, outfile ) < 1 )
		return FALSE;
	if ( int_fwrite( &(bi.biSizeImage), sizeof( bi.biSizeImage ), 1, outfile ) < 1 )
		return FALSE;
	if ( int_fwrite( &(bi.biXPelsPerMeter), sizeof( bi.biXPelsPerMeter ), 1, outfile ) < 1 )
		return FALSE;
	if ( int_fwrite( &(bi.biYPelsPerMeter), sizeof( bi.biYPelsPerMeter ), 1, outfile ) < 1 )
		return FALSE;
	if ( int_fwrite( &(bi.biClrUsed), sizeof( bi.biClrUsed ), 1, outfile ) < 1 )
		return FALSE;
	if ( int_fwrite( &(bi.biClrImportant), sizeof( bi.biClrImportant ), 1, outfile ) < 1 )
		return FALSE;

	return TRUE;
}

// 1,4,8bitビットマップを出力する
BOOL WriteBody1( FILE *outfile, const IBMP *pBmp )
{
	int i, j;
	int ctcnt = 1 << pBmp->BitPerPix;	// カラーテーブルの数
	BUF buf;

	// カラーテーブルを出力する
	for ( i = 0; i < ctcnt && !ferror( outfile ); i++ ) {
		fputc( pBmp->pColor[i].b, outfile );
		fputc( pBmp->pColor[i].g, outfile );
		fputc( pBmp->pColor[i].r, outfile );
		fputc( 0, outfile );
	}

	buf.BufU.buf = 0;
	buf.buflen = 0;

	// ピクセルデータを出力
	for ( i = 0; i < pBmp->height; i++ ) {
		for ( j = 0; j < pBmp->width; j++ ) {
			WriteBuf( &buf, pBmp->BitPerPix, BmpIO_GetPixcel( j, i, pBmp ), outfile );
		}
		FrushBuf_opt( &buf, outfile );
	}
	return TRUE;
}

// 24ビットカラービットマップを出力する
static BOOL WriteBody24( FILE *outfile, const IBMP *pBmp )
{
	int i, j;
	BUF buf;

	buf.BufU.buf = 0;
	buf.buflen = 0;

	// 3バイトずつ出力する
	for ( i = 0; i < pBmp->height; i++ ){
		for ( j = 0; j < pBmp->width; j++ ) {
			WriteBuf( &buf, 8, BmpIO_GetB( j, i, pBmp ), outfile );
			WriteBuf( &buf, 8, BmpIO_GetG( j, i, pBmp ), outfile );
			WriteBuf( &buf, 8, BmpIO_GetR( j, i, pBmp ), outfile );
		}
		FrushBuf_opt( &buf, outfile );
	}
	return TRUE;
}

// バッファのデータを全て出力する
static void FrushBuf_opt( BUF *pBuf, FILE *outfile )
{
	int i;
	if ( 0 == pBuf->buflen ) return ;

#if ISLITTLEENDIAN
	for ( i = 3; i >= 0; i-- )
#else
	for ( i = 0; i < 4; i++ )
#endif
		putc( pBuf->BufU.vbuf[ i ], outfile );

	pBuf->buflen = 0;
	pBuf->BufU.buf = 0;
}

// バッファに指定したビット数分データを出力する
static void WriteBuf( BUF *pBuf, int BitLen, unsigned char c, FILE *outfile )
{
	const unsigned long MASK = ( 0x1 << ( BitLen + 1 ) ) - 1;
	pBuf->BufU.buf |= ( ( (unsigned long)c ) & MASK ) << ( 32 - ( pBuf->buflen + BitLen ) );
	pBuf->buflen += BitLen;
	if ( pBuf->buflen >= 32 )
		FrushBuf_opt( pBuf, outfile );
}

// エンディアンネスを吸収して、ファイルを出力する
size_t int_fwrite( const void *buffer, size_t size, size_t count, FILE *stream )
{
#if ISLITTLEENDIAN
	return fwrite( buffer, size, count, stream );
#else
	size_t i, j;
	char *cbuf = (char*)buffer;
	char *wbuf = (char*)alloca( size );
	size_t r;

	// 1バイト単位ならば、反転する必要はない
	if ( 1 == size )
		return fwrite( buffer, size, count, stream );

	// 項目ごとにバイトオーダーを反転して出力する
	r = 0;
	for ( i = 0; i < count; i++ ) {
		for ( j = 0; j < size; j++ ) {
			int idx1 = i * size + j;
			int idx2 = i * size + ( size - j - 1 );
			wbuf[ idx2 ] = cbuf[ idx1 ];
		}
		if ( fwrite( wbuf, size, 1, stream ) < 1 )
			return r;
		r++;
	}
	return r;
#endif
}

<< BMPファイル形式に戻る

BmpIoLib.h >>

BITest.c >>


連絡先 - サイトマップ - 更新履歴
Copyright (C)  2000 - 2016 nabiki_t All Rights Reserved.