GIF画像サイズを取得する方法は?


ペンた君  2003-07-24 13:50:21  No: 51819  IP: [192.*.*.*]

はじめまして!
GIFファイルを読み込んで画像サイズを取得し最終的には反転作業まで行いたいのですがGIFファイルの読み込み方法と画像サイズの取得方法が分かりません。
教えてください!!

編集 削除
YuO  2003-07-24 14:35:20  No: 51820  IP: [192.*.*.*]

> GIFファイルを読み込んで画像サイズを取得し最終的には反転作業まで行いたいのですがGIFファイルの読み込み方法と画像サイズの取得方法が分かりません。

とりあえず,こんなページがあります。
http://www.geocities.co.jp/SiliconValley/3453/gif_info/index_jp.html

画像サイズは簡単に読み込めますが,イメージデータの読み込みは,
LZWのデコードが絡むので面倒です。
#特許もあるし。

OleLoadPicture使って読み込んで,IPicture::Renderして,
それを反転させる方のが一番簡単だと思います。

編集 削除
ペンた君  2003-07-24 14:46:10  No: 51821  IP: [192.*.*.*]

ありがとうございます。
>OleLoadPicture使って読み込んで,IPicture::Renderして,
それを反転させる方のが一番簡単だと思います。

のやり方が分かりません。
サンプル的に教えていただけませんか?

編集 削除
ペンた君  2003-07-25 11:42:30  No: 51822  IP: [192.*.*.*]

>画像サイズは簡単に読み込めますが,

画像サイズはどのように取り込んだら良いのでしょうか?何度も試しましたが
出来ませんでした。

>OleLoadPicture使って読み込んで,IPicture::Renderして,
>それを反転させる方のが一番簡単だと思います。

例を挙げて教えてくださいませんか??

編集 削除
YuO  2003-07-25 13:17:07  No: 51823  IP: [192.*.*.*]

> 画像サイズはどのように取り込んだら良いのでしょうか?何度も試しましたが
> 出来ませんでした。

どのようなコードを書きましたか?
抜粋してみてください。


> >OleLoadPicture使って読み込んで,IPicture::Renderして,
> >それを反転させる方のが一番簡単だと思います。
> 例を挙げて教えてくださいませんか??

何がわからないのですか?
OleLoadPictureやIPicture::Renderを使った描画は検索エンジンで検索すれば見つかると思いますが。

編集 削除
ペンた君  2003-08-29 11:15:20  No: 51824  IP: [192.*.*.*]

純粋にC言語だけで(fread等で)GIFの画像サイズと縦・横のサイズの取得はできないのでしょうか?

編集 削除
YuO  2003-08-29 12:02:41  No: 51825  IP: [192.*.*.*]

> 純粋にC言語だけで(fread等で)GIFの画像サイズと縦・横のサイズの取得はできないのでしょうか?

可能ですよ。
私が2003/07/24(木) 14:35:20に書いたURLにある,GIFの仕様書(の邦訳)などを参考にすれば,
問題なく取得できると思いますが。

編集 削除
ペンた君  2003-08-29 12:45:54  No: 51826  IP: [192.*.*.*]

GIF Headerから画像全体の横と縦のサイズは取得できたのですが、imageblockのイメージサイズと縦と横のサイズが取得できません。それと、Global Color Tabelの取得の仕方がどうしても出来ませんでした。

編集 削除
ぺんた君  2003-09-04 10:02:14  No: 51827  IP: [192.*.*.*]

GIF Headerから画像全体の横と縦のサイズは取得できたのですが、imageblockのイメージサイズと縦と横のサイズが取得できません。それと、Global Color Tabelの取得の仕方がどうしても出来ませんでしたのでご教授願います。

編集 削除
Gak  2003-09-04 16:26:05  No: 51828  IP: [192.*.*.*]

> imageblockのイメージサイズと縦と横のサイズが取得できません。
GIFを解析している部分のコードを載せてみてはどうでしょう。
そうすれば回答を得やすいかと。

> Global Color Tabelの取得の仕方がどうしても出来ませんでしたのでご教授願います
仕様書にも書いてある通り、Global Color Tabel を持っていないGIFも存在します。
ですので、まずテストに使用したGIFが Global Color Tabel を持っているかを確認してみては。
いくら正しいコードを書いていても、存在しない Global Color Tabel は取得できませんから。

編集 削除
ぺんた君  2003-09-04 19:32:45  No: 51829  IP: [192.*.*.*]

//GIFHeader部分

