Image(画像)の描画

Image(画像)の描画に付いてまとめてみました。

前田稔の超初心者のプログラム入門

画像形式

★サポートする画像形式
 ImageIO.getReaderFormatNames(), ImageIO.getWriterFormatNames() で確認できる。
※Java2 1.5.0_4
 読み: bmp / wbmp / jpeg / png / gif
 書き: bmp / wbmp / jpeg / png
※Java2 1.4.2_08
 読み: jpeg / png / gif
 書き: jpeg / png

参照ページ

    AWT(Abstract Windowing Tools)

  1. AWT で手軽に画像を描画するときは、次のページを参照して下さい。
    JPEG ファイルを表示する
  2. AWT で Sprite Class を使った例は、次のページを参照して下さい。
    AWT Sprite Class でアニメーション
  3. AWT で Double Buffer の効果を確かめるときは、次のページを参照して下さい。
    Window の回転で Double Buffer を使う

    Swing

  4. Swing で手軽に画像を描画するときは、次のページを参照して下さい。
    JPEG ファイルを表示する
  5. ImageIO で画像を取得するときは、次のページを参照して下さい。
    ImageIO で画像を入力する
  6. 画像を回転して描画するときは、次のページを参照して下さい。
    JPanel を継承すると Double Buffer が使われるので、チラツキが少なくなります。
    画像の回転
  7. 入力の完了を待って描画するときは、次のページを参照して下さい。
    入力の完了を待って描画する
  8. CARD Object Class で画像を切り分けるときは、次のページを参照して下さい。
    CARD Class で画像を切り分ける
  9. アニメーションするときは、次のページを参照して下さい。
    ANIME Class でアニメーション
  10. HTML タグで画像を取得するときは、次のページを参照して下さい。
    HTML タグで画像を取得する

    Java Applet

  11. Java Applet で手軽に画像を描画するときは、次のページを参照して下さい。
    Applet で画像を描画
  12. Java Applet で画像を描画する簡単な Class は、次のページを参照して下さい。
    imgclass で画像を描画
  13. Java Applet の card class を使った例は、次のページを参照して下さい。
    カードの画像を切り分けて描画する

画像の入力

  1. プログラムと同じフォルダーから入力します。
        Image   img;
        img = getToolkit().getImage("ayu.jpg");
        g.drawImage(img,16,40,this);
        
  2. フルパスで Animation GIF を入力します。
    フルパスで指定するときは、文字列の中で「\」を使うときは「\\」と書きます。
    Animation GIF を通常の画像と同様に描画するとアニメーションされます。
        Image   img;
        img = getToolkit().getImage("c:\\data\\test\\dog.gif");
        g.drawImage(img,16,40,this);
        
  3. 透明色を使うときは、透明色を設定して保存した GIF 形式、または PNG 形式を使って下さい。
  4. 画像サイズ(幅と高さ)は、次のメソッドで取得することが出来ます。
        Image   img;
        Width= img.getWidth(null);
        Height= img.getHeight(null);
        
  5. Java Applet の動作環境では、ローカルフォルダーはセキュリティで保護されています。
    一般的に画像は、アプレットのディレクトリ DocumentBase または CodeBase から入力します。
        getCodeBase()       :  classファイルがある URL を表す
        getDocumentBase()   :  Htmlファイルを URL で表す
        
        Image   img;
        img = getImage(getDocumentBase(),"ayu.jpg");
        

