Last Update: Jun.27,2001

C Source Library

「LSI C-86 Ver.3.30c 試食版」、「Borland C++ 5.5」、「Microsoft Visual C++ 6.0」でコンパイル出来ます。

■ ビットマップをアイコンに変換

/*
**  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;
}