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

Java 圖像處理基礎:ImageIO 讀寫與像素級操作完整指南

     編輯:Java 相關知識

核心類架構

  • BufferedImage:內存中圖像數據容器,包含 Raster (像素數據) + ColorModel (色彩空間解釋)
  • ImageIO:統一讀寫入口,支援插件擴展格式 (默認 JPEG/PNG/GIF/BMP/WBMP)
  • Raster / WritableRaster:像素數組的訪問接口,支援數組批量讀寫

基礎讀寫操作


// 讀取
File input = new File("input.jpg");
BufferedImage image = ImageIO.read(input); // 返回 null 表示格式不支援或損壞

// 寫入
File output = new File("output.png");
boolean success = ImageIO.write(image, "png", output); // 格式名區分大小寫
if (!success) throw new IllegalStateException("無對應 ImageWriter");

像素級讀寫:高性能批量操作

讀取像素到數組


int type = image.getType();
int w = image.getWidth(), h = image.getHeight();
int[] pixels = new int[w * h];

if (type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB) {
    // 直接從 Raster 獲取數組引用 (零拷貝)
    image.getRaster().getDataElements(0, 0, w, h, pixels);
} else {
    // 其他類型需轉換為 INT_ARGB 內部表示
    image.getRGB(0, 0, w, h, pixels, 0, w);
}

寫入像素數組


if (type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB) {
    image.getRaster().setDataElements(0, 0, w, h, pixels);
} else {
    image.setRGB(0, 0, w, h, pixels, 0, w);
}

ARGB 32位整數與顏色分量互轉


// 解包:0xAARRGGBB -> 四分量
int alpha = (argb >> 24) & 0xFF;
int red   = (argb >> 16) & 0xFF;
int green = (argb >> 8)  & 0xFF;
int blue  = argb & 0xFF;

// 打包:四分量 -> 0xAARRGGBB
int argb = (alpha << 24) | (red << 16) | (green << 8) | blue;

// 快捷方法 (Color 類)
Color c = new Color(argb, true); // true=hasAlpha
int r = c.getRed();
int argb2 = c.getRGB();

圖像加載進度監控:MediaTracker


// Swing 環境下異步加載大圖
MediaTracker tracker = new MediaTracker(component); // component 為 Component 實例
tracker.addImage(image, 0); // ID=0
new Thread(() -> {
    try { tracker.waitForID(0, 10000); } // 等待 10 秒
    catch (InterruptedException e) { /* 超時或中斷 */ }
    if (tracker.isErrorID(0)) { /* 加載失敗 */ }
    else { /* 加載成功,可安全繪製 */ }
}).start();

完整示例:程序化生成等離子體噪聲圖


public class PlasmaGenerator extends JComponent {
    private static final int SIZE = 256;
    private BufferedImage cachedImage;

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.drawImage(getPlasmaImage(), 10, 10, null);
    }

    private BufferedImage getPlasmaImage() {
        if (cachedImage != null) return cachedImage;

        cachedImage = new BufferedImage(SIZE, SIZE, BufferedImage.TYPE_INT_ARGB);
        int[] rgbData = new int[SIZE * SIZE];
        generatePlasma(rgbData);
        setRGB(cachedImage, 0, 0, SIZE, SIZE, rgbData);

        // 順便保存文件
        try { ImageIO.write(cachedImage, "jpg", new File("plasma.jpg")); }
        catch (IOException e) { e.printStackTrace(); }
        return cachedImage;
    }

    private void generatePlasma(int[] rgbData) {
        for (int y = 0; y < SIZE; y++) {
            for (int x = 0; x < SIZE; x++) {
                // 正弦波干涉產生等離子體效果
                double v = Math.sin((x + y) / 8.0) * 128 + 128;
                int c = clamp((int) v);
                int idx = y * SIZE + x;
                rgbData[idx] = (0xFF << 24) | (c << 16) | (c << 8) | c; // 灰階
            }
        }
    }

    private int clamp(int v) { return Math.max(0, Math.min(255, v)); }

    private void setRGB(BufferedImage img, int x, int y, int w, int h, int[] pixels) {
        int type = img.getType();
        if (type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB) {
            img.getRaster().setDataElements(x, y, w, h, pixels);
        } else {
            img.setRGB(x, y, w, h, pixels, 0, w);
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame f = new JFrame("Plasma Noise");
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.add(new PlasmaGenerator());
            f.pack();
            f.setLocationRelativeTo(null);
            f.setVisible(true);
        });
    }
}

擴展格式支援 (JPEG 2000, TIFF, WebP 等)

  1. 引入對應插件 JAR (如 twelvemonkeys-imageio)
  2. 或實現 ImageReader/WriterSpi 打包為 JAR
  3. 啟動參數註冊:-Xbootclasspath/a:plugins.jar (Java 8) / 模組化服務發現 (Java 9+)

總結

掌握 BufferedImage + ImageIO + Raster 三位一體,配合 getDataElements/setDataElements 批量像素操作,是 Java 圖像處理的性能基石。對於生產級圖像管道,建議引入 TwelveMonkeys ImageIO 擴展格式支援,並考慮 Java Advanced Imaging (JAI) 或 OpenCV Java Bindings 處理複雜算法。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved