隨筆-57  評論-202  文章-17  trackbacks-0
                要將BufferedImage實例保存為BMP文件,就需要知道BMP文件的格式,可以參考我轉載的文章:《BMP文件格式》。
                下面是我的將BufferedImage實例保存為24位色BMP文件的實現。
                首先是BMP文件相關的兩個頭結構:BMPFileHeader和BMPInfoHeader。

          /*
           * Created on 2005-6-21
           *
           * TODO To change the template for this generated file go to
           * Window - Preferences - Java - Code Style - Code Templates
           
          */

          package org.lotus.image.codec.bmp;

          /**
           * <p> Title: BMP文件的頭結構</p>
           * 
           * <p> Description: BMP文件的頭結構固定是14個字節,其定義如下:</p>
           * <p>
           * byte[2] bfType;                    指定文件類型,必須是0x424D,即字符串“BM”,也就是說所有.bmp文件的頭兩個字節都是“BM“
           * byte[4] bfSize;                    指定文件大小,包括這14個字節
           * byte[2] bfReserved1;            保留字
           * byte[2] bfReserved2;            保留字
           * byte[4] bfOffBits;                為從文件頭到實際的位圖數據的偏移字節數
           * </p>
           * 
           * <p> Copyright: Copyright (c) 2005</p>
           * 
           * <p> Company: 21Lotus</p>
           * 
           * @author George Hill
           * @version 1.0
           
          */


          class BMPFileHeader {

              
          // Header data
              private byte[] data = new byte[14];

              
          public byte[] getData() {
                  
          return this.data;
              }

              
              
          // BMP file size
              private int size;
              
              
          public int getSize() {
                  
          return this.size;
              }

              
              
          private int offset;
              
              
          public int getOffset() {
                  
          return this.offset;
              }

              
              BMPFileHeader(
          int size, int offset) {
                  
          this.size = size;
                  
          this.offset = offset;
                  
                  data[
          0= 'B';
                  data[
          1= 'M';

                  
          int value = size;
                  data[
          2= (byte) value;
                  value 
          = value >>> 8;
                  data[
          3= (byte) value;
                  value 
          = value >>> 8;
                  data[
          4= (byte) value;
                  value 
          = value >>> 8;
                  data[
          5= (byte) value;

                  value 
          = offset;
                  data[
          10= (byte) value;
                  value 
          = value >>> 8;
                  data[
          11= (byte) value;
                  value 
          = value >>> 8;
                  data[
          12= (byte) value;
                  value 
          = value >>> 8;
                  data[
          13= (byte) value;
              }

              
          }


          /*
           * Created on 2005-6-21
           *
           * TODO To change the template for this generated file go to
           * Window - Preferences - Java - Code Style - Code Templates
           
          */

          package org.lotus.image.codec.bmp;

          /**
           * <p>Title: BMP文件內容的頭結構</p>
           *
           * <p>Description: BMP文件內容的頭結構固定是40個字節,其定義如下:</p>
           * <p>
           * byte[4] biSize;                            指定這個結構的長度,為40
           * byte[4] biWidth;                            指定圖象的寬度,單位是象素
           * byte[4] biHeight;                        指定圖象的高度,單位是象素
           * byte[2] biPlanes;                        必須是1,不用考慮
           * byte[2] biBitCount;                    指定表示顏色時要用到的位數,常用的值為1(黑白二色圖), 4(16色圖), 8(256色), 24(真彩色圖)
           * byte[4] biCompression;                指定位圖是否壓縮
           * byte[4] biSizeImage;                    指定實際的位圖數據占用的字節數
           * byte[4] biXPelsPerMeter;            指定目標設備的水平分辨率,單位是每米的象素個數
           * byte[4] biYPelsPerMeter;            指定目標設備的垂直分辨率,單位是每米的象素個數
           * byte[4] biClrUsed;                        指定本圖象實際用到的顏色數,如果該值為零,則用到的顏色數為2biBitCount
           * byte[4] biClrImportant;            指定本圖象中重要的顏色數,如果該值為零,則認為所有的顏色都是重要的
           * </p>
           *
           * <p>Copyright: Copyright (c) 2005</p>
           *
           * <p>Company: 21Lotus</p>
           *
           * @author George Hill
           * @version 1.0
           
          */


          class BMPInfoHeader {

              
          private byte[] data = new byte[40];
              
              
          public byte[] getData() {
                  
          return this.data;
              }

              
              
          private int width;
              
              
          public int getWidth() {
                  
          return this.width;
              }

              
              
          private int height;
              
              
          public int getHeight() {
                  
          return this.height;
              }

              
              
          public int bitCount;
              
              
          public int getBitCount() {
                  
          return this.bitCount;
              }

              
              
          public BMPInfoHeader(int width, int height, int bitCount) {
                  
          this.width = width;
                  
          this.height = height;
                  
          this.bitCount = bitCount;
                  
                  data[
          0= 40;

                  
          int value = width;
                  data[
          4= (byte) value;
                  value 
          = value >>> 8;
                  data[
          5= (byte) value;
                  value 
          = value >>> 8;
                  data[
          6= (byte) value;
                  value 
          = value >>> 8;
                  data[
          7= (byte) value;

                  value 
          = height;
                  data[
          8= (byte) value;
                  value 
          = value >>> 8;
                  data[
          9= (byte) value;
                  value 
          = value >>> 8;
                  data[
          10= (byte) value;
                  value 
          = value >>> 8;
                  data[
          11= (byte) value;

                  data[
          12= 1;

                  data[
          14= (byte) bitCount;

                  value 
          = width * height * 3;
                  
          if (width % 4 != 0)
                    value 
          += (width % 4* height;
                  data[
          20= (byte) value;
                  value 
          = value >>> 8;
                  data[
          21= (byte) value;
                  value 
          = value >>> 8;
                  data[
          22= (byte) value;
                  value 
          = value >>> 8;
                  data[
          23= (byte) value;
              }

              
          }


                仿照com.sun.image.codec.jpeg.JPEGImageEncoder寫的接口類BMPEncoder。

          /*
           * Created on 2005-6-21
           *
           * TODO To change the template for this generated file go to
           * Window - Preferences - Java - Code Style - Code Templates
           
          */

          package org.lotus.image.codec.bmp;

          import java.awt.image.
          *;
          import java.io.IOException;

          /**
           * <p>Title: </p>
           *
           * <p>Description: </p>
           *
           * <p>Copyright: Copyright (c) 2005</p>
           *
           * <p>Company: 21Lotus</p>
           *
           * @author George Hill
           * @version 1.0
           
          */


          public interface BMPEncoder {

                
          public void encode(BufferedImage bi) throws IOException;
                
                
          public static final int BIT_COUNT_BLACKWHITE = 1;
                
          public static final int BIT_COUNT_16COLORS = 4;
                
          public static final int BIT_COUNT_256COLORS = 8;
                
          public static final int BIT_COUNT_TRUECOLORS = 24;
                
          }


                BMPEncoder接口的實現BMPEncoderImpl。

          /*
           * Created on 2005-6-21
           *
           * TODO To change the template for this generated file go to
           * Window - Preferences - Java - Code Style - Code Templates
           
          */

          package org.lotus.image.codec.bmp;

          import java.awt.image.
          *;
          import java.io.
          *;

          /**
           * <p>Title: </p>
           *
           * <p>Description: </p>
           *
           * <p>Copyright: Copyright (c) 2005</p>
           *
           * <p>Company: 21Lotus</p>
           *
           * @author George Hill
           * @version 1.0
           
          */


          class BMPEncoderImpl implements BMPEncoder {
              
              
          private OutputStream out;
              
              
          public BMPEncoderImpl(OutputStream out{
                  
          this.out = out;
              }

              
                
          public void encode(BufferedImage bi) throws IOException {
                    
          int width = bi.getWidth();
                    
          int height = bi.getHeight();
                    
                    boolean needBlank 
          = (width % 4 != 0);
                    
                    
          int size = width * height * 3;
                    
          if (needBlank) {
                        size 
          += (width % 4* height;
                    }

                    
                    BMPFileHeader fileHeader 
          = new BMPFileHeader(size, 54);
                    BMPInfoHeader infoHeader 
          = new BMPInfoHeader(width, height, BIT_COUNT_TRUECOLORS);

                    
          byte[] rgbs = new byte[3];
                    
          byte[] blank = new byte[width % 4];
                    
                    
          out.write(fileHeader.getData());
                    
          out.write(infoHeader.getData());

                    
          int index = 0;
                    
          for (int y = height - 1; y >= 0; y--{
                        
          for (int x = 0; x < width; x++{
                            index 
          += 3;

                            
          int rgb = bi.getRGB(x, y);
                            rgbs[
          0= (byte) rgb;
                            rgb 
          = rgb >>> 8;
                            rgbs[
          1= (byte) rgb;
                            rgb 
          = rgb >>> 8;
                            rgbs[
          2= (byte) rgb;

                            
          out.write(rgbs);

                            
          if (needBlank && (index % (width * 3== 0)) {
                                
          out.write(blank);
                            }

                        }

                    }

                }


          }


                一個工廠類BMPCodec。

          /*
           * Created on 2005-6-21
           *
           * TODO To change the template for this generated file go to
           * Window - Preferences - Java - Code Style - Code Templates
           
          */

          package org.lotus.image.codec.bmp;

          import java.io.OutputStream;

          /**
           * <p>Title: </p>
           *
           * <p>Description: </p>
           *
           * <p>Copyright: Copyright (c) 2005</p>
           *
           * <p>Company: 21Lotus</p>
           *
           * @author George Hill
           * @version 1.0
           
          */


          public class BMPCodec {

              
          public static BMPEncoder createBMPEncoder(OutputStream dest) {
                  
          return new BMPEncoderImpl(dest);
              }

              
          }


                下面是我的測試用例:

          /*
           * Created on 2005-6-22
           *
           * TODO To change the template for this generated file go to
           * Window - Preferences - Java - Code Style - Code Templates
           
          */

          package org.lotus.test;

          import java.awt.
          *;
          import java.awt.image.
          *;
          import java.io.
          *;

          import junit.framework.TestCase;

          import org.lotus.image.codec.bmp.
          *;

          /**
           * <p>Title: </p>
           *
           * <p>Description: </p>
           *
           * <p>Copyright: Copyright (c) 2005</p>
           *
           * <p>Company: 21Lotus</p>
           *
           * @author George Hill
           * @version 1.0
           
          */

          public class BMPCodecTest extends TestCase {

              
          /*
               * @see TestCase#setUp()
               
          */

              
          protected void setUp() throws Exception {
                  super.setUp();
              }


              
          /*
               * @see TestCase#tearDown()
               
          */

              
          protected void tearDown() throws Exception {
                  super.tearDown();
              }


              
          public void testCreateBMPEncoder() throws Exception {
                  
          int width = 104;
                  
          int height = 100;
                  
          int size = width * height * 3;
                  
          if (width % 4 != 0)
                    size 
          += (width % 4* height;
                  size 
          += 54;
                  BufferedImage image 
          = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
                  Graphics g 
          = image.getGraphics();
                  g.setColor(Color.WHITE);
                  g.fillRect(
          00, width, height);

                  g.setColor(Color.BLUE);
                  g.setFont(
          new Font("宋體", Font.ITALIC, 20));
                  g.drawString(
          "Hello"3030);
                  
                  BMPCodec.createBMPEncoder(
          new FileOutputStream("C:\\house\\test.bmp")).encode(image);
              }


          }


                保存的BMP文件如圖:

          test.JPG
          posted on 2005-07-04 17:33 小米 閱讀(3435) 評論(6)  編輯  收藏 所屬分類: Java

          評論:
          # re: 如何將BufferedImage實例保存為BMP文件 2005-07-05 21:24 | jek
          怎么才能使生成的bmp文件看上去更亂一些呢,例如驗證碼  回復  更多評論
            
          # re: 如何將BufferedImage實例保存為BMP文件 2005-07-06 09:37 | 小米
          這個可以看我的另外一篇隨筆《我的網頁附加碼實現》http://www.aygfsteel.com/georgehill/archive/2005/05/12/4228.html  回復  更多評論
            
          # re: 如何將BufferedImage實例保存為BMP文件 2007-11-27 16:29 | wangle

          if (needBlank && (index % (width * 3) == 0)) {
          out.write(blank);
          }

          我只看到 blank new了,但沒有附值.這一點不里解.請指教.謝謝!

          我的mail: wanglework@163.com  回復  更多評論
            
          # re: 如何將BufferedImage實例保存為BMP文件 2007-11-27 16:37 | wangle
          還對著幾句不理解:

          byte[width % 4];

          if (width % 4 != 0)
          size += (width % 4) * height;


          if (needBlank && (index % (width * 3) == 0))

          望賜教.謝謝!

          我的mail: wanglework@163.com  回復  更多評論
            
          # re: 如何將BufferedImage實例保存為BMP文件 2007-11-27 16:41 | wangle
          這里回復也可以! 我以后回常來拜訪的!!  回復  更多評論
            
          # re: 如何將BufferedImage實例保存為BMP文件 2007-12-09 17:19 | wangle
          呵呵,因為項目里有一個關于解析BMP的問題。在網上找到你這。
          自己敲過代碼后明白些了。謝謝!!  回復  更多評論
            
          主站蜘蛛池模板: 融水| 诸城市| 九龙县| 探索| 聂荣县| 上虞市| 古蔺县| 安溪县| 米林县| 布拖县| 霸州市| 五河县| 苍山县| 通河县| 丰台区| 于田县| 平和县| 杂多县| 苏州市| 桂阳县| 庆安县| 融水| 蒙城县| 尉犁县| 吉林省| 遵义市| 新源县| 三河市| 静安区| 全椒县| 平乐县| 磐石市| 集安市| 宁安市| 阿拉善左旗| 中方县| 常宁市| 盐城市| 北安市| 武威市| 兴海县|