int GetGIFSize(int GIFStream, int *gsize,
         int *width, int *height, int *Ncolos)
{
  unsigned char  count;
  unsigned char bitdata, bcindex,ratio;
  //int var_long;
  unsigned short var_short;
  unsigned char  s,s1;
  char color[765];

  //GIFファイルサイズ
  struct stat buf;
  fstat(GIFStream,&buf);
  *gsize = buf.st_size;

  // GIF 認識文字 "GIF" (0x47 0x49 0x46の固定値)
  if (_read(GIFStream,&s,3) == 3) {
    if (memcmp(&s, "GIF", 3) == 0) {
      printf("[GIF] GIF file\n");
    } 
    else {
     // fprintf(stderr, "%s : Not a GIF file\n", s);
      exit(1);
    }
    count += 3;
  }
   //ヴァージョンの確認 
   //("87a"の場合は,0x38 0x37 0x61の固定値 "89a"の場合は,0x38 0x39 0x61の固定値となる。)
  if (_read(GIFStream,&s1,3) == 3) {
    if (memcmp(&s1, "87a", 3)== 0) {
      printf("Version GIF file\n");
    }
  else if (memcmp(&s1, "89a", 3)== 0) {
      printf("Version GIF file\n");
    }
    else {
      //fprintf(stderr, "%s : Not a Version GIF file\n", s1);
      exit(1);
    }
    count += 3;
  }

    // GIF画像全体の幅 (0x1234の場合は,0x34 0x12と格納される。)
    if (_read(GIFStream,&var_short, 2) == 2) {
      printf("  Width         : %ld [pixel]\n", var_short);
      *width = var_short;
      count += 2;
    }
    // GIF画像全体の高さ (0x1234の場合は,0x34 0x12と格納される。)
    if (_read(GIFStream,&var_short, 2) == 2) {
       printf("  Height        : %ld [pixel]\n", var_short);
      *height = var_short;
      count += 2;
    }
  
  //color map がありますか??
  unsigned char b = count++;
  *Ncolos = 1 << ((b & 7) + 1);
  if ((b &0x80) == 0)
  { printf("No color map\n");
   *ncolors = 0;
  }

  //backgroud color 
  ++count;

  //bitdata読み込み
  if (_read(GIFStream,&bitdata, 1) == 1) {
    unsigned  bit = bitdata & 0x07;
    unsigned  bbit = 1 << bit + 1;

    unsigned  bbbit = bitdata >> 3;
    count +=1;
  }
  //背景色index
  if (_read(GIFStream,&bcindex, 1) == 1) {
      unsigned char bc = bcindex;
    printf(" \n");
      count += 1;
  }
  //ピクセルの縦横比
  if (_read(GIFStream,&ratio, 1) == 1) {
    unsigned char rt = ratio;
      printf(" \n");
    //*pixcel = (var_short + 15)/64; が実際の比率
      count += 1;
  }
  return count;
}
  
  //Global Color Table Flag が存在する場合のTableの情報
/*  int GIFColorTable(int GIFStream,
            int used,
            unsigned char *red, 
            unsigned char *green, 
            unsigned char *blue)
{
    int size,i;
    unsigned char colortable[256][3];
    
    struct channnel{
        Red = 0;
        Blue = 1;
        Green = 2;
    }
    
    for(i = 0;i<size;i++){
    _read(GIFStream,&colortable[i],3);
    }


  int receive,count;

  // ビットの並びは B G R 予約?????? 
  for (i = 0; i < used; i++) {
    blue[i] = _read(GIFStream,&blue,1);
    green[i] = _read(GIFStream,&green,1);
    red[i] = _read(GIFStream,&red,1);
    receive = _read(GIFStream,&receive,1);
    count++;
  }
  return count;
}*/
 
  

/*------------------------------------------------------------------*/
/* Image Block */
/*------------------------------------------------------------------*/
int ImageBlock(int  GIFStream,int *leftposition, int *topposition,
               int *imagew, int *imageh, int *bsize)
{
  int count = 0;
  int var_long;
  unsigned short var_short;
  unsigned char  s2;

  // Image Separator (1byte)
  if (_read(GIFStream,&s2, 1) == 1) {
    if (memcmp(&s2, "2c", 1)== 0) {
      printf("Image block\n");
  } 
    else {
      exit(1);
    }
  count += 1;
  }
  //Image Left Position (0x1234の場合は,0x34 0x12と格納される。)
    if (_read(GIFStream,&var_long, 2) == 2) {
      *leftposition = var_long;
      count += 2;
    }
    // Image TOP Position (0x1234の場合は,0x34 0x12と格納される。)
    if (_read(GIFStream,&var_long, 2) == 2) {
      *topposition = var_long;
      count += 2;
    }
    // ImageBlockの幅
    if (_read(GIFStream,&var_short, 2) == 2) {
      printf("  Width         : %d [pixel]\n", var_short);
      *imagew = var_short;
      count += 2;
    }
    // ImageBlockの高さ 
    if (_read(GIFStream,&var_short, 2) == 2) {
      printf("  Height        : %d [pixel]\n", var_short);
      *imageh = var_short;
      count += 2;
    }
  //Local Color Table Flag, Interlace Flag
  //Sort Flag, Reserved, Size of Local Color Table
  if (_read(GIFStream,&var_long, 1) == 1) {
      count += 1;
  }
  //Local Color Table (Global Color Table Flagが1の場合に存在する。)

  //LZW Mimimum Code Side(LZWコードの最小ビット数)
  if (_read(GIFStream,&var_long, 1) == 1) {
      count += 1;
  }
  //Block Size(イメージサイズ)
  if (_read(GIFStream,&var_long, 1) == 1) {
      printf("  Block Size      : %d [bit]\n", var_long);
      *bsize = var_long;
      count += 1;
  } 
  else {
    fprintf(stderr, "GIF Image Block error\n");
  }
   return count;
}


