<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    小方的Java博客

      BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      27 隨筆 :: 17 文章 :: 115 評(píng)論 :: 0 Trackbacks
    摘要
        雖然 Java 提供了幾種打開(kāi)圖像的機(jī)制,但保存圖像并不是它的強(qiáng)項(xiàng)。這篇技巧將講述如何將圖像保存在 24 位位圖文件中。另外,Jean-Pierre 還提供了將圖像文件寫(xiě)入位圖文件所需的全部代碼。 
        這篇技巧是 "在 Java 應(yīng)用程序中加載位圖文件的逐步指南" 的補(bǔ)充,那篇技巧說(shuō)明了在 Java 應(yīng)用程序中加載位圖文件的過(guò)程。本月我再提供一篇教程,說(shuō)明如何將圖像保存在 24 位位圖文件中,其中還包含將圖像對(duì)象寫(xiě)入位圖文件的代碼片斷。 
        如果您在 Microsoft Windows 環(huán)境中工作,那么創(chuàng)建位圖文件的功能將為您提供許多方便。例如,在我的上一個(gè)項(xiàng)目中,我必須將 Java 與 Microsoft Access 對(duì)接。Java 程序允許用戶在屏幕上繪圖。這幅圖隨后被打印到 Microsoft Access 報(bào)表中。由于 Java 不支持 OLE,我的唯一選擇就是創(chuàng)建該圖的一個(gè)位圖文件,并通知 Microsoft Access 報(bào)表在何處能找到這個(gè)位圖文件。如果您寫(xiě)過(guò)向剪貼板發(fā)送圖像的應(yīng)用程序,則這個(gè)技巧可能對(duì)您有用 -- 尤其是當(dāng)您將這個(gè)信息傳遞給另一個(gè)應(yīng)用程序時(shí)。 

    位圖文件的格式
    位圖文件格式支持 4 位 RLE(行程長(zhǎng)度編碼)以及 8 位和 24 位編碼。因?yàn)槲覀冎惶幚?nbsp;24 位格式,所以下面我們查看一下該文件的結(jié)構(gòu)。 

    位圖文件分為三個(gè)部分。我已將它們列在下面。 

    第 1 部分:位圖文件的標(biāo)頭
    標(biāo)頭包含位圖文件的類型大小信息和版面信息。結(jié)構(gòu)如下(摘自 C 語(yǔ)言結(jié)構(gòu)定義): 

    typedef struct tagBITMAPFILEHEADER 
    {
       UINT bfType;
       DWORD bfSize;
       UINT bfReserved1;
       UINT bfReserved2;
       DWORD bfOffBits;
    }
    BITMAPFILEHEADER;


    下面是對(duì)這個(gè)清單中的代碼元素的說(shuō)明: 


    bfType:指定文件類型,其值始終為 BM。 

    bfSize:指定整個(gè)文件的大?。ㄒ宰止?jié)為單位)。 

    bfReserved1:保留 
    -- 必須為 0。 

    bfReserved2:保留 
    -- 必須為 0。 

    bfOffBits:指定從 BitmapFileHeader 到圖像首部的字節(jié)偏移量。 
    現(xiàn)在您已經(jīng)明白位圖標(biāo)頭的用途就是標(biāo)識(shí)位圖文件。讀取位圖文件的每個(gè)程序都使用位圖標(biāo)頭來(lái)進(jìn)行文件驗(yàn)證。 

    第 
    2 部分:位圖信息標(biāo)頭
    隨后的標(biāo)頭稱為信息標(biāo)頭,其中包含圖像本身的屬性。 

    下面說(shuō)明如何指定 Windows 
    3.0(或更高版本)設(shè)備獨(dú)立位圖 (DIB) 的大小和顏色格式: 

    typedef struct tagBITMAPINFOHEADER 
    {
        DWORD biSize;
        LONG biWidth;
        LONG biHeight;
        WORD biPlanes;
        WORD biBitCount;
        DWORD biCompression;
        DWORD biSizeImage;
        LONG biXPelsPerMeter;
        LONG biYPelsPerMeter;
        DWORD biClrUsed;
        DWORD biClrImportant;
    }
     BITMAPINFOHEADER;


    以上代碼清單的每個(gè)元素說(shuō)明如下: 


    biSize:指定 BITMAPINFOHEADER 結(jié)構(gòu)所需的字節(jié)數(shù)。 

    biWidth:指定位圖的寬度(以象素為單位)。 

    biHeight:指定位圖的高度(以象素為單位)。 

    biPlanes:指定目標(biāo)設(shè)備的位面數(shù)。這個(gè)成員變量的值必須為 
    1。 

    biBitCount:指定每個(gè)象素的位數(shù)。其值必須為 
    148 或 24。 

    biCompression:指定壓縮位圖的壓縮類型。在 
    24 位格式中,該變量被設(shè)置為 0。 

    biSizeImage:指定圖像的大小(以字節(jié)為單位)。如果位圖的格式是 BI_RGB,則將此成員變量設(shè)置為 
    0 是有效的。 

    biXPelsPerMeter:為位圖指定目標(biāo)設(shè)備的水平分辨率(以“象素
    /米”為單位)。應(yīng)用程序可用該值從最符合當(dāng)前設(shè)備特征的資源群組中選擇一個(gè)位圖。 

    biYPelsPerMeter:為位圖指定目標(biāo)設(shè)備的垂直分辨率(以“象素
    /米”為單位)。 

    biClrUsed:指定位圖實(shí)際所用的顏色表中的顏色索引數(shù)。如果 biBitCount 設(shè)為 
    24,則 biClrUsed 指定用來(lái)優(yōu)化 Windows 調(diào)色板性能的參考顏色表。 

    biClrImportant:指定對(duì)位圖的顯示有重要影響的顏色索引數(shù)。如果此值為 
    0,則所有顏色都很重要。 
    現(xiàn)在已定義了創(chuàng)建圖像所需的全部信息。 

    第 
    3 部分:圖像
    在 
    24 位格式中,圖像中的每個(gè)象素都由存儲(chǔ)為 BRG 的三字節(jié) RGB 序列表示。每個(gè)掃描行都被補(bǔ)足到 4 位。為了使這個(gè)過(guò)程稍復(fù)雜一點(diǎn),圖像是自底而上存儲(chǔ)的,即第一個(gè)掃描行是圖像中的最后一個(gè)掃描行。下圖顯示了標(biāo)頭 (BITMAPHEADER) 和 (BITMAPINFOHEADER) 以及部分圖像。各個(gè)部分由垂線分隔: 

    0000000000 4D42 B536 0002 0000 0000 0036 0000 | 0028
    0000000020 0000 0107 0000 00E0 0000 0001 0018 0000
    0000000040 0000 B500 0002 0EC4 0000 0EC4 0000 0000
    0000000060 0000 0000 0000 | FFFF FFFF FFFF FFFF FFFF
    0000000100 FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF
    *


    現(xiàn)在,我們開(kāi)始檢視代碼
    現(xiàn)在我們已經(jīng)知道了 
    24 位位圖文件的結(jié)構(gòu),下面就是您期待已久的內(nèi)容:用來(lái)將圖像對(duì)象寫(xiě)入位圖文件的代碼。 

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

    public class BMPFile extends Component {

      
    //--- 私有常量
      private final static int BITMAPFILEHEADER_SIZE = 14;
      
    private final static int BITMAPINFOHEADER_SIZE = 40;

      
    //--- 私有變量聲明

      
    //--- 位圖文件標(biāo)頭
      private byte bitmapFileHeader [] = new byte [14];
      
    private byte bfType [] = {'B''M'};
      
    private int bfSize = 0;
      
    private int bfReserved1 = 0;
      
    private int bfReserved2 = 0;
      
    private int bfOffBits = BITMAPFILEHEADER_SIZE + BITMAPINFOHEADER_SIZE;

      
    //--- 位圖信息標(biāo)頭
      private byte bitmapInfoHeader [] = new byte [40];
      
    private int biSize = BITMAPINFOHEADER_SIZE;
      
    private int biWidth = 0;
      
    private int biHeight = 0;
      
    private int biPlanes = 1;
      
    private int biBitCount = 24;
      
    private int biCompression = 0;
      
    private int biSizeImage = 0x030000;
      
    private int biXPelsPerMeter = 0x0;
      
    private int biYPelsPerMeter = 0x0;
      
    private int biClrUsed = 0;
      
    private int biClrImportant = 0;

      
    //--- 位圖原始數(shù)據(jù)
      private int bitmap [];

      
    //--- 文件部分
      private FileOutputStream fo;

      
    //--- 缺省構(gòu)造函數(shù)
      public BMPFile() {

      }



      
    public void saveBitmap (String parFilename, Image parImage, int
    parWidth, 
    int parHeight) {

         
    try {
            fo 
    = new FileOutputStream (parFilename);
            save (parImage, parWidth, parHeight);
            fo.close (); 
         }

         
    catch (Exception saveEx) {
            saveEx.printStackTrace ();
         }


      }



      
    /*
       * saveMethod 是該進(jìn)程的主方法。該方法
       * 將調(diào)用 convertImage 方法以將內(nèi)存圖像轉(zhuǎn)換為
       * 字節(jié)數(shù)組;writeBitmapFileHeader 方法創(chuàng)建并寫(xiě)入
       * 位圖文件標(biāo)頭;writeBitmapInfoHeader 創(chuàng)建 
       * 信息標(biāo)頭;writeBitmap 寫(xiě)入圖像。
       *
       
    */

      
    private void save (Image parImage, int parWidth, int parHeight) {

         
    try {
            convertImage (parImage, parWidth, parHeight);
            writeBitmapFileHeader ();
            writeBitmapInfoHeader ();
            writeBitmap ();
         }

         
    catch (Exception saveEx) {
            saveEx.printStackTrace ();
         }

      }



      
    /*
       * convertImage 將內(nèi)存圖像轉(zhuǎn)換為位圖格式 (BRG)。
       * 它還計(jì)算位圖信息標(biāo)頭所用的某些信息。
       *
       
    */

      
    private boolean convertImage (Image parImage, int parWidth, int parHeight) {

         
    int pad;
         bitmap 
    = new int [parWidth * parHeight];

         PixelGrabber pg 
    = new PixelGrabber (parImage, 00, parWidth, parHeight,
                                             bitmap, 
    0, parWidth);

         
    try {
            pg.grabPixels ();
         }

         
    catch (InterruptedException e) {
            e.printStackTrace ();
            
    return (false);
         }


         pad 
    = (4 - ((parWidth * 3% 4)) * parHeight;
         biSizeImage 
    = ((parWidth * parHeight) * 3+ pad;
         bfSize 
    = biSizeImage + BITMAPFILEHEADER_SIZE +
    BITMAPINFOHEADER_SIZE;
         biWidth 
    = parWidth;
         biHeight 
    = parHeight;

         
    return (true);
      }


      
    /*
       * writeBitmap 將象素捕獲器返回的圖像轉(zhuǎn)換為
       * 所需的格式。請(qǐng)記?。簰呙栊性谖粓D文件中是
       * 反向存儲(chǔ)的!
       *
       * 每個(gè)掃描行必須補(bǔ)足為 4 個(gè)字節(jié)。
       
    */

      
    private void writeBitmap () {

          
    int size;
          
    int value;
          
    int j;
          
    int i;
          
    int rowCount;
          
    int rowIndex;
          
    int lastRowIndex;
          
    int pad;
          
    int padCount;
          
    byte rgb [] = new byte [3];


          size 
    = (biWidth * biHeight) - 1;
          pad 
    = 4 - ((biWidth * 3% 4);
          
    if (pad == 4// <==== 錯(cuò)誤修正
             pad = 0// <==== 錯(cuò)誤修正
          rowCount = 1;
          padCount 
    = 0;
          rowIndex 
    = size - biWidth;
          lastRowIndex 
    = rowIndex;

          
    try {
             
    for (j = 0; j < size; j++{
                value 
    = bitmap [rowIndex];
                rgb [
    0= (byte) (value & 0xFF);
                rgb [
    1= (byte) ((value >> 8& 0xFF);
                rgb [
    2= (byte) ((value >> 16& 0xFF);
                fo.write (rgb);
                
    if (rowCount == biWidth) {
                   padCount 
    += pad;
                   
    for (i = 1; i <= pad; i++{
                      fo.write (
    0x00);
                   }

                   rowCount 
    = 1;
                   rowIndex 
    = lastRowIndex - biWidth;
                   lastRowIndex 
    = rowIndex;
                }

                
    else
                   rowCount
    ++;
                rowIndex
    ++;
             }


             
    //--- 更新文件大小
             bfSize += padCount - pad;
             biSizeImage 
    += padCount - pad;
          }

          
    catch (Exception wb) {
             wb.printStackTrace ();
          }


       }
     

      
    /*
       * writeBitmapFileHeader 將位圖文件標(biāo)頭寫(xiě)入文件中。
       *
       
    */

      
    private void writeBitmapFileHeader () {

         
    try {
            fo.write (bfType);
            fo.write (intToDWord (bfSize));
            fo.write (intToWord (bfReserved1));
            fo.write (intToWord (bfReserved2));
            fo.write (intToDWord (bfOffBits));

         }

         
    catch (Exception wbfh) {
            wbfh.printStackTrace ();
         }


      }


      
    /*
       *
       * writeBitmapInfoHeader 將位圖信息標(biāo)頭
       * 寫(xiě)入文件中。
       *
       
    */


      
    private void writeBitmapInfoHeader () {

         
    try {
            fo.write (intToDWord (biSize));
            fo.write (intToDWord (biWidth));
            fo.write (intToDWord (biHeight));
            fo.write (intToWord (biPlanes));
            fo.write (intToWord (biBitCount));
            fo.write (intToDWord (biCompression));
            fo.write (intToDWord (biSizeImage));
            fo.write (intToDWord (biXPelsPerMeter));
            fo.write (intToDWord (biYPelsPerMeter));
            fo.write (intToDWord (biClrUsed));
            fo.write (intToDWord (biClrImportant));
         }

         
    catch (Exception wbih) {
            wbih.printStackTrace ();
         }


      }



      
    /*
       *
       * intToWord 將整數(shù)轉(zhuǎn)換為單字,返回值
       * 存儲(chǔ)在一個(gè)雙字節(jié)數(shù)組中。
       *
       
    */

      
    private byte [] intToWord (int parValue) {

         
    byte retValue [] = new byte [2];

         retValue [
    0= (byte) (parValue & 0x00FF);
         retValue [
    1= (byte) ((parValue >> 8& 0x00FF);

         
    return (retValue);

      }


      
    /*
       *
       * intToDWord 將整數(shù)轉(zhuǎn)換為雙字,返回值
       * 存儲(chǔ)在一個(gè) 4 字節(jié)數(shù)組中。
       *
       
    */

      
    private byte [] intToDWord (int parValue) {

         
    byte retValue [] = new byte [4];

         retValue [
    0= (byte) (parValue & 0x00FF);
         retValue [
    1= (byte) ((parValue >> 8& 0x000000FF);
         retValue [
    2= (byte) ((parValue >> 16& 0x000000FF);
         retValue [
    3= (byte) ((parValue >> 24& 0x000000FF);

         
    return (retValue);

      }


    }

    小結(jié)
    這就是所要做的全部工作。我確信您將會(huì)發(fā)現(xiàn)這個(gè)類很有用,因?yàn)榈?nbsp;JDK 1.1.6 為止,Java 不支持用任何常用的格式保存圖像。JDK 1.2 將支持創(chuàng)建 JPEG 圖像,但不支持創(chuàng)建位圖。所以這個(gè)類仍將填補(bǔ) JDK1.2 中的空白。 

    如果您使用這個(gè)類并發(fā)現(xiàn)了改進(jìn)它的方法,請(qǐng)通知我!下面的個(gè)人簡(jiǎn)歷中有我的電子郵件地址。 

    作者簡(jiǎn)介
    jeanpierre.dube Jean-Pierre Dubé 是一名自由 Java 咨詢者。他于 1988 年注冊(cè)創(chuàng)辦了 Infocom公司。從那時(shí)起,Infocom 已承接并開(kāi)發(fā)了幾套應(yīng)用程序,涉及的領(lǐng)域包括制造業(yè)、文檔管理和大規(guī)模輸電線管理。他有豐富的 C 語(yǔ)言、Visual Basic 和 Java(最近)編程經(jīng)驗(yàn),他的公司現(xiàn)在主要使用 Java 語(yǔ)言。 Infocom 最近的一個(gè)項(xiàng)目是一種圖形 API,其測(cè)試版很快就會(huì)面市。  
    posted on 2006-02-01 12:27 方佳瑋 閱讀(896) 評(píng)論(0)  編輯  收藏 所屬分類: J2se 高級(jí)

    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 内射无码专区久久亚洲| 亚洲黄色中文字幕| 亚洲欧洲无卡二区视頻| 日韩视频免费在线观看| 日批日出水久久亚洲精品tv| 亚洲性一级理论片在线观看| 丝袜足液精子免费视频| 国产男女猛烈无遮挡免费网站| 亚洲精品免费在线视频| 中文字幕免费不卡二区| 亚洲精品成人网久久久久久| 亚洲乱色伦图片区小说| 黄网站色在线视频免费观看| 亚洲AV永久无码精品水牛影视| 手机永久免费的AV在线电影网| 免费看大美女大黄大色 | 亚洲日韩精品无码一区二区三区| 亚洲熟妇av午夜无码不卡 | 久久精品国产亚洲77777| 香蕉视频在线免费看| 日本不卡高清中文字幕免费| 亚洲欧洲校园自拍都市| 人人揉揉香蕉大免费不卡| 国产亚洲精品看片在线观看| 国产精品亚洲一区二区三区久久| 在线视频免费观看高清| 亚洲国产超清无码专区| 四虎影视在线影院在线观看免费视频| 久久久久亚洲精品中文字幕| 深夜福利在线免费观看| 国产精品免费看香蕉| 亚洲色成人网站WWW永久四虎 | 久久亚洲中文无码咪咪爱| 啦啦啦高清视频在线观看免费| 91亚洲国产成人久久精品网站| 免费在线观看一级片| 国产亚洲综合色就色| 18禁超污无遮挡无码免费网站| 亚洲老妈激情一区二区三区| 天黑黑影院在线观看视频高清免费| 久久亚洲国产成人影院网站|