■ ビットマップをアイコンに変換
/*
** bmp2icon.c : ビットマップをアイコンに変換
**
** Copyright (c) 2000, 2001 AOK.
**
** 2000.4.12 - 初版
** 2001.6.27 - 2版
**
** 使い方: BMP2ICON ファイル名
*/
#ifdef __BORLANDC__ /* Borland C++ */
#pragma warn -8059
#pragma option -a-
#endif
#ifdef _MSC_VER /* Visual C++ */
#pragma pack(1)
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;
typedef long LONG;
#define WIDTHBYTES(bits) ((((bits)+31)>>5)<<2)
typedef struct {
BYTE bWidth;
BYTE bHeight;
BYTE bColorCount;
BYTE bReserved;
WORD wPlanes;
WORD wBitCount;
DWORD dwBytesInRes;
DWORD dwImageOffset;
} ICONDIRENTRY, *LPICONDIRENTRY;
typedef struct {
WORD idReserved;
WORD idType;
WORD idCount;
ICONDIRENTRY idEntries[1];
} ICONDIR, *LPICONDIR;
typedef struct {
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 tagRGBQUAD {
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} RGBQUAD;
typedef struct tagBITMAPFILEHEADER {
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER;
/* グローバル変数 */
BITMAPFILEHEADER bmfh;
BITMAPINFOHEADER bmih;
ICONDIR id;
DWORD mask_size = 0;
WORD ctbl_size = 0;
/* プロトタイプ宣言 */
int change_ext(char *fname);
/* BITMAPFILEHEADERの読みこみ */
int read_bmpfile_hdr(FILE *fp)
{
fread(&bmfh, sizeof(BITMAPFILEHEADER), 1, fp);
return (bmfh.bfType == 0x4D42);
}
/* BITMAPINFOHEADERの読みこみ */
void read_bmpinfo_hdr(FILE *fp)
{
fread(&bmih, sizeof(BITMAPINFOHEADER), 1, fp);
}
/* ICONDIRの各値のセット */
void set_icondir(void)
{
LONG w, h;
WORD p, bc;
memset(&id, 0, sizeof(ICONDIR));
id.idType = id.idCount = 1;
w = id.idEntries[0].bWidth = (BYTE)bmih.biWidth;
h = id.idEntries[0].bHeight = (BYTE)bmih.biHeight;
p = id.idEntries[0].wPlanes = bmih.biPlanes;
bc = id.idEntries[0].wBitCount = bmih.biBitCount;
if (p * bc >= 8)
id.idEntries[0].bColorCount = 0;
else
id.idEntries[0].bColorCount = 1 << (p * bc);
mask_size = WIDTHBYTES(w) * h;
ctbl_size = sizeof(RGBQUAD) * (bc == 8 ? 256 : id.idEntries[0].bColorCount);
id.idEntries[0].dwBytesInRes =
sizeof(BITMAPINFOHEADER)+ctbl_size+bmih.biSizeImage+mask_size;
id.idEntries[0].dwImageOffset = sizeof(ICONDIR);
}
/* アイコンファイルを書き出す */
void write_icon_data(FILE *fi, FILE *fo)
{
DWORD i;
fwrite(&id, sizeof(ICONDIR), 1, fo);
bmih.biHeight *= 2;
bmih.biXPelsPerMeter = 0;
bmih.biYPelsPerMeter = 0;
bmih.biClrUsed = 0;
bmih.biClrImportant = 0;
fwrite(&bmih, sizeof(BITMAPINFOHEADER), 1, fo);
fseek(fi, sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER), SEEK_SET);
for (i=0; i<bmih.biSizeImage+ctbl_size; i++)
fputc((BYTE)getc(fi), fo);
if (mask_size != 0)
for (i=0; i<mask_size; i++)
fputc(0x00, fo);
}
/* メインルーチン */
int main(int argc, char **argv)
{
FILE *fi, *fo;
char fn[FILENAME_MAX+1];
if (argc == 2)
{
if ((fi = fopen(*(argv+1), "rb")) != NULL)
{
if (read_bmpfile_hdr(fi))
{
read_bmpinfo_hdr(fi);
set_icondir();
strcpy(fn, *(argv+1));
if (change_ext(fn))
{
if ((fo = fopen(fn, "wb")) != NULL)
{
printf("%s -> %s \n\n", *(argv+1), fn);
write_icon_data(fi, fo);
puts("書き出しに成功しました.");
fclose(fo);
}
else
puts("出力ファイルを開けません.");
}
}
else
puts("入力ファイルはビットマップではありません.");
fclose(fi);
}
else
puts("入力ファイルを開けません.");
}
else
puts("Usage: BMP2ICON filename");
return 0;
}
/* 拡張子の付け替え */
int change_ext(char *fname)
{
char *p;
int len;
len = strlen(fname);
p = strrchr(fname, '.');
if (len >= 5 && len <= FILENAME_MAX && p != NULL)
{
if (strcmpi(p, ".BMP") == 0)
strcpy(p, ".ICO");
else
{
*fname = '\0';
puts("入力ファイルはビットマップではありません.");
return 0;
}
}
else
{
*fname = '\0';
puts("拡張子の付け替えが出来ません.");
return 0;
}
return 1;
}