画像描画 Object Class

  1. 画像を切り分ける Sprite(CARD) Object Class です。
    AWT の class は Frame を継承しています。
    Swing の class は JFrame を継承します。
    Image img; は画像データ(イメージ)の領域です。
    Width, Height は Sprite(カード一枚分)の幅と高さです。
    Wnum, Hnum は切り分ける Sprite(カード)の横と縦の枚数です。
    frameNum は切り分ける Sprite(カード)の総枚数です。
        import java.awt.*;
    
        class Sprite extends Frame
        {   Image   img;
            int     Height,Width,Hnum,Wnum;
            int     frameNum;
        
  2. Java にはゲームプログラムで使えそうな構造体(Class)が用意されています。
    せっかくなので CARD Class に Dimension 構造体を使ってみます。
        class CARD extends JFrame
        {   private Image       Img;
            private Dimension   size;   // Sprite Size
            private Dimension   num;    // Sprite 並び数
            int     frameNum;
        
  3. Class の中に次の領域を定義することがあります。
    Sp_no は切り分けた Sprite の既定の番号で、99 のとき「描画しない」になります。
    posX, posY は描画する既定の座標で、float 型で計算します。
        int             Sp_no;          // CARD の番号
        float           posX, posY;     // CARD の座標
        
    Sp_no, posX, posY を使って描画するメソッドです。
        public void View(Graphics g)
        {   View(g, Sp_no, (int)posX, (int)posY);
        }
        
  4. Sprite(CARD) Object Class では Constructor で Sprite 一枚分のサイズまたは、並んでいる Sprite の枚数を受けて、 片方を画像サイズ(幅と高さ)から計算しています。
    このとき問題になるのが「画像を入力するのに多少時間がかかる」ことです。
    getToolkit().getImage() ではスレッドで画像の入力を開始すると制御は次の命令に移ります。
    入力が終了するまでは img.getWidth(null) や img.getHeight(null) の値は -1 になっています。
    そこで MediaTracker を使って入力が終了するのを待ち合わせます。
        img= getToolkit().getImage(filename);
        // MediaTracker で待ち合わせ
        MediaTracker tracker = new MediaTracker(new Component(){});
        tracker.addImage(img, 0);
        try
        {   tracker.waitForID(0);
        } catch(InterruptedException e){}
        
  5. MediaTracker を使わないで ImageIO で画像を取得する方法もあります。
    詳細は ImageIO で画像を入力する を参照して下さい。
    try と catch で例外が起こったときの処理を記述します。
        public static Image loadImage(String fileName)
        {   InputStream is = null;
            try
            {   is = new FileInputStream(fileName);
                Image img = ImageIO.read(is);
                return img;
            }
            catch (IOException e)
            {   throw new RuntimeException(e);  }
            finally
            {   if (is != null)
                    try { is.close(); }
                    catch (IOException e) {}
            }
        }
        
    ImageIO を使ってホームページの URL から画像を入力することも出来ます。
    img = loadImageUrl("http://www.eonet.ne.jp/~maeda/winc/img/ayu.jpg");
  6. Java3D では BufferedImage が使われます。
    BufferedImage も Image と同様に ImageIO で入力出来ます。
        import java.io.*;
        import javax.imageio.ImageIO;
        import java.awt.image.BufferedImage;
    
        public static BufferedImage loadImage(String fileName)
        {   InputStream is = null;
            try
            {   is = new FileInputStream(fileName);
                BufferedImage img = ImageIO.read(is);
                return img;
            }
            catch (IOException e)
            {   throw new RuntimeException(e);  }
            finally
            {   if (is != null)
                    try { is.close(); }
                    catch (IOException e) {}
            }
        }
        
  7. Image を BufferedImage に変換する方法です。
        // Image⇒BufferedImage
        public static BufferedImage createBufferedImage(Image img)
        {   BufferedImage bimg = new BufferedImage(img.getWidth(null),img.getHeight(null),BufferedImage.TYPE_INT_RGB);
            Graphics g = bimg.getGraphics();
            g.drawImage(img, 0, 0, null);
            g.dispose();
            return bimg;
        }
        
  8. Java Applet の DocumentBase(CodeBase) は init() メソッドの中では問題無いのですが、 new でインスタンス化した Class の中で使うと実行時にエラーが発生します。
    そこで init() メソッドで Image を取得して Constructor に渡します。
            //画像ロード
            MediaTracker mediaT = new MediaTracker(this);
            Image img = getImage(getDocumentBase(),"card.gif");
            mediaT.addImage(img,0);
            //ロード待ち
            try  {   mediaT.waitForAll();  }
            catch(InterruptedException e) { }
            obj = new card(img,56,65);
        
  9. Java Applet でも MediaTracker を使わないで ImageIO で画像を取得することも出来ます。
    class imgclass を作成して、Constructor で ImageIO を使ってみましょう。
    URL を使うので import java.net.URL; を取り込んで下さい。
  10. URL と画像ファイル名を結合して渡す場合の class imgclass です。
        // imgclass のインスタンス化
        obj = new imgclass(getCodeBase().toString() + "ayu.jpg"); 
    
        // Constructor
        imgclass(String path)
        {   try
            {   URL u = new URL(path);
                Img = ImageIO.read(u);
            }
            catch (IOException e)
            {   System.out.println("Image Load Error");
                Img= null;
            }
        }
        

アルファチャネルと透明色

Alpha Cannel とは R(赤), G(緑), B(青) 以外に A または W と呼ばれる Alpha Cannel を付加した画像です。
Alpha Cannel を使う事により、ピクセル単位で透明度の設定が可能になります。
Alpha Cannel 対応の BMP32bit ファイルの作成と描画ツールは 前田稔の超初心者のプログラム入門から「Game Program & 各種 Tool」から提供しています。
Alpha Cannel 付き BMP32bit 画像のロードは アルファチャネル付き画像をロード を参照して下さい。
  1. GIF や PNG には透明色を設定する機能があります。
    透明色を設定した画像をテクスチャで張り付けると透けて見えます。
    透明色を使うときは Appearance で setTransparencyAttributes を設定して下さい。
    サンプルプログラムは 矩形にテクスチャを貼付る を参照して下さい。
  2. ImageIO.read() で画像を入力すると、入力画像の形式に合わせて ColorModel が設定されるようです。
    TYPE_4BYTE_ABGR では、先頭から 24〜31= アルファ成分、16〜23= 赤色成分、8〜15= 緑色成分、0〜7= 青色成分です。
    アルファ成分の標準は 0XFF000000 の不透明で、ゼロに設定すると完全な透明になります。
    ImageIO.read() で入力した BufferedImage を getColorModel() で確認してみました。
  3. 透明色が設定された BufferedImage(GIF や PNG) に対して、BufferedImage.setRGB(x,y,0); でゼロを格納すると透明になります。
    アルファ成分にもゼロが設定されて、完全な透明になるものと思われます。
    透明色が設定されていなければ真っ黒になります。
    アルファ成分が変更されず 0XFF000000 になるためと思われます。
    色を透明にするプログラムは 指定された色を透明にする を参照して下さい。
    アルファチャネルを使ったプログラムは アルファチャネル設定イメージ を参照して下さい。
  4. TextureLoader() で直接画像を入力することも出来ます。
    Texture2D texture2d = (Texture2D)new TextureLoader("C:\\DATA\\Test\\star.gif",this).getTexture();
    便利なのですが、何故か透明色が効きません。

超初心者のプログラム入門(Java2)