こんな感じでイメージサイズと高さ・幅を抽出できればと思ったのですがどうですか??

編集 削除
Gak  2003-09-05 13:58:58  No: 51830  IP: [192.*.*.*]

気づいた部分を修正してみました。
仕様書を見ながらソースを追えば解かってくるかと。
ただ動作確認していないので正しい保証はありません。参考程度に。

-----------------------------------------------
int GetGIFSize(
    int GIFStream,
    int *gsize,
    int *width,
    int *height,
    int *Ncolos
) {
        :省略

//  //color map がありますか??
//  unsigned char b = count++;
//  *Ncolos = 1 << ((b & 7) + 1);
//  if ((b &0x80) == 0) {
//      printf("No color map\n");
//      *ncolors = 0;
//  }
//
//  //backgroud color
//  ++count;

    //bitdata読み込み
    if (_read(GIFStream,&bitdata, 1) == 1) {
//    unsigned  bit = bitdata & 0x07;
//    unsigned  bbit = 1 << bit + 1;
//    
//    unsigned  bbbit = bitdata >> 3;
        count +=1;

        //  bitdataの最上位ビットをチェックしてGlobal Color Tableが存在するなら
        //  色数を得る。存在しない場合は 0 を設定
        *Ncolos = ((bitdata & 0x80) ? (2 << (bitdata & 0x07)) : 0);
    }

        :省略
}

//Global Color Table Flag が存在する場合のTableの情報
int GIFColorTable(
    int GIFStream,
    int used,
    unsigned char *red,
    unsigned char *green,
    unsigned char *blue
) {
    //  ビットの並びはRGB
    //  red,green,blueはメモリ確保済みとして
    for (int i = 0; i < used; i++) {
        _read(GIFStream, &red[i], 1);
        _read(GIFStream, &green[i], 1);
        _read(GIFStream, &blue[i], 1);
    }
    return used * 3  //  Tableのサイズ(Byte)を返しておく?
}

/*------------------------------------------------------------------*/
/* Image Block */
/*------------------------------------------------------------------*/
int ImageBlock(
    int  GIFStream,
    int *leftposition,
    int *topposition,
    int *imagew,
    int *imageh,
    int *bsize
) {
        :省略

//  // Image Separator (1byte)
//  if (_read(GIFStream,&s2, 1) == 1) {
//      if (memcmp(&s2, "2c", 1)== 0) {
//          printf("Image block\n");
//      }
//      else {
//          exit(1);
//      }
//      count += 1;
//  }

        :省略

//  //Block Size(イメージサイズ)
//  if (_read(GIFStream,&var_long, 1) == 1) {
//      printf("  Block Size      : %d [bit]\n", var_long);
//      *bsize = var_long;
//      count += 1;
//  } 
//  else {
//      fprintf(stderr, "GIF Image Block error\n");
//  }

    //Block Size(イメージサイズ)
    *bsize = 0;
    while (_read(GIFStream,&var_long, 1) == 1) {
        if (var_long == 0)  break;
        *bsize += (1 + var_long);  //  データ副ブロックのブロック寸法領域のサイズを足す
        _lseek(GIFStream, var_long, SEEK_CUR);  //  次のデータ副ブロック開始位置へ
    }
    return count + *bsize;
}

