本文目录导读:

BufferedImage 是 Java 中处理图像的核心类,位于 java.awt.image 包下,它允许你在内存中创建一个可操作的图像缓冲区,并进行读取、绘制、像素操作和保存。
以下是 BufferedImage 最常用、最核心的操作指南。
创建 BufferedImage
通常有三种方式创建:
import java.awt.image.BufferedImage;
import java.awt.Color;
import java.awt.Graphics2D;
// 方法1:直接创建一个空白的 RGB 图像
int width = 200;
int height = 200;
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 方法2:创建带透明度的 ARGB 图像
BufferedImage transparentImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
// 方法3:从文件读取图像
// import javax.imageio.ImageIO;
// import java.io.File;
// BufferedImage loadedImage = ImageIO.read(new File("path/to/image.png"));
常见图像类型(imageType):
TYPE_INT_RGB:不透明,标准 RGB(红绿蓝)TYPE_INT_ARGB:带 Alpha 通道(透明度)TYPE_3BYTE_BGR:字节顺序为 BGR,常见于 Windows 图片
在图像上绘制(使用 Graphics2D)
这是最常用的方式——在图像上画线、文字、几何图形或贴图。
// 获取 Graphics2D 画笔(强烈推荐转型,功能更强)
Graphics2D g2d = image.createGraphics();
// --- 背景填充 ---
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, width, height); // 用白色填充整个画布
// --- 设置绘画属性 ---
g2d.setColor(Color.BLUE); // 设置画笔颜色
g2d.drawRect(10, 10, 100, 50); // 画矩形框
g2d.fillRect(50, 50, 80, 80); // 画实心矩形
// --- 画线 ---
g2d.setColor(Color.RED);
g2d.drawLine(0, 0, 200, 200); // 画一条对角线
// --- 画圆/椭圆 ---
g2d.setColor(Color.GREEN);
g2d.drawOval(20, 20, 100, 100); // 画圆框
g2d.fillOval(30, 30, 80, 80); // 画实心圆
// --- 画文字 ---
g2d.setColor(Color.BLACK);
g2d.setFont(new Font("Serif", Font.BOLD, 24));
g2d.drawString("Hello Java", 50, 150); // 在坐标(50,150)画文字
// --- 贴上另一张图(渲染另一个 BufferedImage) ---
BufferedImage logo = ImageIO.read(new File("logo.png"));
g2d.drawImage(logo, 10, 10, null); // 在(10,10)处贴图
// --- 释放资源(非常重要!)---
g2d.dispose();
⚠️ 每次使用
createGraphics()后,必须调用g2d.dispose()释放系统资源。
直接操作像素(获取/设置颜色)
如果你想逐像素修改图像(比如滤镜、颜色变换),可以直接访问像素数组。
getRGB / setRGB(简单但较慢,适合小区域)
// 获取某个像素的 ARGB 值
int x = 10, y = 20;
int argb = image.getRGB(x, y);
// 解析 ARGB(可选)
int alpha = (argb >> 24) & 0xFF;
int red = (argb >> 16) & 0xFF;
int green = (argb >> 8) & 0xFF;
int blue = argb & 0xFF;
// 创建一个新颜色并设置
Color color = new Color(255, 0, 0); // 红色,不透明
image.setRGB(x, y, color.getRGB()); // 设置像素
// 批量修改整块区域(性能好很多)
int[] pixels = image.getRGB(0, 0, width, height, null, 0, width);
for (int i = 0; i < pixels.length; i++) {
// 示例:将红色通道设为最大值
int rgb = pixels[i];
int alpha = (rgb >> 24) & 0xFF;
int red = 255; // 设为最红
int green = (rgb >> 8) & 0xFF;
int blue = rgb & 0xFF;
pixels[i] = (alpha << 24) | (red << 16) | (green << 8) | blue;
}
image.setRGB(0, 0, width, height, pixels, 0, width);
使用 Raster 和 DataBuffer(高性能,适合视频帧/实时处理)
// 获取像素数据数组(直接操作内存)
int[] data = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
for (int i = 0; i < data.length; i++) {
// 直接修改 data[i] 的 ARGB 值
}
// 注意:这种方法需要图像类型是 TYPE_INT_RGB 或 TYPE_INT_ARGB
// 且修改后图像自动更新,无需 setRGB
调整图像尺寸(缩放)
import java.awt.image.BufferedImage;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
public static BufferedImage resize(BufferedImage original, int newWidth, int newHeight) {
BufferedImage resized = new BufferedImage(newWidth, newHeight, original.getType());
Graphics2D g2d = resized.createGraphics();
// 启用抗锯齿,提高缩放质量
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.drawImage(original, 0, 0, newWidth, newHeight, null);
g2d.dispose();
return resized;
}
保存 BufferedImage 到文件
import javax.imageio.ImageIO;
import java.io.File;
import java.io.IOException;
try {
// 保存为 PNG(无损,支持透明)
ImageIO.write(image, "png", new File("output.png"));
// 保存为 JPG(有损,不支持透明,背景会变黑)
// ImageIO.write(image, "jpg", new File("output.jpg"));
System.out.println("图片保存成功!");
} catch (IOException e) {
e.printStackTrace();
}
⚠️ 如果图片带透明通道(ARGB),不要存成 JPG,否则透明部分会变黑色,存为 PNG 最安全。
常见陷阱与最佳实践
| 问题 | 解决方案 |
|---|---|
忘记调用 dispose() |
每次 createGraphics() 后 finally 或 try-with-resources 释放 |
| 透明背景变成黑色 | 使用 TYPE_INT_ARGB 创建,保存为 PNG |
| 坐标越界 | 始终检查 x>=0 && x<width && y>=0 && y<height |
| 性能慢(逐像素改) | 用 getRGB(..., pixelArray) 批量访问 |
| 图像类型不匹配 | 读取图片后可用 new BufferedImage(w, h, TYPE_INT_ARGB) 创建新画布再绘制 |
推荐模板:高效处理像素(颜色反转示例)
BufferedImage img = ImageIO.read(new File("input.jpg"));
int w = img.getWidth();
int h = img.getHeight();
// 确保类型是 INT_RGB 或 INT_ARGB
BufferedImage result = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics2D g = result.createGraphics();
g.drawImage(img, 0, 0, null);
g.dispose();
int[] pixels = result.getRGB(0, 0, w, h, null, 0, w);
for (int i = 0; i < pixels.length; i++) {
int argb = pixels[i];
int a = (argb >> 24) & 0xFF;
int r = 255 - ((argb >> 16) & 0xFF);
int g = 255 - ((argb >> 8) & 0xFF);
int b = 255 - (argb & 0xFF);
pixels[i] = (a << 24) | (r << 16) | (g << 8) | b;
}
result.setRGB(0, 0, w, h, pixels, 0, w);
ImageIO.write(result, "jpg", new File("inverted.jpg"));
掌握这些操作,你就能用 BufferedImage 完成大部分图像处理任务了,如果还有其他具体需求(如裁剪、滤镜、旋转),可以继续提问。