首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

JBuilder 實現圖片屬性解析器:GIF/JPG/BMP/PNG 格式深度解析

     編輯:Java 相關知識

針對短信/彩信業務需解析圖片元數據(尺寸、色深、格式驗證),本文實現基於文件頭解析的純 Java 方案,不依賴 ImageIO,適合輕量級場景。

格式規範與文件頭結構

GIF

  • 簽名:GIF87a / GIF89a (偏移 0-5)
  • 寬度:偏移 6-7(小端序)
  • 高度:偏移 8-9(小端序)
  • 色深:偏移 10,公式 2^( (flag & 0x07) + 1 )

JPG (JFIF)

  • 簽名:JFIF (偏移 6-9)
  • SOF 段標記 0xFFC0 後:高度(2B)、寬度(2B)、精度(1B)、分量數(1B)…
  • 文中採用固定偏移近似方案(兩種常見結構),生產建議完整掃描段標記。
  • 色深:通常 24 位 → 16M。

BMP

  • 簽名:BM (偏移 0-1)
  • 寬度:偏移 18-21(小端序,4 字節)
  • 高度:偏移 22-25(小端序)
  • 色深:偏移 28(2 字節),公式 2^bits

PNG

  • 簽名:PNG (偏移 1-3)
  • IHDR 塊:寬度(偏移 16-19)、高度(20-23)、位深(24)、色彩類型(25)…
  • 文中固定偏移讀寬高,色深固定返回 16M。

核心代碼結構

模型類 PicsModel

public class PicsModel implements Serializable {
    private String picsExtendName; // 格式
    private int picsWidth, picsHeight;
    private String picsColor;      // 色深描述
    private String picsSize;       // 文件大小 KB/MB
    // getter/setter 省略
}

解析器 readpic

public class readpic {
    public static void main(String[] args) {
        PicsModel m = getFileAttributes("E:/test.jpg");
        System.out.println("格式:" + m.getPicsExtendName());
        System.out.println("寬:" + m.getPicsWidth() + " 高:" + m.getPicsHeight());
        System.out.println("色深:" + m.getPicsColor() + " 大小:" + m.getPicsSize());
    }

    private static PicsModel getFileAttributes(String path) {
        byte[] data = readFile(path);
        PicsModel m = new PicsModel();
        m.setPicsSize(formatSize(data.length));

        String fmt = detectFormat(data);
        m.setPicsExtendName(fmt);

        switch (fmt) {
            case "GIF": parseGIF(data, m); break;
            case "JPG": parseJPG(data, m); break;
            case "BMP": parseBMP(data, m); break;
            case "PNG": parsePNG(data, m); break;
        }
        return m;
    }

    // 讀取文件字節數組
    private static byte[] readFile(String path) throws IOException {
        try (FileInputStream in = new FileInputStream(path)) {
            byte[] buf = new byte[in.available()];
            in.read(buf);
            return buf;
        }
    }

    // 格式檢測:按簽名匹配
    private static String detectFormat(byte[] b) {
        if (b[0]==71 && b[1]==73 && b[2]==70 && b[3]==56 && (b[4]==55||b[4]==57) && b[5]==97) return "GIF";
        if (b[6]==74 && b[7]==70 && b[8]==73 && b[9]==70) return "JPG";
        if (b[0]==66 && b[1]==77) return "BMP";
        if (b[1]==80 && b[2]==78 && b[3]==71) return "PNG";
        return "UNKNOWN";
    }

    // 通用小端序讀取(GIF/BMP/PNG)
    private static int readLE(byte[] b, int offset, int len) {
        int val = 0;
        for (int i = len-1; i >= 0; i--) {
            val = (val << 8) | (b[offset+i] & 0xFF);
        }
        return val;
    }

    // 大端序讀取(JPG/JFIF 段)
    private static int readBE(byte[] b, int offset, int len) {
        int val = 0;
        for (int i = 0; i < len; i++) {
            val = (val << 8) | (b[offset+i] & 0xFF);
        }
        return val;
    }

    private static void parseGIF(byte[] b, PicsModel m) {
        m.setPicsWidth(readLE(b, 6, 2));
        m.setPicsHeight(readLE(b, 8, 2));
        int flag = b[10] & 0xFF;
        m.setPicsColor(formatColor(1 << ((flag & 0x07) + 1)));
    }

    private static void parseJPG(byte[] b, PicsModel m) {
        // 簡化:嘗試兩種常見偏移
        int w1 = readBE(b, 166, 2), h1 = readBE(b, 164, 2), c1 = (b[167] & 0xFF) * 8;
        if (w1>0 && h1>0 && c1<=24) { m.setPicsWidth(w1); m.setPicsHeight(h1); m.setPicsColor(formatColor(1<= 1048576) return (colors/1048576) + "M";
        if (colors >= 1024) return (colors/1024) + "K";
        return String.valueOf(colors);
    }

    private static String formatSize(long bytes) {
        if (bytes >= 1024) return (bytes/1024 + 1) + "K";
        return bytes + "B";
    }
}

圖片文件頭示意圖

GIF 文件頭結構

JPG 結構示例1

JPG 結構示例2 (畫圖保存後)

BMP 文件頭結構

PNG 文件頭結構

優化建議

  • JPG 完整解析:掃描 0xFFC0 SOF 標記,動態定位尺寸,避免固定偏移失效。
  • PNG 色深:解析 IHDR 塊的位深與色彩類型計算真實色數。
  • 大文件:使用 RandomAccessFile 僅讀取頭部,避免全量載入內存。
  • 生產環境優先使用 ImageIO 或 metadata-extractor 庫,標準、健壯、支持更多格式(EXIF、ICC Profile 等)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved