1x1pxのgifのjavaでの作成の覚書

 
tiutiu.net/ プログラム/language/java/gif01.html
2007/9/14
概要

1x1pxの赤gifファイルを作成します。 もっとも簡単なgifファイルの確認ですので, LZWアルゴリズムはプログラムには含まれていません。 iamge dataは机上で計算して作成しました。

コンパイル
$ javac mkgif.java
実行
$ java mkgif
ソース

ソースコードのファイル名はmkgif.javaです。

// mkgif

import java.io.*;

class mkgif {

  public static void main(String[] args) {
    try {
      // header
      byte[] signature = {0x47, 0x49, 0x46}; // GIF
      byte[] version   = {0x38, 0x39, 0x61}; // 89a
      // logical screen descriptor
      // 横幅=1px, リトルエンディアン
      byte[] screen_width = {0x01, 0x00};
      // 縦幅=1px, リトルエンディアン
      byte[] screen_height = {0x01, 0x00};
      byte[] screen_pack = new byte[1];
      int gct_flag = 0x80;  // gct=global color table
      int color_resolution = 0x00;
      // ここには色の指定(global color tableへのインデックス)に
      // 必要なbit数-1を設定する。
      // 赤だけなので1bitあればいいから0を設定
      int sort_flag = 0x00; // global table is not sorted.
      int size_of_gct = 0x00;
      screen_pack[0] = (byte)(gct_flag
                              | color_resolution
                              | sort_flag
                              | size_of_gct);
      byte[] background_color_index = {0x01};
      byte[] pixel_aspect_ratio = {0x00};
        // * 縦横比は設定しない。
      // global color table
      byte[] global_color_table = {
        -0x01, 0x00, 0x00,
           // * RGB順, -0x01=0xff(ややこしい!)
        0x00, 0x00, 0x00
      };

      // image descriptor
      byte[] image_separator = {0x2c};
      byte[] image_left_pos  = {0x00, 0x00};
      byte[] image_top_pos   = {0x00, 0x00};
      byte[] image_width     = {0x01, 0x00};
      byte[] image_height    = {0x01, 0x00};
      byte[] image_pack = new byte[1];
      // int local_color_table_flag = 0;
      // int interlace_flag = 0;
      // int sort_flag = 0;
      // int reserverd = 0;
      // int size_of_lct = 0;
      image_pack[0] = 0x00;
      
      // table based image data
      byte[] lzw_minimum_code_size = {0x02};
      // 一色なので1bitでいいのだが, 
      // 実装の都合上(?), 最低値が2(?)

      // lzw_minimum_code_sizeから
      // clear_codeは 100
      // したがって, 終了コードは101
      // したがって, 全体のコードは
      // 100...101となる。
      // clear_codeの直後は左上の画素の色の指定。
      // global color tableの0番目をここでは指定
      // するので, 0。ビット数を圧縮コードの長さ, 
      // ここではlzw_minimum_code_size+1=3bitに
      // 合わせるので000にする。
      // 先のclear_code, 終了コードとあわせて, 
      // 100 000 101
      // これを8bitづつにパックする。
      // 圧縮コードは左から右のまま, 右詰で
      // つめていく(あぁ, ややこしい)
      // 最初のclear_codeを設置
      //   xxxxx100
      // インデックスを追加
      //   xx000100
      // 終了コードを追加, 先頭の1bitがあまるが, 
      // それは2バイト目に右詰で追加。
      //   01000100 xxxxxxx1
      // 終わったので, 残りの未設定の部分を
      // 0で埋める。
      //   01000100 00000001
      byte[] block_size = {0x02};
      byte[] data_values = {0x44, 0x01};

      // block terminator
      byte[] block_terminator = {0x00};

      // trailer
      byte[] trailer = {0x3b}; // 固定

      // ファイルへの書き込み
      // 準備
      File fp = new File("red.gif");
      fp.createNewFile(); // 存在していた場合がないが...
      FileOutputStream fs = new FileOutputStream(fp);

      // 書き込んで行きましょう。
      fs.write(signature);
      fs.write(version);
      fs.write(screen_width);
      fs.write(screen_height);
      fs.write(screen_pack);
      fs.write(background_color_index);
      fs.write(pixel_aspect_ratio);
      fs.write(global_color_table);

      // image descriptor
      fs.write(image_separator);
      fs.write(image_left_pos);
      fs.write(image_top_pos);
      fs.write(image_width);
      fs.write(image_height);
      fs.write(image_pack);
      fs.write(lzw_minimum_code_size);
      fs.write(block_size);
      fs.write(data_values);
      fs.write(block_terminator);

      fs.write(trailer);

      // 書き込み終了
      fs.close();
    } catch(Exception e) {}
  } // main
}

// /mkgif
参考

仕様書, http://www.w3.org/Graphics/GIF/spec-gif89a.txt


Google