/*------------------------------------------------------------------*/
/* main
/*------------------------------------------------------------------*/
int main() {
    int GIFStream = _open("xxxx.gif", ...);

    //  Logical Screen Descriptor 情報取得
    int gsize, width, height, Ncolos;
    GetGIFSize(GIFStream, &gsize, &width, &height, &Ncolos);

    //  Global Color Table 情報取得
    if (Ncolos > 0)  GIFColorTable(GIFStream, Ncolos, ...);

    //  ブロックを解析
    int var_long, iImageNum = 0;
    while (_read(GIFStream, &var_long, 1) == 1) {
        switch (var_long) {
            case 0x2C:  //  イメージ記述ブロック
                ImageBlock(GIFStream, ...);
                iImageNum++;
                break;
            case 0x3B:  //  ストリーム終了
                goto End;
            case 0x21:  //  拡張ブロック
                _lseek(GIFStream, 1, SEEK_CUR);  //  ラベル領域分を飛ばす
            default:
                while (_read(GIFStream, &var_long, 1) == 1) {
                    if (var_long == 0)  break;
                    _lseek(GIFStream, var_long, SEEK_CUR);  //  次のデータ副ブロック開始位置へ
                }
                break;
        }
    }
:End
    //  後処理

    printf("%d 枚の画像が格納されています\n", iImageNum);
    return 0;
}

編集 削除
ペンた君  2003-09-05 16:04:13  No: 51831  IP: [192.*.*.*]

やって見たのですが、どうしてもGlobal Color Table でエラーが出てしまい回避出来ません。ご教授お願いします。

#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <io.h>
#include <fcntl.h>
#include <stdlib.h>



//GIFHeader部分

int GetGIFSize(int GIFStream, int *gsize,
         int *width, int *height, int *Ncolos)
{
  unsigned char  count;
  unsigned char bitdata, bcindex,ratio;
  //int var_long;
  unsigned short var_short;
  unsigned char  s,s1;
  char color[765];

  //GIFファイルサイズ
/*  struct stat buf;
  fstat(GIFStream,&buf);
  *gsize = buf.st_size;*/

  // GIF 認識文字 "GIF" (0x47 0x49 0x46の固定値)
  if (_read(GIFStream,&s,3) == 3) {
    if (memcmp(&s, "GIF", 3) == 0) {
      printf("[GIF] GIF file\n");
    } 
    else {
     // fprintf(stderr, "%s : Not a GIF file\n", s);
      exit(1);
    }
    count += 3;
  }
   //ヴァージョンの確認 
   //("87a"の場合は,0x38 0x37 0x61の固定値 "89a"の場合は,0x38 0x39 0x61の固定値となる。)
  if (_read(GIFStream,&s1,3) == 3) {
    if (memcmp(&s1, "87a", 3)== 0) {
      printf("Version GIF file\n");
    }
  else if (memcmp(&s1, "89a", 3)== 0) {
      printf("Version GIF file\n");
    }
    else {
      //fprintf(stderr, "%s : Not a Version GIF file\n", s1);
      exit(1);
    }
    count += 3;
  }

    // GIF画像全体の幅 (0x1234の場合は,0x34 0x12と格納される。)
    if (_read(GIFStream,&var_short, 2) == 2) {
      printf("  Width         : %ld [pixel]\n", var_short);
      *width = var_short;
      count += 2;
    }
    // GIF画像全体の高さ (0x1234の場合は,0x34 0x12と格納される。)
    if (_read(GIFStream,&var_short, 2) == 2) {
       printf("  Height        : %ld [pixel]\n", var_short);
      *height = var_short;
      count += 2;
    }
  
  //color map がありますか??
/*  unsigned char b = count++;
  *Ncolos = 1 << ((b & 7) + 1);
  if ((b &0x80) == 0)
  { printf("No color map\n");
   *ncolors = 0;
  }*/

  //backgroud color 
  //++count;

  //bitdata読み込み
  if (_read(GIFStream,&bitdata, 1) == 1) 
  {
//    unsigned  bit = bitdata & 0x07;
//    unsigned  bbit = 1 << bit + 1;

//    unsigned  bbbit = bitdata >> 3;
    count +=1;
    //bitdataの最上位ビットをチェックしてGlobal Color Table が存在するなら
    //色数を得る。存在しない場合は、0を設定。
    *Ncolos = ((bitdata & 0x80) ? (2 << (bitdata & 0x07)): 0); 
  }
  //背景色index
  if (_read(GIFStream,&bcindex, 1) == 1) {
      unsigned char bc = bcindex;
    printf(" \n");
      count += 1;
  }
  //ピクセルの縦横比
  if (_read(GIFStream,&ratio, 1) == 1) {
    unsigned char rt = ratio;
      printf(" \n");
    //*pixcel = (var_short + 15)/64; が実際の比率
      count += 1;
  }
  return count;
}
  
//Global Color Table Flag が存在する場合のTableの情報
int GIFColorTable(int GIFStream,
            long used,
            unsigned char *red, 
            unsigned char *green, 
            unsigned char *blue)
{
  //ビットの並びはRGB
  //red,blue,greenはメモリ確保済みとして、
  for(int i = 0; i < used; i++)
  {
    _read(GIFStream, &red[i], 1);
    _read(GIFStream, &green[i], 1);
    _read(GIFStream, &blue[i], 1);
  }

  return used*3;
}

  

