隨筆-57  評(píng)論-202  文章-17  trackbacks-0
                要將BufferedImage實(shí)例保存為BMP文件,就需要知道BMP文件的格式,可以參考我轉(zhuǎn)載的文章:《BMP文件格式》
                下面是我的將BufferedImage實(shí)例保存為24位色BMP文件的實(shí)現(xiàn)。
                首先是BMP文件相關(guān)的兩個(gè)頭結(jié)構(gòu):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文件的頭結(jié)構(gòu)</p>
           * 
           * <p> Description: BMP文件的頭結(jié)構(gòu)固定是14個(gè)字節(jié),其定義如下:</p>
           * <p>
           * byte[2] bfType;                    指定文件類(lèi)型,必須是0x424D,即字符串“BM”,也就是說(shuō)所有.bmp文件的頭兩個(gè)字節(jié)都是“BM“
           * byte[4] bfSize;                    指定文件大小,包括這14個(gè)字節(jié)
           * byte[2] bfReserved1;            保留字
           * byte[2] bfReserved2;            保留字
           * byte[4] bfOffBits;                為從文件頭到實(shí)際的位圖數(shù)據(jù)的偏移字節(jié)數(shù)
           * </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文件內(nèi)容的頭結(jié)構(gòu)</p>
           *
           * <p>Description: BMP文件內(nèi)容的頭結(jié)構(gòu)固定是40個(gè)字節(jié),其定義如下:</p>
           * <p>
           * byte[4] biSize;                            指定這個(gè)結(jié)構(gòu)的長(zhǎng)度,為40
           * byte[4] biWidth;                            指定圖象的寬度,單位是象素
           * byte[4] biHeight;                        指定圖象的高度,單位是象素
           * byte[2] biPlanes;                        必須是1,不用考慮
           * byte[2] biBitCount;                    指定表示顏色時(shí)要用到的位數(shù),常用的值為1(黑白二色圖), 4(16色圖), 8(256色), 24(真彩色圖)
           * byte[4] biCompression;                指定位圖是否壓縮
           * byte[4] biSizeImage;                    指定實(shí)際的位圖數(shù)據(jù)占用的字節(jié)數(shù)
           * byte[4] biXPelsPerMeter;            指定目標(biāo)設(shè)備的水平分辨率,單位是每米的象素個(gè)數(shù)
           * byte[4] biYPelsPerMeter;            指定目標(biāo)設(shè)備的垂直分辨率,單位是每米的象素個(gè)數(shù)
           * byte[4] biClrUsed;                        指定本圖象實(shí)際用到的顏色數(shù),如果該值為零,則用到的顏色數(shù)為2biBitCount
           * byte[4] biClrImportant;            指定本圖象中重要的顏色數(shù),如果該值為零,則認(rèn)為所有的顏色都是重要的
           * </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寫(xiě)的接口類(lèi)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接口的實(shí)現(xiàn)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);
                            }

                        }

                    }

                }


          }


                一個(gè)工廠類(lèi)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);
              }

              
          }


                下面是我的測(cè)試用例:

          /*
           * 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) 評(píng)論(6)  編輯  收藏 所屬分類(lèi): Java

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

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

          我只看到 blank new了,但沒(méi)有附值.這一點(diǎn)不里解.請(qǐng)指教.謝謝!

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

          byte[width % 4];

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


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

          望賜教.謝謝!

          我的mail: wanglework@163.com  回復(fù)  更多評(píng)論
            
          # re: 如何將BufferedImage實(shí)例保存為BMP文件 2007-11-27 16:41 | wangle
          這里回復(fù)也可以! 我以后回常來(lái)拜訪(fǎng)的!!  回復(fù)  更多評(píng)論
            
          # re: 如何將BufferedImage實(shí)例保存為BMP文件 2007-12-09 17:19 | wangle
          呵呵,因?yàn)轫?xiàng)目里有一個(gè)關(guān)于解析BMP的問(wèn)題。在網(wǎng)上找到你這。
          自己敲過(guò)代碼后明白些了。謝謝?。?nbsp; 回復(fù)  更多評(píng)論
            
          主站蜘蛛池模板: 辰溪县| 平定县| 眉山市| 保定市| 常宁市| 蓬溪县| 青铜峡市| 通化市| 长丰县| 安陆市| 台山市| 巨野县| 抚顺县| 嘉荫县| 扎兰屯市| 襄垣县| 都匀市| 奉新县| 临安市| 鄂托克前旗| 屯留县| 漯河市| 黔南| 舟山市| 岳阳县| 平安县| 牡丹江市| 台江县| 河东区| 徐闻县| 禄丰县| 建德市| 濮阳县| 漯河市| 桃江县| 罗山县| 福清市| 河津市| 沿河| 思南县| 上高县|