home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DOS/V Power Report 2001 January
/
VPR0101A.BIN
/
OLS
/
LZR100
/
lzr100.lzh
/
Source
/
GIFSPI.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
2000-10-07
|
7KB
|
214 lines
/*--------------------------------------------------------------------------------------*/
/* 非LZW理論GIFデコーダー <-> Susie Plug-in インターフェース 実装ファイル Ver 1.00 */
/* for VisualStudio6.0 only */
/* ※サポート関数とGIFヘッダ解析部を実装。 */
/* Copyright (C) 2000 DJ☆Uchi [H.Uchida] */
/*--------------------------------------------------------------------------------------*/
#include "SPIMain.h"
#include "GIF.h"
/*--------------------------------------------------------------------------------------*/
/* IsSupportedEx() */
/* ヘッダ情報からファイル形式を調べる。 */
/* ※filnameはファイル名で、NULLが入っていることもある。 */
/* ※dataはファイルのヘッダで、サイズは2000バイト。 */
/*--------------------------------------------------------------------------------------*/
BOOL IsSupportedEx(char *filename, char *data)
{
GIFHEADER *gif_head;
gif_head = (GIFHEADER *)data;
if ( gif_head->signature1 == 0x38464947 ) { //識別子=GIF8+(7a or 9a)
return TRUE;
} else {
return FALSE;
}
}
/*--------------------------------------------------------------------------------------*/
/* GetPictureInfoEx() */
/* 画像ファイルの情報を書き込み、エラーコードを返す。 */
/* ※dataはファイルイメージで、サイズはdatasizeバイト。 */
/* ※アニメーションGIFの場合は、一枚目の画像情報を返す。 */
/*--------------------------------------------------------------------------------------*/
int GetPictureInfoEx(long datasize, struct PictureInfo *lpInfo, char *data)
{
//グローバル画面記述情報を取得。
GIFHEADER *gif_info;
gif_info = (GIFHEADER *)data;
//グローバルカラーマップ&GIF拡張ブロックを読み飛ばす。
char *ext_block;
ext_block = data + sizeof(GIFHEADER);
if ( gif_info->state & 0x80 ) ext_block += sizeof(GIFRGB) * (2 << (gif_info->state & 0x07));
while (*ext_block == 0x21) {
ext_block+= 2;
while (*ext_block) {
ext_block += *(ext_block) + 1;
}
ext_block++;
}
//一枚目のイメージ記述情報を取得。
GIFIMAGEHEADER *gif_head;
gif_head = (GIFIMAGEHEADER *)ext_block;
//PictureInfo構造体に値を返す。
lpInfo->left = gif_head->left;
lpInfo->top = gif_head->top;
lpInfo->width = gif_head->width;
lpInfo->height = gif_head->height;
lpInfo->x_density = 0;
lpInfo->y_density = 0;
lpInfo->colorDepth = (gif_info->state & 0x07)+1;
//画像のテキスト情報には、とりあえず画像の形式(GIF87a/GIF89a)を入れておく。
char str[] = "GIF87a";
if ( gif_info->signature2 == 0x6139 ) str[4]='9';//GIF89a
HGLOBAL htxt = GlobalAlloc(GMEM_MOVEABLE, strlen(str)+1);
char *txt = (char *)GlobalLock(htxt);
strcpy(txt, str);
lpInfo->hInfo = htxt;
return SPI_ALL_RIGHT;
}
/*--------------------------------------------------------------------------------------*/
/* GetPictureEx() */
/* 画像ファイルをDIBに変換し、エラーコードを返す。 */
/* ※コールバック関数は未実装。 */
/* ※dataはファイルイメージで、サイズはdatasizeバイト。 */
/*--------------------------------------------------------------------------------------*/
int GetPictureEx(long datasize, HANDLE *pHBInfo, HANDLE *pHBm, SPI_PROGRESS, long, BYTE *data)
{
//グローバル画面記述情報を取得。
GIFHEADER *gif_info;
gif_info = (GIFHEADER *)data;
GIFRGB *gif_palette = NULL;
//元のGIFのカラービット数(8ビット以下)
BYTE gif_color = gif_info->state & 0x07;
//DIBヘッダ領域確保(テンポラリ用、パレット×256固定)
BITMAPINFOHEADER *bmp_head;
bmp_head = (BITMAPINFOHEADER *)LocalAlloc
(LMEM_FIXED, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256);
RGBQUAD *bmp_palette;
bmp_palette = (RGBQUAD *)(bmp_head + 1);
//グローバルカラーマップの処理
BYTE *gif_data;
gif_data = data + sizeof(GIFHEADER);
if ( gif_info->state & 0x80 ) {
gif_palette = (GIFRGB *)gif_data;
for (int i=0; i<(2 << gif_color); i++) {
gif_data += sizeof(GIFRGB);
bmp_palette->rgbBlue = gif_palette->blue;
bmp_palette->rgbGreen = gif_palette->green;
bmp_palette->rgbRed = gif_palette->red;
gif_palette++;
bmp_palette++;
}
}
//GIF拡張ブロックを読み飛ばす。
while (*gif_data != 0x2C) {
gif_data+= 2;
while (*gif_data) {
gif_data += *(gif_data) + 1;
}
gif_data++;
}
//一枚目のイメージ記述情報を取得。
GIFIMAGEHEADER *gif_head;
gif_head = (GIFIMAGEHEADER *)gif_data;
//インタレースフラグ
DWORD gif_inter = gif_head->state & 0x40;
//ローカルカラーマップがある場合の処理
gif_data += sizeof(GIFIMAGEHEADER);
if (gif_head->state & 0x80) {
bmp_palette = (RGBQUAD *)(bmp_head + 1);
gif_color = gif_head->state & 0x07;
gif_palette = (GIFRGB *)gif_data;
for (int i=0; i<(2 << gif_color); i++) {
gif_data += sizeof(GIFRGB);
bmp_palette->rgbBlue = gif_palette->blue;
bmp_palette->rgbGreen = gif_palette->green;
bmp_palette->rgbRed = gif_palette->red;
gif_palette++;
bmp_palette++;
}
}
//DIB構造体(ヘッダ部)への書き込み
bmp_head->biSize = sizeof(BITMAPINFOHEADER);
bmp_head->biWidth = gif_head->width;
bmp_head->biHeight = gif_head->height;
bmp_head->biPlanes = 1;
bmp_head->biCompression = 0;
bmp_head->biSizeImage = 0;
bmp_head->biXPelsPerMeter = 0;
bmp_head->biYPelsPerMeter = 0;
bmp_head->biClrUsed = 0;
bmp_head->biClrImportant = 0;
//DIBヘッダサイズ及びDIBイメージサイズ決定
DWORD info_size;
DWORD img_size;
DWORD dib_align;
//カラービット数をDIBで使用できる値に強制変換(オーバーサンプル)
if (gif_color == 0) {
info_size = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*2;
dib_align = (((bmp_head->biWidth + 7) >> 3) + 3) & ~3;
img_size = dib_align * bmp_head->biHeight;
bmp_head->biBitCount = 1; //単色DIB
} else if (gif_color < 4) {
info_size = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*16;
dib_align = (((bmp_head->biWidth + 1) >> 1) + 3) & ~3;
img_size = dib_align * bmp_head->biHeight;
bmp_head->biBitCount = 4; //16色以下のGIFは16色DIBに強制変換
} else if (gif_color < 8) {
info_size = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256;
dib_align = (bmp_head->biWidth + 3) & ~3;
img_size = dib_align * bmp_head->biHeight;
bmp_head->biBitCount = 8; //256色以下のGIFは256色DIBに強制変換
} else {
return SPI_NOT_SUPPORT;
}
//親アプリに渡すDIB(ヘッダ/イメージ)領域を確保
*pHBInfo = LocalAlloc(LMEM_MOVEABLE, info_size);
*pHBm = LocalAlloc(LMEM_MOVEABLE, img_size);
//メモリ確保に失敗(メモリ不足?)
if (*pHBInfo == NULL || *pHBm == NULL) {
if (*pHBInfo == NULL) LocalFree(*pHBInfo);
if (*pHBm == NULL) LocalFree(*pHBm);
return SPI_NO_MEMORY;
}
//確保したメモリをロック
BYTE *pInfo = (BYTE *)LocalLock(*pHBInfo);
BYTE *pBm = (BYTE *)LocalLock(*pHBm);
//*pHBInfoにはBITMAPINFOを返却
memcpy(pInfo, bmp_head, info_size);
//*pHBmにはビットマップデータを返却
//GIF展開用関数コール(肝!)
GifDecode((BYTE *)pBm, gif_data, bmp_head->biWidth, bmp_head->biHeight,
dib_align, gif_inter, bmp_head->biBitCount, (DWORD)datasize-(gif_data-data));
//メモリをアンロック
LocalUnlock(*pHBm);
LocalUnlock(*pHBInfo);
//DIBヘッダ領域解放(テンポラリ用)
LocalFree(bmp_head);
return SPI_ALL_RIGHT;
}