/*------------------------------------------------------------------*/
/* Image Block */
/*------------------------------------------------------------------*/
int ImageBlock(int  GIFStream,int *leftposition, int *topposition,
               int *imagew, int *imageh, int *bsize)
{
  int count = 0;
  int var_long;
  unsigned short var_short;
  unsigned char  s2;

  // Image Separator (1byte)
/*  if (_read(GIFStream,&s2, 1) == 1) {
    if (memcmp(&s2, "2c", 1)== 0) {
      printf("Image block\n");
  } 
    else {
      exit(1);
    }
  count += 1;
  }*/
  //Image Left Position (0x1234の場合は,0x34 0x12と格納される。)
    if (_read(GIFStream,&var_long, 2) == 2) {
      *leftposition = var_long;
      count += 2;
    }
    // Image TOP Position (0x1234の場合は,0x34 0x12と格納される。)
    if (_read(GIFStream,&var_long, 2) == 2) {
      *topposition = var_long;
      count += 2;
    }
    // ImageBlockの幅
    if (_read(GIFStream,&var_short, 2) == 2) {
      printf("  ImWidth         : %d [pixel]\n", var_short);
      *imagew = var_short;
      count += 2;
    }
    // ImageBlockの高さ 
    if (_read(GIFStream,&var_short, 2) == 2) {
      printf("  ImHeight        : %d [pixel]\n", var_short);
      *imageh = var_short;
      count += 2;
    }
  //Local Color Table Flag, Interlace Flag
  //Sort Flag, Reserved, Size of Local Color Table
  if (_read(GIFStream,&var_long, 1) == 1) {
      count += 1;
  }
  //Local Color Table (Global Color Table Flagが1の場合に存在する。)

  //LZW Mimimum Code Side(LZWコードの最小ビット数)
  if (_read(GIFStream,&var_long, 1) == 1) {
      count += 1;
  }
  //Block Size(イメージサイズ)
  /*  if (_read(GIFStream,&var_long, 1) == 1) {
      printf("  Block Size      : %d [bit]\n", var_long);
      *bsize = var_long;
      count += 1;
  } 
  else {
    fprintf(stderr, "GIF Image Block error\n");
  }*/
  //Block Size(イメージサイズ)
  *bsize = 0;
  while (_read(GIFStream, &var_long, 1) == 1)
  {
    if(var_long == 0)  break;
    //データ副ブロックのブロック寸法領域のサイズを足す。
    *bsize += (1 + var_long); 
    //次のデータ副ブロック開始位置へ
    _lseek(GIFStream, var_long,SEEK_CUR);
  }

   return count + *bsize;
}

//main

int main()
{
  int GIFStream = _open("F:\\開発\\GIF関連\\GIF画像\\m1.gif", _O_RDONLY|_O_BINARY);

  //Logical Screen Descripter 情報取得
  int gsize, width, height, Ncolos;
  GetGIFSize(GIFStream, &gsize, &width, &height, &Ncolos);

  //Global Color Table情報取得
  int used ;
  unsigned char red,blue, green;
  if (Ncolos > 0) GIFColorTable(GIFStream, used, &red, &green, &blue);

  //ブロックを解析
  int var_long, iImageNum = 0;
  int leftposition, topposition, imagew, imageh, bsize;
  while (_read(GIFStream, &var_long, 1) == 1)
  {
    switch (var_long){
    case 0x2C :    //イメージ記述ブロック
        ImageBlock(GIFStream,&leftposition, &topposition, &imagew, &imageh, &bsize);
        iImageNum++;
        break;
    case 0x3B ://ストリーム終了
        goto End;
    case 0x21 : //拡張ブロック
        //ラベル領域を飛ばす!!
        _lseek(GIFStream, 1, SEEK_CUR); 
    default :
        while (_read(GIFStream, &var_long, 1) == 1){
          if (var_long == 0) break;
          //次のデータ副ブロックへ
          _lseek(GIFStream, var_long, SEEK_CUR);
        }
        break;
    }
  }
End:
    //後処理
    printf("%d枚の画像が格納されています。\n",iImageNum);
  return 0;
}

編集 削除
Gak  2003-09-05 17:39:38  No: 51832  IP: [192.*.*.*]

> //Global Color Table情報取得
> int used ;
> unsigned char red,blue, green;
> if (Ncolos > 0) GIFColorTable(GIFStream, used, &red, &green, &blue);

配列、又は malloc() 等を使用して必要なサイズ分のメモリを確保しないと…

> int var_long, iImageNum = 0;
> int leftposition, topposition, imagew, imageh, bsize;
> while (_read(GIFStream, &var_long, 1) == 1)

  var_long = 0xFFFFFFFF;
  _read(GIFStream, &var_long, 1)
