アルファチャネル付き画像をロードします。

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

プログラムの作成

  1. アルファチャネル付き BMP 画像をロードします。
    メモ帳などでタイプして AlphaLoad.java の名前で保存して下さい。
    //★ アルファチャネル設定 BMP を入力    前田 稔
    import java.awt.*;
    import java.awt.image.*;
    import javax.swing.*;
    import java.io.*;
    import javax.imageio.ImageIO;
    
    public class AlphaLoad extends JFrame
    {
        BufferedImage   aimg;
        String  Name = "C:\\DATA\\Test\\alph32.bmp";
    
        // Main
        public static void main(String args[])
        {   new AlphaLoad();  }
    
        // Constructor
        public AlphaLoad()
        {   super("アルファチャネル");
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setSize(480, 240);
    
            aimg= loadAlpha(Name);
            setVisible(true);
        }
    
        // Paint
        public void paint(Graphics g)
        {   Dimension  size = getSize();
            g.setColor(Color.blue);
            //g.setColor(Color.yellow);
            g.fillRect(0, 0, size.width, size.height);
            if (aimg!=null)
            {   g.drawImage(aimg,0,0,this);  }
        }
    
        // Alpha Cannel Image の入力
        public static BufferedImage loadAlpha(String fileName)
        {   BufferedImage img= null;
            int     width;
            int     height;
            int     len;
            byte[]  buf = new byte[64];
    
            try
            {   InputStream in = new FileInputStream(fileName);
                BufferedInputStream bin = new BufferedInputStream(in);
    
                // BITMAPFILEHEADER を入力
                if ((len= bin.read(buf, 0, 14))==-1)    return null;
                if (buf[0]!='B' || buf[1]!='M')     return img; // BMP以外
    
                // BITMAPINFOHEADER を入力
                if ((len= bin.read(buf, 0, 40))==-1)    return null;
                width= byte2int(buf, 4);
                height= byte2int(buf, 8);
                int  biBitCount= (buf[14]&0xFF) | ((buf[15]<<8)&0xFF00);
                if (biBitCount!=32) return null;        // 32bit以外
                int ary[] = new int[width * height];
                byte bt[] = new byte[width * height * 4];
                if ((len= bin.read(bt, 0, width*height*4))==-1) return null;
                bin.close();
                img= new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
                cvt(bt, ary);
                for(int y=0; y<height; y++)
                {   for(int x=0; x<width; x++)
                    {   img.setRGB(x, height-y-1, ary[y*width+x]);  }
                }
            }
            catch(Exception e) { }
            return img;
        }
    
        // byte[] ⇒ int[] 変換
        public static void cvt(byte[] bt, int ary[])
        {   for(int i=0; i<ary.length; i++)
                ary[i]= byte2int(bt, i*4);
        }
    
        // byte[] ⇒ int 変換
        public static int byte2int(byte[] buf, int p)
        {   return (buf[p]&0xFF) | ((buf[p+1]<<8)&0xFF00) | ((buf[p+2]<<16)&0xFF0000) | ((buf[p+3]<<24)&0xFF000000);
        }
    }
    
  2. アルファチャネル付き BMP 画像を直接ロードして描画します。
    Java にはアルファチャネル付き画像をロードするメソッドが見つからなかったので自前で作成しました。
    背景色を yellow に設定して見て下さい。
    画像が透けて背景色が見えていることが良く解るでしょう。
    g.setColor(Color.yellow);

プログラムの説明

  1. アルファチャネル付きの画像を作成するツールはインターネットで検索してもなかなか見つかりません。
    そこでアルファチャネル付きの画像を作成するツールを開発しました。
    前田稔の超初心者のプログラム入門の「Game Program & 各種 Tool」から提供しています。
    ところが、画像は作成出来ても Java にはアルファチャネル付きでロードする方法が見つかりません。
    仕方が無く、アルファチャネル付き BMP 画像をロードするメソッドを自前で開発しました。
    BufferedImage aimg がアルファチャネル付き BMP 画像をロードする領域で、"C:\\DATA\\Test\\alph32.bmp" がその名前です。
        BufferedImage   aimg;
        String  Name = "C:\\DATA\\Test\\alph32.bmp";
        
  2. アルファチャネル付きの画像をロードする loadAlpha() メソッドです。
    BufferedInputStream.read() でファイルからロードするのですが、入力領域は byte[] 配列で定義します。
    そこで byte[] 配列から int 型に変換するメソッドを作成しました。
    BMP 画像ファイルは BITMAPFILEHEADER と BITMAPINFOHEADER の二個のヘッダを持っています。
    BITMAPFILEHEADER の 'B' 'M' が BMPファイルのIDです。
    BITMAPINFOHEADER から画像の幅と高さを取得します。
    BMP の色モードが32ビット以外はサポートしません。
    二個のヘッダに続いてピクセル配列が格納されています。
    注意すべきことは、画像の上下が反対になっていることです。
    つまり最初のドットラインは一番下のラインで、最後のドットラインが一番上のラインです。
    必要最小限のコードしか書いていないので、読めないファイルがあるかも知れませんが、一応私が開発したツールで作成したファイルは確認済です。
    BMP ファイルの形式は 前田稔の超初心者のプログラム入門から 「C言語 Windows/BitMap(BMP)画像ファイル形式の説明書」を参照して下さい。
            try
            {   InputStream in = new FileInputStream(fileName);
                BufferedInputStream bin = new BufferedInputStream(in);
    
                // BITMAPFILEHEADER を入力
                if ((len= bin.read(buf, 0, 14))==-1)    return null;
                if (buf[0]!='B' || buf[1]!='M')     return img; // BMP以外
    
                // BITMAPINFOHEADER を入力
                if ((len= bin.read(buf, 0, 40))==-1)    return null;
                width= byte2int(buf, 4);
                height= byte2int(buf, 8);
                int  biBitCount= (buf[14]&0xFF) | ((buf[15]<<8)&0xFF00);
                if (biBitCount!=32) return null;        // 32bit以外
                int ary[] = new int[width * height];
                byte bt[] = new byte[width * height * 4];
                if ((len= bin.read(bt, 0, width*height*4))==-1) return null;
                bin.close();
                img= new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
                cvt(bt, ary);
                for(int y=0; y<height; y++)
                {   for(int x=0; x<width; x++)
                    {   img.setRGB(x, height-y-1, ary[y*width+x]);  }
                }
            }
        
  3. byte[] 配列から int 型及び、int[] 配列に変換するメソッドです。
        // byte[] ⇒ int[] 変換
        public static void cvt(byte[] bt, int ary[])
        {   for(int i=0; i<ary.length; i++)
                ary[i]= byte2int(bt, i*4);
        }
    
        // byte[] ⇒ int 変換
        public static int byte2int(byte[] buf, int p)
        {   return (buf[p]&0xFF) | ((buf[p+1]<<8)&0xFF00) | ((buf[p+2]<<16)&0xFF0000) | ((buf[p+3]<<24)&0xFF000000);
        }
        

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