• <label id="pxtpz"><meter id="pxtpz"></meter></label>
      1. <span id="pxtpz"><optgroup id="pxtpz"></optgroup></span>

        當前位置:雨林木風下載站 > 技術開發(fā)教程 > 詳細頁面

        用 Java 保存位圖文件

        用 Java 保存位圖文件

        更新時間:2022-04-30 文章作者:未知 信息來源:網(wǎng)絡 閱讀次數(shù):

        用 Java 保存位圖文件
        5/23/2001 9:28:10· Jean-Pierre Dubé·jdeveloper

        --------------------------------------------------------------------------------

        1 2下一頁


        摘要
          雖然 Java 提供了幾種打開圖像的機制,但保存圖像并不是它的強項。這篇技巧將講述如何將圖像保存在 24 位位圖文件中。另外,Jean-Pierre 還提供了將圖像文件寫入位圖文件所需的全部代碼。

          這篇技巧是 "在 Java 應用程序中加載位圖文件的逐步指南" 的補充,那篇技巧說明了在 Java 應用程序中加載位圖文件的過程。本月我再提供一篇教程,說明如何將圖像保存在 24 位位圖文件中,其中還包含將圖像對象寫入位圖文件的代碼片斷。

          如果您在 Microsoft Windows 環(huán)境中工作,那么創(chuàng)建位圖文件的功能將為您提供許多方便。例如,在我的上一個項目中,我必須將 Java 與 Microsoft Access 對接。Java 程序允許用戶在屏幕上繪圖。這幅圖隨后被打印到 Microsoft Access 報表中。由于 Java 不支持 OLE,我的唯一選擇就是創(chuàng)建該圖的一個位圖文件,并通知 Microsoft Access 報表在何處能找到這個位圖文件。如果您寫過向剪貼板發(fā)送圖像的應用程序,則這個技巧可能對您有用 -- 尤其是當您將這個信息傳遞給另一個應用程序時。

          位圖文件的格式

          位圖文件格式支持 4 位 RLE(行程長度編碼)以及 8 位和 24 位編碼。因為我們只處理 24 位格式,所以下面我們查看一下該文件的結構。

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

          第 1 部分:位圖文件的標頭

          標頭包含位圖文件的類型大小信息和版面信息。結構如下(摘自 C 語言結構定義):

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

         下面是對這個清單中的代碼元素的說明:

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

          bfSize:指定整個文件的大小(以字節(jié)為單位)。

          bfReserved1:保留 -- 必須為 0。

          bfReserved2:保留 -- 必須為 0。

          bfOffBits:指定從 BitmapFileHeader 到圖像首部的字節(jié)偏移量。

          現(xiàn)在您已經(jīng)明白位圖標頭的用途就是標識位圖文件。讀取位圖文件的每個程序都使用位圖標頭來進行文件驗證。

          第 2 部分:位圖信息標頭

          隨后的標頭稱為信息標頭,其中包含圖像本身的屬性。

          下面說明如何指定 Windows 3.0(或更高版本)設備獨立位圖 (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;

          
          以上代碼清單的每個元素說明如下:


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

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

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

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

           biBitCount:指定每個象素的位數(shù)。其值必須為 1、4、8 或 24。

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

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

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

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

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

           biClrImportant:指定對位圖的顯示有重要影響的顏色索引數(shù)。如果此值為 0,則所有顏色都很重要。

          現(xiàn)在已定義了創(chuàng)建圖像所需的全部信息。

          第 3 部分:圖像

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

        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)在我們已經(jīng)知道了 24 位位圖文件的結構,下面就是您期待已久的內容:用來將圖像對象寫入位圖文件的代碼。
        import java.awt.*;
        import java.io.*;
        import java.awt.image.*;

        public class BMPFile extends Component {

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

        file://--- 私有變量聲明

        file://--- 位圖文件標頭
        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;

        file://--- 位圖信息標頭
        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;

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

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

        file://--- 缺省構造函數(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 是該進程的主方法。該方法
        * 將調用 convertImage 方法以將內存圖像轉換為
        * 字節(jié)數(shù)組;writeBitmapFileHeader 方法創(chuàng)建并寫入
        * 位圖文件標頭;writeBitmapInfoHeader 創(chuàng)建
        * 信息標頭;writeBitmap 寫入圖像。
        *
        */
        private void save (Image parImage, int parWidth, int parHeight) {

        try {
        convertImage (parImage, parWidth, parHeight);
        writeBitmapFileHeader ();
        writeBitmapInfoHeader ();
        writeBitmap ();
        }
        catch (Exception saveEx) {
        saveEx.printStackTrace ();
        }
        }


        /*
        * convertImage 將內存圖像轉換為位圖格式 (BRG)。
        * 它還計算位圖信息標頭所用的某些信息。
        *
        */
        private boolean convertImage (Image parImage, int parWidth, int parHeight) {

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

        PixelGrabber pg = new PixelGrabber (parImage, 0, 0, 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 將象素捕獲器返回的圖像轉換為
        * 所需的格式。請記。簰呙栊性谖粓D文件中是
        * 反向存儲的!
        *
        * 每個掃描行必須補足為 4 個字節(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) // <==== 錯誤修正
        pad = 0; // <==== 錯誤修正
        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++;
        }

        file://--- 更新文件大小
        bfSize += padCount - pad;
        biSizeImage += padCount - pad;
        }
        catch (Exception wb) {
        wb.printStackTrace ();
        }

        }

        /*
        * writeBitmapFileHeader 將位圖文件標頭寫入文件中。
        *
        */
        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 將位圖信息標頭
        * 寫入文件中。
        *
        */

        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ù)轉換為單字,返回值
        * 存儲在一個雙字節(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ù)轉換為雙字,返回值
        * 存儲在一個 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);

        }

        }


          小結

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

        溫馨提示:喜歡本站的話,請收藏一下本站!

        本類教程下載

        系統(tǒng)下載排行

        主站蜘蛛池模板: 亚洲男同gay片| 老司机亚洲精品影院无码| 亚洲精品伊人久久久久| 最近免费中文字幕mv电影| 亚洲欧洲国产精品你懂的| 七色永久性tv网站免费看| 亚洲av日韩av无码黑人| 久久精品成人免费观看| 777亚洲精品乱码久久久久久| 91精品视频在线免费观看| 亚洲视频免费在线看| 免费AA片少妇人AA片直播| 亚洲伊人久久精品| 免费一本色道久久一区| 亚洲日本成本人观看| 国产免费看插插插视频| 午夜不卡AV免费| 国产AV无码专区亚洲Av| 一级毛片免费不卡在线| 亚洲成人黄色在线| 日韩高清在线免费观看| 无码免费又爽又高潮喷水的视频| 国产亚洲午夜高清国产拍精品| 成人网站免费大全日韩国产| 亚洲好看的理论片电影| 毛片免费观看网站| 九九九国产精品成人免费视频| 亚洲日韩精品无码专区网址| 在线观看免费视频资源| 亚洲精品国产第一综合99久久| 亚洲国产一区视频| 日韩精品人妻系列无码专区免费| 456亚洲人成影院在线观| 一本色道久久88亚洲综合| a在线观看免费网址大全| 亚洲一区二区三区在线观看蜜桃 | 污污免费在线观看| 久久亚洲高清观看| 成年女人毛片免费观看97| 色屁屁在线观看视频免费| 久久久久久亚洲Av无码精品专口|