と4バイトの変数に_read()で1バイトデータを読込む、なんてすると 
var_longの中身は 0xFFFFFF** と上位3バイトには以前の値が残り正確な値が取得できません。
(まあ、2つ目は私の書いたコードなんで私の間違いですが…)

こんなのが重なってエラーが出ているのでしょう。

とりあえずソース貼らせて貰います。VC6.0 + SP5 Win98 で動作確認済み。
後は仕様書を見ながらで何とかなるでしょう。

-----------------------------------------------
//GIFHeader部分
int GetGIFSize(int GIFStream, int *gsize, int *width,
               int *height, int *Ncolos)
{
    unsigned char  count = 0;
    unsigned char bitdata, bcindex,ratio;
    unsigned short var_short;
    unsigned char  s[4], s1[4];

    //  GIF 認識文字 "GIF" (0x47 0x49 0x46の固定値)
    if (_read(GIFStream,&s,3) == 3) {
        if (memcmp(&s, "GIF", 3) == 0)    printf("[GIF] GIF file\n");
        else    exit(1);
        count += 3;
    }

    //ヴァージョンの確認 
    //("87a"の場合は,0x38 0x37 0x61の固定値 "89a"の場合は,0x38 0x39 0x61の固定値となる。)
    if (_read(GIFStream,&s1,3) == 3) {
        if (memcmp(&s1, "87a", 3)== 0)        printf("Version GIF file\n");
        else if (memcmp(&s1, "89a", 3)== 0)   printf("Version GIF file\n");
        else    exit(1);
        count += 3;
    }

    // GIF画像全体の幅 (0x1234の場合は,0x34 0x12と格納される。)
    if (_read(GIFStream,&var_short, 2) == 2) {
        printf("  Width         : %ld [pixel]\n", var_short);
        *width = var_short;
        count += 2;
    }

    // GIF画像全体の高さ (0x1234の場合は,0x34 0x12と格納される。)
    if (_read(GIFStream,&var_short, 2) == 2) {
        printf("  Height        : %ld [pixel]\n", var_short);
        *height = var_short;
        count += 2;
    }

    //bitdata読み込み
    if (_read(GIFStream,&bitdata, 1) == 1) {
        count +=1;
        //bitdataの最上位ビットをチェックしてGlobal Color Table が存在するなら
        //色数を得る。存在しない場合は、0を設定。
        *Ncolos = ((bitdata & 0x80) ? (2 << (bitdata & 0x07)): 0); 
    }

    //背景色index
    if (_read(GIFStream,&bcindex, 1) == 1) {
        unsigned char bc = bcindex;
        printf(" \n");
        count += 1;
    }

    //ピクセルの縦横比
    if (_read(GIFStream,&ratio, 1) == 1) {
        unsigned char rt = ratio;
        printf(" \n");
        count += 1;
    }
    return count;
}
    
//Global Color Table Flag が存在する場合のTableの情報
int GIFColorTable(int GIFStream,
            long used,
            unsigned char *red, 
            unsigned char *green, 
            unsigned char *blue)
{
    //ビットの並びはRGB
    //red,blue,greenはメモリ確保済みとして、
    for(int i = 0; i < used; i++) {
        _read(GIFStream, &red[i], 1);
        _read(GIFStream, &green[i], 1);
        _read(GIFStream, &blue[i], 1);
    }
    return used*3;
}

/*------------------------------------------------------------------*/
/* Image Block */
/*------------------------------------------------------------------*/
int ImageBlock(int  GIFStream,int *leftposition, int *topposition,
               int *imagew, int *imageh, int *bsize)
{
    int count = 0;
    unsigned short var_short;

    //Image Left Position (0x1234の場合は,0x34 0x12と格納される。)
    if (_read(GIFStream,&var_short, 2) == 2) {
        *leftposition = var_short;
        count += 2;
    }

    // Image TOP Position (0x1234の場合は,0x34 0x12と格納される。)
    if (_read(GIFStream,&var_short, 2) == 2) {
        *topposition = var_short;
        count += 2;
    }

    // ImageBlockの幅
    if (_read(GIFStream,&var_short, 2) == 2) {
        printf("  ImWidth         : %d [pixel]\n", var_short);
        *imagew = var_short;
        count += 2;
    }

    // ImageBlockの高さ 
    if (_read(GIFStream,&var_short, 2) == 2) {
        printf("  ImHeight        : %d [pixel]\n", var_short);
        *imageh = var_short;
        count += 2;
    }

    //Local Color Table Flag, Interlace Flag
    //Sort Flag, Reserved, Size of Local Color Table
    unsigned char var_byte;
    if (_read(GIFStream,&var_byte, 1) == 1)    count += 1;
    if ((var_byte & 0x80)) {
        //Local Color Tableが存在したが面倒なので無視する
        _lseek(GIFStream, (2 << (var_byte & 0x07)), SEEK_CUR);
        count += (2 << (var_byte & 0x07));
    }

    //LZW Mimimum Code Side(LZWコードの最小ビット数)
    if (_read(GIFStream,&var_byte, 1) == 1) {
        count += 1;
    }

    //Block Size(イメージサイズ)
    *bsize = 0;
    while (_read(GIFStream, &var_byte, 1) == 1) {
        if(var_byte == 0)  break;
        //データ副ブロックのブロック寸法領域のサイズを足す。
        *bsize += (1 + var_byte); 
        //次のデータ副ブロック開始位置へ
        _lseek(GIFStream, var_byte, SEEK_CUR);
    }
    return count + *bsize;
}

