一、BufferedImage介绍
image是一个抽象类,BufferedImage是其实现类,是一个带缓冲区图像类,主要作用是将一幅图片加载到内存中(BufferedImage生成的图片在内存里有一个图像缓冲区,利用这个缓冲区我们可以很方便地操作这个图片),提供获得绘图对象、图像缩放、选择图像平滑度等功能,通常用来做图片大小变换、图片变灰、设置透明不透明等。
二、BufferedImage继承关系
三、BufferedImage的组成
BufferedImage对象中最重要的两个组件是Raster与ColorModel,分别用于存储图像的像素数据和颜色数据。
图像像素的存储
图像的是以像素的形式存储在计算机中的,而像素在计算机中又以二进制表示。像素的存储空间取决于像素深度。
像素深度是指存储每个像素所用的位数,也用它来度量图像的分辨率。像素深度决定彩色图像的每个像素可能有的颜色数,或者确定灰度图像的每个像素可能有的灰度级数。如果只有两种颜色黑和白,一个像素用二进制的0或1表示。如果颜色是8位灰度图像,每个像素用一个8位二进制表示。在RGB模式中,一个像素相当于3个字节。
Raster对象的作用与像素存储
BufferedImage对象使用Raster来存储像素数组。Raster对象自己使用两个对象来存储像素,一个是DataBuffer,另一个是SampleModel。DataBuffer为Raster存储像素,SampleModel描述如何在DataBuffer定位给定样本值。
BufferedImage支持从Raster对象中获取任意位置(x,y)点的像素值p(x,y)
image.getRaster().getDataElements(x,y,width,height,pixels)
x,y表示开始的像素点,width和height表示像素数据的宽度和高度,pixels数组用来存放获取到的像素数据,image是一个BufferedImage的实例化引用。
图像类型与ColorModel
ColorModel用来存储像素的颜色值,ColorModel}抽象类封装了将像素值转换为颜色分量的方法(例如,红色、绿色和蓝色)和alpha分量。为了将图像呈现给屏幕、打印机或其他设备中,像素值必须转换为颜色和alpha分量。
java.awt.image包提供了4种颜色模型:
- PackedColorModel—一个抽象的ColorModel,表现其颜色成分直接嵌入成为该整数像素的数据位的像素值。DirectColorModel是PackedColorModel的子类。
- DirectColorModel— 一个ColorModel可以表现含有RGB颜色成分,并且其颜色成分直接嵌入作为该像素自身数据位的像素。DirectColorModel模型的观感与X11 TrueColor相似。
- ComponentColorModel—ColorModel可以处理任意的ColorSpace以及由颜色成分构成的、与ColorSpace相匹配的数组。
- IndexColorModel—一个ColorModel,所表现的像素值是一个sRGB颜色空间的固定颜色表的索引。
IndexColorModel的构造函数有五个参数:分别为
1)Bits:表示每个像素所占的位数,对RGB来说是8位
2)Size:表示颜色组件数组长度,对应RGB取值范围为0~255,值为256
3)r[]:字节数组r表示颜色组件的RED值数组
4)g[]:字节数组g表示颜色组件的GREEN值数组
5)b[]:字节数组b表示颜色组件的BLUE值数组
四、BufferedImage的操作
Java将一副图片加载到内存中的方法
BufferedImage bufferedImage = ImageIO.read(new FileInputStream(filePath));
远程图片转BufferedImage
/**
* 远程图片转BufferedImage
* @param destUrl 远程图片地址
* @return
*/
public static BufferedImage getBufferedImageDestUrl(String destUrl) {
HttpURLConnection conn = null;
BufferedImage image = null;
try {
URL url = new URL(destUrl);
conn = (HttpURLConnection) url.openConnection();
if (conn.getResponseCode() == 200) {
image = ImageIO.read(conn.getInputStream());
return image;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
conn.disconnect();
}
return image;
}
写图像文件的代码
File outputfile = new File("saved.png");
ImageIO.write(bufferedImage, "png",outputfile);
创建一个全新的BufferedImage对象,直接调用BufferedImage的构造函数
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY)
//其中width表示图像的宽度,height表示图像的高度,最后一个参数表示图像字节灰度图像
根据已经存在的BufferedImage对象来创建一个相同的copy体
public BufferedImage createBufferedImage(BufferedImage src){
ColorModel cm = src.getColorModel();
BufferedImage image = new BufferedImage(cm,
cm.creatCompatibleWritableRaster(
src.getWidth(),
src.getHeight()),
cm.isAlphaPremultiplied(), null);
return image;
}
实现图片拼接
/**
* 待合并的两张图必须满足这样的前提,如果水平方向合并,则高度必须相等;如果是垂直方向合并,宽度必须相等。
* mergeImage方法不做判断,自己判断。 * @param img1 待合并的第一张图
* @param img2 带合并的第二张图
* @param isHorizontal 为true时表示水平方向合并,为false时表示垂直方向合并
* @return 返回合并后的BufferedImage对象
* @throws IOException
*/
public static BufferedImage mergeImage(BufferedImage img1,
BufferedImage img2, boolean isHorizontal) throws IOException {
int w1 = img1.getWidth();
int h1 = img1.getHeight();
int w2 = img2.getWidth();
int h2 = img2.getHeight();
// 从图片中读取RGB
int[] ImageArrayOne = new int[w1 * h1];
ImageArrayOne = img1.getRGB(0, 0, w1, h1, ImageArrayOne, 0, w1); // 逐行扫描图像中各个像素的RGB到数组中
int[] ImageArrayTwo = new int[w2 * h2];
ImageArrayTwo = img2.getRGB(0, 0, w2, h2, ImageArrayTwo, 0, w2);
// 生成新图片
BufferedImage DestImage = null;
if (isHorizontal) { // 水平方向合并
DestImage = new BufferedImage(w1+w2, h1, BufferedImage.TYPE_INT_RGB);
DestImage.setRGB(0, 0, w1, h1, ImageArrayOne, 0, w1); // 设置上半部分或左半部分的RGB
DestImage.setRGB(w1, 0, w2, h2, ImageArrayTwo, 0, w2);
} else { // 垂直方向合并
DestImage = new BufferedImage(w1, h1 + h2, BufferedImage.TYPE_INT_RGB);
DestImage.setRGB(0, 0, w1, h1, ImageArrayOne, 0, w1); // 设置上半部分或左半部分的RGB
DestImage.setRGB(0, h1, w2, h2, ImageArrayTwo, 0, w2); // 设置下半部分的RGB
}
return DestImage;
}