home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 2001 January / VPR0101A.BIN / OLS / LZR100 / lzr100.lzh / Source / GIFSPI.cpp < prev    next >
C/C++ Source or Header  |  2000-10-07  |  7KB  |  214 lines

  1. /*--------------------------------------------------------------------------------------*/
  2. /*    非LZW理論GIFデコーダー <-> Susie Plug-in インターフェース 実装ファイル    Ver 1.00    */
  3. /*    for VisualStudio6.0 only                                                            */
  4. /*    ※サポート関数とGIFヘッダ解析部を実装。                                                */
  5. /*    Copyright (C) 2000 DJ☆Uchi [H.Uchida]                                                */
  6. /*--------------------------------------------------------------------------------------*/
  7. #include "SPIMain.h"
  8. #include "GIF.h"
  9.  
  10.  
  11. /*--------------------------------------------------------------------------------------*/
  12. /*    IsSupportedEx()                                                                        */
  13. /*    ヘッダ情報からファイル形式を調べる。                                                */
  14. /*    ※filnameはファイル名で、NULLが入っていることもある。                                */
  15. /*    ※dataはファイルのヘッダで、サイズは2000バイト。                                    */
  16. /*--------------------------------------------------------------------------------------*/
  17. BOOL IsSupportedEx(char *filename, char *data)
  18. {
  19.     GIFHEADER *gif_head;
  20.     gif_head = (GIFHEADER *)data;
  21.  
  22.     if ( gif_head->signature1 == 0x38464947 ) {    //識別子=GIF8+(7a or 9a)
  23.         return TRUE;
  24.     } else {
  25.         return FALSE;
  26.     }
  27. }
  28.  
  29.  
  30. /*--------------------------------------------------------------------------------------*/
  31. /*    GetPictureInfoEx()                                                                    */
  32. /*    画像ファイルの情報を書き込み、エラーコードを返す。                                    */
  33. /*    ※dataはファイルイメージで、サイズはdatasizeバイト。                                */
  34. /*    ※アニメーションGIFの場合は、一枚目の画像情報を返す。                                */
  35. /*--------------------------------------------------------------------------------------*/
  36. int GetPictureInfoEx(long datasize, struct PictureInfo *lpInfo, char *data)
  37. {
  38.     //グローバル画面記述情報を取得。
  39.     GIFHEADER *gif_info;
  40.     gif_info = (GIFHEADER *)data;
  41.  
  42.     //グローバルカラーマップ&GIF拡張ブロックを読み飛ばす。
  43.     char *ext_block;
  44.     ext_block = data + sizeof(GIFHEADER);
  45.     if ( gif_info->state & 0x80 ) ext_block += sizeof(GIFRGB) * (2 << (gif_info->state & 0x07));
  46.     while (*ext_block == 0x21) {
  47.         ext_block+= 2;
  48.         while (*ext_block) {
  49.             ext_block += *(ext_block) + 1;
  50.         }
  51.         ext_block++;
  52.     }
  53.  
  54.     //一枚目のイメージ記述情報を取得。
  55.     GIFIMAGEHEADER *gif_head;
  56.     gif_head = (GIFIMAGEHEADER *)ext_block;
  57.  
  58.     //PictureInfo構造体に値を返す。
  59.     lpInfo->left        = gif_head->left;
  60.     lpInfo->top            = gif_head->top;
  61.     lpInfo->width        = gif_head->width;
  62.     lpInfo->height        = gif_head->height;
  63.     lpInfo->x_density    = 0;
  64.     lpInfo->y_density    = 0;
  65.     lpInfo->colorDepth    = (gif_info->state & 0x07)+1;
  66.     //画像のテキスト情報には、とりあえず画像の形式(GIF87a/GIF89a)を入れておく。
  67.     char str[] = "GIF87a";
  68.     if ( gif_info->signature2 == 0x6139 ) str[4]='9';//GIF89a
  69.     HGLOBAL htxt = GlobalAlloc(GMEM_MOVEABLE, strlen(str)+1);
  70.     char *txt = (char *)GlobalLock(htxt);
  71.     strcpy(txt, str);
  72.     lpInfo->hInfo        = htxt;
  73.  
  74.     return SPI_ALL_RIGHT;
  75. }
  76.  
  77.  
  78. /*--------------------------------------------------------------------------------------*/
  79. /*    GetPictureEx()                                                                        */
  80. /*    画像ファイルをDIBに変換し、エラーコードを返す。                                        */
  81. /*    ※コールバック関数は未実装。                                                        */
  82. /*    ※dataはファイルイメージで、サイズはdatasizeバイト。                                */
  83. /*--------------------------------------------------------------------------------------*/
  84. int GetPictureEx(long datasize, HANDLE *pHBInfo, HANDLE *pHBm, SPI_PROGRESS, long, BYTE *data)
  85. {
  86.     //グローバル画面記述情報を取得。
  87.     GIFHEADER *gif_info;
  88.     gif_info = (GIFHEADER *)data;
  89.     GIFRGB *gif_palette = NULL;
  90.  
  91.     //元のGIFのカラービット数(8ビット以下)
  92.     BYTE gif_color = gif_info->state & 0x07;
  93.  
  94.     //DIBヘッダ領域確保(テンポラリ用、パレット×256固定) 
  95.     BITMAPINFOHEADER *bmp_head;
  96.     bmp_head = (BITMAPINFOHEADER *)LocalAlloc
  97.         (LMEM_FIXED, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256);
  98.     RGBQUAD *bmp_palette;
  99.     bmp_palette = (RGBQUAD *)(bmp_head + 1);
  100.  
  101.     //グローバルカラーマップの処理
  102.     BYTE *gif_data;
  103.     gif_data = data + sizeof(GIFHEADER);
  104.     if ( gif_info->state & 0x80 ) {
  105.         gif_palette = (GIFRGB *)gif_data;
  106.         for (int i=0; i<(2 << gif_color); i++) {
  107.             gif_data += sizeof(GIFRGB);
  108.             bmp_palette->rgbBlue = gif_palette->blue;
  109.             bmp_palette->rgbGreen = gif_palette->green;
  110.             bmp_palette->rgbRed = gif_palette->red;
  111.             gif_palette++;
  112.             bmp_palette++;
  113.         }
  114.     }
  115.  
  116.     //GIF拡張ブロックを読み飛ばす。
  117.     while (*gif_data != 0x2C) {
  118.         gif_data+= 2;
  119.         while (*gif_data) {
  120.             gif_data += *(gif_data) + 1;
  121.         }
  122.         gif_data++;
  123.     }
  124.  
  125.     //一枚目のイメージ記述情報を取得。
  126.     GIFIMAGEHEADER *gif_head;
  127.     gif_head = (GIFIMAGEHEADER *)gif_data;
  128.  
  129.     //インタレースフラグ
  130.     DWORD gif_inter = gif_head->state & 0x40;
  131.  
  132.     //ローカルカラーマップがある場合の処理
  133.     gif_data += sizeof(GIFIMAGEHEADER);
  134.     if (gif_head->state & 0x80) {
  135.         bmp_palette = (RGBQUAD *)(bmp_head + 1);
  136.         gif_color = gif_head->state & 0x07;
  137.         gif_palette = (GIFRGB *)gif_data;
  138.         for (int i=0; i<(2 << gif_color); i++) {
  139.             gif_data += sizeof(GIFRGB);
  140.             bmp_palette->rgbBlue = gif_palette->blue;
  141.             bmp_palette->rgbGreen = gif_palette->green;
  142.             bmp_palette->rgbRed = gif_palette->red;
  143.             gif_palette++;
  144.             bmp_palette++;
  145.         }
  146.     }
  147.  
  148.     //DIB構造体(ヘッダ部)への書き込み
  149.     bmp_head->biSize            = sizeof(BITMAPINFOHEADER);
  150.     bmp_head->biWidth            = gif_head->width;
  151.     bmp_head->biHeight            = gif_head->height;
  152.     bmp_head->biPlanes            = 1;
  153.     bmp_head->biCompression        = 0;
  154.     bmp_head->biSizeImage        = 0;
  155.     bmp_head->biXPelsPerMeter    = 0;
  156.     bmp_head->biYPelsPerMeter    = 0;
  157.     bmp_head->biClrUsed            = 0;
  158.     bmp_head->biClrImportant    = 0;
  159.  
  160.     //DIBヘッダサイズ及びDIBイメージサイズ決定
  161.     DWORD info_size;
  162.     DWORD img_size;
  163.     DWORD dib_align;
  164.     //カラービット数をDIBで使用できる値に強制変換(オーバーサンプル)
  165.     if (gif_color == 0) {
  166.         info_size = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*2;
  167.         dib_align = (((bmp_head->biWidth + 7) >> 3) + 3) & ~3;
  168.         img_size = dib_align * bmp_head->biHeight;
  169.         bmp_head->biBitCount = 1;    //単色DIB
  170.     } else if (gif_color < 4) {
  171.         info_size = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*16;
  172.         dib_align = (((bmp_head->biWidth + 1) >> 1) + 3) & ~3;
  173.         img_size = dib_align * bmp_head->biHeight;
  174.         bmp_head->biBitCount = 4;    //16色以下のGIFは16色DIBに強制変換
  175.     } else if (gif_color < 8) {
  176.         info_size = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256;
  177.         dib_align = (bmp_head->biWidth + 3) & ~3;
  178.         img_size = dib_align * bmp_head->biHeight;
  179.         bmp_head->biBitCount = 8;    //256色以下のGIFは256色DIBに強制変換
  180.     } else {
  181.         return SPI_NOT_SUPPORT;
  182.     }
  183.  
  184.     //親アプリに渡すDIB(ヘッダ/イメージ)領域を確保
  185.     *pHBInfo = LocalAlloc(LMEM_MOVEABLE, info_size);
  186.     *pHBm    = LocalAlloc(LMEM_MOVEABLE, img_size);
  187.     //メモリ確保に失敗(メモリ不足?)
  188.     if (*pHBInfo == NULL || *pHBm == NULL) {
  189.         if (*pHBInfo == NULL) LocalFree(*pHBInfo);
  190.         if (*pHBm == NULL) LocalFree(*pHBm);
  191.         return SPI_NO_MEMORY;
  192.     }
  193.  
  194.     //確保したメモリをロック
  195.     BYTE *pInfo = (BYTE *)LocalLock(*pHBInfo);
  196.     BYTE *pBm   = (BYTE *)LocalLock(*pHBm);
  197.     //*pHBInfoにはBITMAPINFOを返却
  198.     memcpy(pInfo, bmp_head, info_size);
  199.  
  200.     //*pHBmにはビットマップデータを返却
  201.     //GIF展開用関数コール(肝!)
  202.     GifDecode((BYTE *)pBm, gif_data, bmp_head->biWidth, bmp_head->biHeight,
  203.         dib_align, gif_inter, bmp_head->biBitCount, (DWORD)datasize-(gif_data-data));
  204.  
  205.     //メモリをアンロック
  206.     LocalUnlock(*pHBm);
  207.     LocalUnlock(*pHBInfo);
  208.  
  209.     //DIBヘッダ領域解放(テンポラリ用)
  210.     LocalFree(bmp_head);
  211.  
  212.     return SPI_ALL_RIGHT;
  213. }
  214.