int main() {
    int GIFStream = _open("F:\\siisiselogo.gif", _O_RDONLY|_O_BINARY);

    //Logical Screen Descripter 情報取得
    int gsize, width, height, Ncolos;
    GetGIFSize(GIFStream, &gsize, &width, &height, &Ncolos);

    //Global Color Table情報取得
    unsigned char *red, *blue, *green;
    red = blue = green = NULL;
    if (Ncolos > 0) {
        red    = (unsigned char*)malloc(Ncolos);
        blue  = (unsigned char*)malloc(Ncolos);
        green  = (unsigned char*)malloc(Ncolos);
        GIFColorTable(GIFStream, Ncolos, red, green, blue);
    }

    //ブロックを解析
    unsigned char var_byte;
    int iImageNum = 0;
    int leftposition, topposition, imagew, imageh, bsize;
    while (_read(GIFStream, &var_byte, 1) == 1)
    {
        switch (var_byte){
        case 0x2C :        //イメージ記述ブロック
                ImageBlock(GIFStream,&leftposition, &topposition, &imagew, &imageh, &bsize);
                iImageNum++;
                break;
        case 0x3B ://ストリーム終了
                goto End;
        case 0x21 : //拡張ブロック
                //ラベル領域を飛ばす!!
                _lseek(GIFStream, 1, SEEK_CUR); 
        default :
                while (_read(GIFStream, &var_byte, 1) == 1){
                    if (var_byte == 0) break;
                    //次のデータ副ブロックへ
                    _lseek(GIFStream, var_byte, SEEK_CUR);
                }
                break;
        }
    }
End:
    //後処理
    if (red != NULL)    free(red);
    if (green != NULL)  free(green);
    if (blue != NULL)   free(blue);
    _close(GIFStream);

    printf("%d枚の画像が格納されています。\n",iImageNum);
    return 0;
}

編集 削除
ぺんた君  2003-09-05 18:06:58  No: 51833  IP: [192.*.*.*]

ありがとうございます!!ここから以前Junixさんの掲示板を拝見しまして、
GifのPDF化に帰着したいのですが、イメージの高さ・幅・サイズのみでPDFにする事が出来るでしょうか??(JPEGは出来ていた、bmpはカラーパレットのオブジェクトを使用していたし、生のデータをstream間に挿入しなければならない。ということは、gifは・・・PDFのLZWDecodeのみで行けるのかな?)

編集 削除
ぺんた君  2003-09-08 10:03:39  No: 51834  IP: [192.*.*.*]

GIF画像のヘッダ部分を除いたイメージデータのみをメモ帳に表示することはできますか?

編集 削除
pbmplus  2003-09-08 10:31:20  No: 51835  IP: [192.*.*.*]

できません。バイナリエディタを使って観察してください。

編集 削除
ぺんた君  2003-09-08 11:31:03  No: 51836  IP: [192.*.*.*]

ご返答ありがとうございます。
ということは、stream間にイメージデータを挿入することはできないのでしょうか?自分の考えですが、LZWアルゴリズムのイメージデータ部分のみstream間に挿入すれば良いと考えたのですが、この考え方は間違っているのでしょうか??

編集 削除
pbmplus  2003-09-08 14:42:51  No: 51837  IP: [192.*.*.*]

私ができないと言ったのは「イメージデータをメモ帳で見ることはできない」ということです。
その他のことは、テスト&解析してみないと分かりません。ただ、「iText」(java)という著名な
ライブラリでも無圧縮GIFファイルは扱えてもLZWのGIFファイルは扱えませんから、LZWデータを
そのままstream間に突っ込むということはできないような気がします。

編集 削除
ぺんた君  2003-09-08 14:56:10  No: 51838  IP: [192.*.*.*]

ありがとうございます。ということは、LZWのGIFファイルはPDF化にできないということですね。無圧縮なGIFファイルならPDF化は可能ですか??

編集 削除
pbmplus  2003-09-08 19:28:27  No: 51839  IP: [192.*.*.*]

