版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013379717/article/details/89711193
一、绘制图形图像
/**
* 线段 / 折线
*/
public static void drawLine() throws IOException {
// 创建图像缓冲区(空图片)
BufferedImage bi = new BufferedImage(512, 512, BufferedImage.TYPE_INT_RGB);
// 创建 Graphics 的副本
Graphics2D g2d = bi.createGraphics();
// 抗锯齿
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// 设置画笔颜色
g2d.setColor(Color.RED);
// 1. 两点绘制线段: 点(20, 50), 点(200, 50)
g2d.drawLine(50, 50, 200, 50);
// 2. 多点绘制折线: 点(50, 100), 点(100, 130), 点(150, 70), 点(200, 100)
int[] xPoints = new int[] { 50, 100, 150, 200 };
int[] yPoints = new int[] { 100, 120, 80, 100 };
int nPoints = 4;
g2d.drawPolyline(xPoints, yPoints, nPoints);
// 3. 两点绘制线段(设置线宽为5px): 点(50, 150), 点(200, 150)
BasicStroke bs1 = new BasicStroke(5); // 笔画的轮廓(画笔宽度/线宽为5px)
g2d.setStroke(bs1);
g2d.drawLine(50, 150, 200, 150);
// 4. 绘制虚线: 将虚线分为若干段( 实线段 和 空白段 都认为是一段), 实线段 和 空白段 交替绘制,
// 绘制的每一段(包括 实线段 和 空白段)的 长度 从 dash 虚线模式数组中取值(从首
// 元素开始循环取值), 下面数组即表示每段长度分别为: 5px, 10px, 5px, 10px, ...
float[] dash = new float[] { 5, 10 };
BasicStroke bs2 = new BasicStroke(
1, // 画笔宽度/线宽
BasicStroke.CAP_SQUARE,
BasicStroke.JOIN_MITER,
10.0f,
dash, // 虚线模式数组
0.0f
);
g2d.setStroke(bs2);
g2d.drawLine(50, 200, 200, 200);
// 自己创建的副本用完要销毁掉
g2d.dispose();
// 保存文件
ImageIO.write(bi, "png", new File("F:/Tst/test-res.png"));
}
/**
* 矩形 / 多边形
*/
public static void drawRect() throws IOException {
// 创建图像缓冲区(空图片)
BufferedImage bi = new BufferedImage(512, 512, BufferedImage.TYPE_INT_RGB);
// 创建 Graphics 的副本
Graphics2D g2d = bi.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.GRAY);
// 1. 绘制一个矩形: 起点(30, 20), 宽80, 高100
g2d.drawRect(30, 20, 80, 100);
// 2. 填充一个矩形
g2d.fillRect(140, 20, 80, 100);
// 3. 绘制一个圆角矩形: 起点(30, 150), 宽80, 高100, 圆角宽30, 圆角高30
g2d.drawRoundRect(30, 150, 80, 100, 30, 30);
// 4. 绘制一个多边形(收尾相连): 点(140, 150), 点(180, 250), 点(220, 200)
int[] xPoints = new int[] { 140, 180, 220};
int[] yPoints = new int[] { 150, 250, 200};
int nPoints = 3;
g2d.drawPolygon(xPoints, yPoints, nPoints);
// 绘制一个3D矩形(左上或者右下的边框高亮实现的3D)
g2d.draw3DRect(300, 300, 80, 80, false);
// 填充一个3D矩形(左上或者右下的边框高亮实现的3D)
g2d.fill3DRect(400, 400, 80, 80, false);
g2d.dispose();
// 保存文件
ImageIO.write(bi, "png", new File("F:/Tst/test-res.png"));
}
/**
* 圆弧 / 扇形
*/
public static void drawArc() throws IOException {
// 创建图像缓冲区(空图片)
BufferedImage bi = new BufferedImage(512, 512, BufferedImage.TYPE_INT_RGB);
// 创建 Graphics 的副本
Graphics2D g2d = bi.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.RED);
// 1. 绘制一条圆弧: 椭圆的外切矩形 左上角坐标为(0, 0), 宽100, 高100,
// 弧的开始角度为0度, 需要绘制的角度数为-90度,
// 椭圆右边水平线为0度, 逆时针为正角度, 顺时针为负角度
g2d.drawArc(0, 0, 100, 100, 0, -90);
// 2. 绘制一个圆: 圆的外切矩形 左上角坐标为(120, 20), 宽高为100
g2d.drawArc(120, 20, 100, 100, 0, 360);
g2d.setColor(Color.GRAY);
// 3. 填充一个扇形
g2d.fillArc(80, 150, 100, 100, 90, 270);
g2d.dispose();
// 保存文件
ImageIO.write(bi, "png", new File("F:/Tst/test-res.png"));
}
/**
* 椭圆 (实际上通过绘制360度的圆弧/扇形也能达到绘制圆/椭圆的效果)
*/
public static void drawOval() throws IOException {
// 创建图像缓冲区(空图片)
BufferedImage bi = new BufferedImage(512, 512, BufferedImage.TYPE_INT_RGB);
// 创建 Graphics 的副本
Graphics2D g2d = bi.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.RED);
// 1. 绘制一个圆: 圆的外切矩形 左上角坐标为(0, 0), 宽高为100
g2d.drawOval(0, 0, 100, 100);
g2d.setColor(Color.GRAY);
// 2. 填充一个椭圆
g2d.fillOval(120, 100, 100, 150);
g2d.dispose();
// 保存文件
ImageIO.write(bi, "png", new File("F:/Tst/test-res.png"));
}
/**
* 文本
*/
public static void drawText() throws IOException {
// 创建图像缓冲区(空图片)
BufferedImage bi = new BufferedImage(512, 512, BufferedImage.TYPE_INT_RGB);
// 创建 Graphics 的副本
Graphics2D g2d = bi.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// 设置字体样式, null 表示使用默认字体, Font.PLAIN 为普通样式, 大小为 25px
g2d.setFont(new Font("楷体", Font.PLAIN, 25));
// 绘制文本, 其中坐标参数指的是文本绘制后的 左下角 的位置
// 首次绘制需要初始化字体, 可能需要较耗时
g2d.drawString("Hello World!", 20, 60);
g2d.drawString("你好, 世界!", 20, 120);
g2d.dispose();
// 保存文件
ImageIO.write(bi, "png", new File("F:/Tst/test-res.png"));
}
/**
* 图片 将一张图绘成另一张图
*/
public static void drawImage() throws IOException {
// 创建图像缓冲区(空图片)
BufferedImage bi = new BufferedImage(256, 256, BufferedImage.TYPE_INT_RGB);
// 创建 Graphics 的副本
Graphics2D g2d = bi.createGraphics();
// 从本地读取一张图片
BufferedImage src = ImageIO.read(new File("F:/Tst/test.png"));
// 绘制图片(如果宽高传的不是图片原本的宽高, 则图片将会适当缩放绘制)
g2d.drawImage(src, 50, 50, 100, 100, null);
g2d.dispose();
// 保存文件
ImageIO.write(bi, "png", new File("F:/Tst/test-res.png"));
}
2、修改背景颜色
/**
* 纯绘制图形,默认背景色黑色
*/
public static void drawImageInit() throws IOException{
// 创建图像缓冲区(空图片)
BufferedImage bi = new BufferedImage(256, 256, BufferedImage.TYPE_INT_RGB);
// 获取Graphics2D
Graphics2D g2d = bi.createGraphics();
// 绘制形状
g2d.setColor(Color.RED); // 设置填充的颜色 new Color(255, 0, 0)
g2d.fillRect(64, 64, 128, 128); // 填充的矩形,指定开始的x和y,指定矩的w和h
// 释放对象
g2d.dispose();
FileOutputStream out = new FileOutputStream("F:/Tst/test-res.png");
// 保存文件 方式一 文件更小
ImageIO.write(bi, "png", out);
// 保存文件 方式二 文件更大
ImageEncoder encoder = ImageCodec.createImageEncoder("PNG", out, new PNGEncodeParam.RGB());
encoder.encode(bi);
}
/**
* 纯绘制图形,修改背景色
*/
public static void drawImageChangeBackground() throws IOException{
//创建图像缓冲区
BufferedImage bi = new BufferedImage(256, 256, BufferedImage.TYPE_INT_RGB);
// 获取Graphics2D
Graphics2D g2d = bi.createGraphics();
// 修改背景色一 默认背景色为黑色,通过绘制充满整个图像缓冲区的填充可以实现修改背景色
g2d.setColor(Color.WHITE); // 设置填充的颜色
g2d.fillRect(0, 0, 256, 256); // 填充的矩形,指定开始的x和y,指定矩的w和h
// 修改背景色二 默认背景色为黑色,通过设置指定的背景色并使用填充矩形来清除背景色(原理一致)
g2d.setBackground(Color.WHITE); // 指定背景色,不影响当前容器的背景色,仅影响后续的clearRect操作和绘制图形的默认背景色
g2d.clearRect(0, 0, 256, 256); // 以当前背景色的填充来实现清除指定的矩形
// 绘制图形
g2d.setColor(Color.RED); // 设置填充的颜色
g2d.fillRect(64, 64, 128, 128); // 填充的矩形,指定开始的x和y,指定矩的w和h
// 释放对象
g2d.dispose();
// 保存文件
ImageIO.write(bi, "png", new File("F:/Tst/test.png"));
}
/**
* 纯绘制图形,修改背景色为透明
*/
public static void drawImageChangeTransparent() throws IOException{
//创建图像缓冲区
BufferedImage bi = new BufferedImage(256, 256, BufferedImage.TYPE_INT_RGB);
// 获取Graphics2D
Graphics2D g2d = bi.createGraphics();
// 设置背景色为透明
bi = g2d.getDeviceConfiguration().createCompatibleImage(256, 256, Transparency.TRANSLUCENT); // 重新获取图片缓冲区
g2d = bi.createGraphics(); // 重新获取Graphics2D
// 绘制图形
g2d.setColor(Color.RED); // 设置填充的颜色
g2d.fillRect(64, 64, 128, 128); // 填充的矩形,指定开始的x和y,指定矩的w和h
// 释放对象
g2d.dispose();
// 保存文件
ImageIO.write(bi, "png", new File("F:/Tst/test-res.png"));
}
3、图片背景和叠加
/**
* 图片缩放并添加背景板
*/
public static void resetImageInclude() throws IOException {
// 构造Image对象
BufferedImage src = ImageIO.read(new File("F:/Tst/test.png"));
// 创建和原图大小一致的容器
BufferedImage res = new BufferedImage(src.getWidth(), src.getHeight(), BufferedImage.TYPE_INT_RGB);
// 将图片缩小到原来的一半
Image content = src.getScaledInstance(src.getWidth() / 2, src.getHeight() / 2, BufferedImage.TYPE_INT_RGB);
// 填充容器的颜色,即背景颜色
res.getGraphics().setColor(Color.WHITE);
res.getGraphics().fillRect(0, 0, src.getWidth(), src.getHeight());
// 将缩小后的图片写入容器的中间位置
res.getGraphics().drawImage(content, src.getWidth() / 4, src.getHeight() / 4, src.getWidth() / 2, src.getHeight() / 2, null);
FileOutputStream out = new FileOutputStream("F:/Tst/test-res.png");
// 保存图片
ImageEncoder encoder = ImageCodec.createImageEncoder("PNG", out, new PNGEncodeParam.Palette());
encoder.encode(res);
}
/**
* 将一张图片添加到另一张图片之上
*/
public static void mergeBothImage() throws IOException {
// 构造Image对象
BufferedImage image = ImageIO.read(new File("F:/Tst/test.png"));
BufferedImage icon = ImageIO.read(new File("F:/Tst/icon.png"));
// 添加
image.getGraphics().drawImage(icon, 100, 100, null);
// 保存
ImageIO.write(image, "PNG", new File("F:/Tst/test-res.png"));
}
/**
* 设置叠加图片的透明度
*/
public static void clipFillet4() throws IOException {
// 构造Image对象
BufferedImage image = ImageIO.read(new File("F:/Tst/test.png"));
BufferedImage icon = ImageIO.read(new File("F:/Tst/t1.png"));
Graphics2D g2d = image.createGraphics();
// 设置透明度
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.5f)); // 透明度设置开始(0<alpha<1,0为透明,1为不透明)
// 添加
g2d.drawImage(icon, 100, 100, null);
// 结束透明度
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); // 透明度设置 结束
// 再添加
g2d.drawImage(icon, 200, 200, null);
// 保存
ImageIO.write(image, "PNG", new File("F:/Tst/test-res.png"));
}
4、图片缩放和裁剪
/**
* 缩放 调整大小
* @throws IOException
*/
public static void resetImageSize() throws IOException {
// 构造Image对象
BufferedImage src = ImageIO.read(new File("F:/Tst/test.png"));
// 创建容器
BufferedImage res = new BufferedImage(src.getWidth(), src.getHeight(), BufferedImage.TYPE_INT_RGB);
// 缩放方式一 当指定宽度和高度时将自动进行缩放以填充整个指定范围的矩形
res.getGraphics().drawImage(src, 0, 0, src.getWidth() / 4, src.getHeight() / 4, null);
// 缩放方式二 原图缩放后通过画板写入
Image content = src.getScaledInstance(src.getWidth() / 2, src.getHeight() / 2, BufferedImage.TYPE_INT_RGB);
// 将内容填充到容器中,不带宽度和高度时多出部分不显示(Image不能直接写入文件)
res.getGraphics().drawImage(content, 0, 0, null);
// 缩放方式三 基于画板的缩放
Graphics2D g2d = res.createGraphics();
// 缩放画板
g2d.scale(0.5, 0.5);
// 此时的宽和高如果大于画板则无效,自动缩放到充满画板
g2d.drawImage(src, 0, 0, src.getWidth(), src.getHeight(), null);
// 保存
ImageIO.write(res, "PNG", new File("F:/Tst/test-res.png"));
}
/**
* 限定显示区域
* @throws IOException
*/
public static void clipRect() throws IOException {
// 创建图像缓冲区(空图片)
BufferedImage bi = new BufferedImage(512, 512, BufferedImage.TYPE_INT_RGB);
// 创建 Graphics 的副本
Graphics2D g2d = bi.createGraphics();
// 从本地读取一张图片
BufferedImage src = ImageIO.read(new File("F:/Tst/yanwo.png"));
// 限定图形在指定区域内的显示,超出部分不显示。多个限制区有覆盖时,得到限制区域的交集区域
g2d.clipRect(100, 100, 100, 100);
g2d.drawImage(src, 0, 0, src.getWidth(), src.getHeight(), null);
g2d.dispose();
// 保存文件
ImageIO.write(bi, "png", new File("F:/Tst/test-res.png"));
}
/**
* 裁剪图片
* @throws IOException
*/
public static void subImage() throws IOException {
// 构造图像缓冲区
BufferedImage src = ImageIO.read(new File("F:/Tst/test.png"));
// 裁剪 起始位置和裁剪大小
BufferedImage res = src.getSubimage(src.getWidth()/4, src.getHeight()/4, src.getWidth()/2, src.getHeight()/2);
// 保存文件
ImageIO.write(res, "PNG", new File("F:/Tst/test-res.png"));
}
4、平移和旋转
/**
* 平移
*/
public static void translate() throws IOException {
// 创建图像缓冲区(空图片)
BufferedImage bi = new BufferedImage(512, 512, BufferedImage.TYPE_INT_RGB);
// 创建 Graphics 的副本
Graphics2D g2d = bi.createGraphics();
// 从本地读取一张图片
BufferedImage src = ImageIO.read(new File("F:/Tst/yanwo.png"));
// 平移 画板的平移
g2d.translate(50, 50);
g2d.drawImage(src, 50, 50, src.getWidth() / 2, src.getHeight() / 2, null);
g2d.dispose();
// 保存文件
ImageIO.write(bi, "png", new File("F:/Tst/test-res.png"));
}
/**
* 旋转
*/
public static void rotate() throws IOException {
// 创建图像缓冲区(空图片)
BufferedImage bi = new BufferedImage(512, 512, BufferedImage.TYPE_INT_RGB);
// 创建 Graphics 的副本
Graphics2D g2d = bi.createGraphics();
// 从本地读取一张图片
BufferedImage src = ImageIO.read(new File("F:/Tst/yanwo.png"));
// 旋转
g2d.rotate(180, 256, 256);
g2d.drawImage(src, 0, 0, src.getWidth() / 2, src.getHeight() / 2, null);
g2d.dispose();
// 保存文件
ImageIO.write(bi, "png", new File("F:/Tst/test-res.png"));
}
5、图片水印和灰化
/**
* 在源图片上设置水印文字
*/
public static void alphaWords2Image() throws IOException {
// 构造Image对象
BufferedImage image = ImageIO.read(new File("F:/Tst/test.png"));
// 创建java2D对象
Graphics2D g2d = image.createGraphics();
// 设置透明度 (0<alpha<1,0为透明,1为不透明)
AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.8f);
g2d.setComposite(ac);
// 设置文字字体名称、样式(Font.PLAIN=标准;Font.BOLD=粗体)、大小
g2d.setFont(new Font("楷体", Font.PLAIN, 22));
g2d.setColor(Color.RED); // 设置字体颜色
// 输入水印文字及其起始x、y坐标
g2d.drawString("仅XXX使用", 100, 80);
g2d.dispose();
FileOutputStream fos = new FileOutputStream("F:/Tst/test-res.png");
ImageIO.write(image, "PNG", fos);
}
/**
* 图片灰化操作
*/
public static void grayImage() throws IOException {
// 构造Image对象
BufferedImage src = ImageIO.read(new File("F:/Tst/test.png"));
// 定义转换变量
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY); // 颜色空间
ColorConvertOp op = new ColorConvertOp(cs, null); // 颜色转换
// 执行转换
src = op.filter(src, null);
// 保存
ImageIO.write(src, "PNG", new File("F:/Tst/test-res.png"));
}
6、水平镜像
/**
* 水平镜像图片
*/
public static void horizontalMirror() throws IOException {
// 读取图片
BufferedImage bufImage = ImageIO.read(new File("F:/Tst/test.png"));
// 获取图片的宽高
final int width = bufImage.getWidth();
final int height = bufImage.getHeight();
// 读取出图片的所有像素
int[] rgbs = bufImage.getRGB(0, 0, width, height, null, 0, width);
// 对图片的像素矩阵进行水平镜像
for (int row = 0; row < height; row++) {
for (int col = 0; col < width / 2; col++) {
int temp = rgbs[row * width + col];
rgbs[row * width + col] = rgbs[row * width + (width - 1 - col)];
rgbs[row * width + (width - 1 - col)] = temp;
}
}
// 把水平镜像后的像素矩阵设置回 bufImage
bufImage.setRGB(0, 0, width, height, rgbs, 0, width);
// 把修改过的 bufImage 保存到本地
ImageIO.write(bufImage, "PNG", new File("F:/Tst/test-res.png"));
}
7、切透明圆角
/**
* 图片切圆角一 切除部分透明
*/
public static void clipFillet() throws IOException {
// 构造Image对象
BufferedImage src = ImageIO.read(new File("F:/Tst/test.png"));
// ARGB从表面看比RGB多了个A,也是一种色彩模式,是在RGB的基础上添加了Alpha(透明度)通道
BufferedImage image = new BufferedImage(src.getWidth(), src.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D gs = image.createGraphics();
gs.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
gs.setClip(new RoundRectangle2D.Double(0, 0, src.getWidth(), src.getHeight(), src.getWidth()/5, src.getHeight()/5));
gs.drawImage(src, 0, 0, src.getWidth(), src.getHeight(), null);
gs.dispose();
ImageIO.write(image, "png", new File("F:/Tst/test-res.png"));
}
/**
* 图片切圆角二 切除部分透明
* @throws IOException
*/
public static void clipFillet() throws IOException {
// 构造Image对象
BufferedImage src = ImageIO.read(new File("F:/Tst/test.png"));
BufferedImage image = new BufferedImage(src.getWidth(), src.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D gs = image.createGraphics();
// 设置背景色为透明
image = gs.getDeviceConfiguration().createCompatibleImage(src.getWidth(), src.getHeight(), Transparency.TRANSLUCENT); // 重新获取图片缓冲区
gs = image.createGraphics(); // 重新获取Graphics2D
gs.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
gs.setClip(new RoundRectangle2D.Double(0, 0, src.getWidth(), src.getHeight(), src.getWidth()/5, src.getHeight()/5));
gs.drawImage(src, 0, 0, src.getWidth(), src.getHeight(), null);
gs.dispose();
ImageIO.write(image, "png", new File("F:/Tst/test-res.png"));
}
8、图片RGB值的读写
/**
* 获取RGB的值
*/
public static void getRGB() throws IOException {
//读入文件
File file = new File("F:/Tst/test.png");
// 构造Image对象
BufferedImage src = ImageIO.read(file);
// 获取指定坐标的RGB值
System.out.println(src.getRGB(400, 200));
// 获取指定区域的RGB值 从指定起点到指定宽度和高度的区域的RGB数组,offset表示数组开头的偏移,scansize表示一行占用的长度(可以大于指定宽度,但小于时异常)
System.out.println(src.getRGB(400, 200, 100, 100, null, 0, 100));
}
/**
* 设置RGB的值
*/
public static void setRGB() throws IOException {
//创建图像缓冲区
BufferedImage bi = new BufferedImage(256, 256, BufferedImage.TYPE_INT_RGB);
// 获取Graphics2D
Graphics2D g2d = bi.createGraphics();
// 初始化
g2d.setBackground(Color.WHITE);
g2d.clearRect(0, 0, 256, 256);
// 设置指定坐标的RGB值
bi.setRGB(80, 80, 10000);
// 设置从指定起点到指定宽度和高度的区域的RGB值,offset表示数组开头的偏移,scansize表示一行占用的长度
bi.setRGB(120, 120, 16, 16, new int[256], 0, 16);
// 保存文件
ImageIO.write(bi, "png", new File("F:/Tst/test-res.png"));
}
9、图片转TIF格式
/**
* PNG转TIF 通过JAI包实现 JPG等类似
* @throws IOException
*/
public static void pngToTif() throws IOException {
// 创建操作对象
RenderedOp renderOp = JAI.create("fileload", "F:/Tst/test.png");
// 创建存储文件流
OutputStream outputStream = new FileOutputStream("F:/Tst/test.tif");
// 创建编码器
TIFFEncodeParam tiffParam = new TIFFEncodeParam();
ImageEncoder imageEncoder = ImageCodec.createImageEncoder("TIFF", outputStream, tiffParam);
// 转换保存
imageEncoder.encode(renderOp);
}