この辺りのことは実際にテスト&解析してみないと分かりません。
また、「iText」の例ではLZWライセンスを回避しながらGIF2PDFは
できないという事を例として出してみました。言葉足らずですみません。

前回の件を要約しますと、

< GIF2PDF(無圧縮) >
  LZWライセンスを回避して作成することができます。
< GIF2PDF(LZW)    >
  LZWライセンスを回避できない可能性が非常に高い。
  (圧縮されたデータを展開する必要があるかもしれない)

ということです。

おそらくこの辺りの情報はネット上などには流れていないと
思いますが、PDFファイルを解析しまくれば何とかなりますので、
がんばってください。

# GIF2PDF(無圧縮)については「iText」で吐き出されたファイルを解析すれば楽勝だと思います。

編集 削除
ぺんた君  2003-09-09 08:39:03  No: 51840  IP: [192.*.*.*]

ありがとうございます。大変勉強になりました。GIF2PDF(無圧縮)についての「iText」で吐き出されたファイルというのはどこにおいてあるのでしょうか?
また、言語はjavaな様ですが、C言語ではないでしょうか?何分C言語しか勉強していないので・・・

編集 削除
pbmplus  2003-09-09 18:13:45  No: 51841  IP: [192.*.*.*]

> ...「iText」で吐き出されたファイルというのはどこにおいてあるのでしょうか?

「iText」ライブラリ [en]
http://www.lowagie.com/iText/

「iTextFront」iTextを使っただけのソフトウェア [ja]
http://www.vector.co.jp/soft/win95/writing/se258136.html

ファイルは「iTextFront」を使ってGIF(無圧縮)からPDFファイルに変換して下さい。
あとはメモ帳(秀丸)とバイナリエディタを使って観察すればフォーマットがわかるかと思います。

<PDF作成ライブラリのリンク集(おまけ)>

PDFLib  (C言語など多種多様) [en]
http://www.pdflib.com/
CLibPDF (C言語など多種多様) [en]
http://www.fastio.com/
Hobbit's PDF Library  (java) [ja]
http://www.puzzle.gr.jp/programming/pdf/doc/index.html.ja
PDFJ (Perl) [ja]
http://hp1.jonex.ne.jp/~nakajima.yasushi/PDFJ.jp.html
ReportLab (Python?) [en] <- 作成されるファイルが壊れている場合がある
http://www.reportlab.com/
iText (java) [en]
http://www.lowagie.com/iText/
Ghostscript (C言語) [en]  <- 厳密に言うとライブラリではない
http://www.cs.wisc.edu/~ghost/
PowerPdf (Delphi) [en]
http://www.est.hi-ho.ne.jp/takeshi_kanno/powerpdf/

ほとんどがGNU系のライブラリと有料ライブラリです。
一般のフリーソフトはありません。非常に残念です。

編集 削除
ぺんた君  2003-09-10 09:23:24  No: 51842  IP: [192.*.*.*]

ありがとうございます。無圧縮のGIF画像はネットに転がっているのでしょうか??

編集 削除
pbmplus  2003-09-10 19:00:06  No: 51843  IP: [192.*.*.*]

Googleなどを使って検索してみてください。見つかるはずです。
http://www.google.co.jp/

編集 削除
ぺんた君  2003-09-11 12:42:55  No: 51844  IP: [192.*.*.*]

無圧縮のGIF画像を必死で探してみたんですけどありませんでした。どこかにおいてありそうなサイトってありますか?

編集 削除
pbmplus  2003-09-12 14:20:18  No: 51845  IP: [192.*.*.*]

こんな感じで探してください。
http://www.google.co.jp/search?hl=ja&ie=UTF-8&oe=UTF-8&q=GIF+%E7%84%A1%E5%9C%A7%E7%B8%AE+&lr=


UcGIF [bmp2gif]
http://www.h2.dion.ne.jp/~wogota/pub/pub2-00.htm
など、、、。

編集 削除
ぺんた君  2003-12-17 10:07:30  No: 51846  IP: [192.*.*.*]

お久しぶりです。色々調査しましたが、
LZWライセンスを使用した場合PDFにするには
どうすれば良いでしょうか??

編集 削除
通りすがり  2003-12-20 12:19:37  No: 51847  IP: [192.*.*.*]

たとえば pbmplus さんが一番上で紹介している PDFLib は
ドキュメントを読む限り GIF の読み込みに対応していると
あるので、多分LZW圧縮されたGIFファイルを読み込んで PDF
に変換することもできると思います。

ちゃんと調べましたか?

編集 削除
シャノン  2003-12-20 15:56:01  No: 51848  IP: [192.*.*.*]

LZW を使わない GIF のデコードもあるみたいよ。
こちらからどうぞ。

http://homepage1.nifty.com/uchi/

編集 削除