修复图片操作未调用flush导致资源未释放问题

This commit is contained in:
Looly 2024-03-28 22:26:32 +08:00
parent abfa378ce0
commit eebec03334
4 changed files with 317 additions and 127 deletions

View File

@ -20,6 +20,7 @@
* 【core 】 修复DateUtil.betweenYear闰年2月问题issue#I97U3J@Gitee
* 【captcha】 修复Graphics2D的资源没释放问题issue#I98PYN@Gitee
* 【core 】 修复ClassUtil.getTypeArgument() 获取泛型存在null问题issue#3516@Github
* 【core 】 修复图片操作未调用flush导致资源未释放问题issue#I9C7NA@Gitee
-------------------------------------------------------------------------------------------------------------
# 5.8.26(2024-02-10)

View File

@ -8,6 +8,7 @@ import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.sun.imageio.plugins.common.ImageUtil;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;
@ -30,10 +31,7 @@ import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.CropImageFilter;
import java.awt.image.ImageFilter;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.io.*;
import java.net.URL;
import java.nio.file.Path;
@ -43,7 +41,7 @@ import java.nio.file.Path;
* @author looly
* @since 4.1.5
*/
public class Img implements Serializable {
public class Img implements Flushable, Serializable {
private static final long serialVersionUID = 1L;
private final BufferedImage srcImage;
@ -754,6 +752,12 @@ public class Img implements Serializable {
}
}
@Override
public void flush() {
ImgUtil.flush(this.srcImage);
ImgUtil.flush(this.targetImage);
}
// ---------------------------------------------------------------------------------------------------------------- Private method start
/**

View File

@ -4,6 +4,7 @@ import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.io.resource.Resource;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.NumberUtil;
@ -11,45 +12,17 @@ import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.*;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;
import javax.swing.ImageIcon;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.ColorConvertOp;
import java.awt.image.ColorModel;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;
import java.awt.image.RenderedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.awt.image.*;
import java.io.*;
import java.net.URL;
import java.util.Iterator;
import java.util.Random;
@ -63,12 +36,32 @@ import java.util.Random;
*/
public class ImgUtil {
public static final String IMAGE_TYPE_GIF = "gif";// 图形交换格式
public static final String IMAGE_TYPE_JPG = "jpg";// 联合照片专家组
public static final String IMAGE_TYPE_JPEG = "jpeg";// 联合照片专家组
public static final String IMAGE_TYPE_BMP = "bmp";// 英文Bitmap位图的简写它是Windows操作系统中的标准图像文件格式
public static final String IMAGE_TYPE_PNG = "png";// 可移植网络图形
public static final String IMAGE_TYPE_PSD = "psd";// Photoshop的专用格式Photoshop
// region ----- [const] image type
/**
* 图形交换格式GIF
*/
public static final String IMAGE_TYPE_GIF = "gif";
/**
* 联合照片专家组JPG
*/
public static final String IMAGE_TYPE_JPG = "jpg";
/**
* 联合照片专家组JPEG
*/
public static final String IMAGE_TYPE_JPEG = "jpeg";
/**
* 英文Bitmap位图的简写它是Windows操作系统中的标准图像文件格式BMP
*/
public static final String IMAGE_TYPE_BMP = "bmp";
/**
* 可移植网络图形PNG
*/
public static final String IMAGE_TYPE_PNG = "png";
/**
* Photoshop的专用格式PSD
*/
public static final String IMAGE_TYPE_PSD = "psd";
// endregion
// ---------------------------------------------------------------------------------------------------------------------- scale
@ -80,7 +73,13 @@ public class ImgUtil {
* @param scale 缩放比例比例大于1时为放大小于1大于0为缩小
*/
public static void scale(File srcImageFile, File destImageFile, float scale) {
scale(read(srcImageFile), destImageFile, scale);
BufferedImage image = null;
try {
image = read(srcImageFile);
scale(image, destImageFile, scale);
} finally {
flush(image);
}
}
/**
@ -93,7 +92,13 @@ public class ImgUtil {
* @since 3.0.9
*/
public static void scale(InputStream srcStream, OutputStream destStream, float scale) {
scale(read(srcStream), destStream, scale);
BufferedImage image = null;
try {
image = read(srcStream);
scale(image, destStream, scale);
} finally {
flush(image);
}
}
/**
@ -106,14 +111,20 @@ public class ImgUtil {
* @since 3.1.0
*/
public static void scale(ImageInputStream srcStream, ImageOutputStream destStream, float scale) {
scale(read(srcStream), destStream, scale);
BufferedImage image = null;
try {
image = read(srcStream);
scale(image, destStream, scale);
} finally {
flush(image);
}
}
/**
* 缩放图像按比例缩放<br>
* 缩放后默认为jpeg格式此方法并不关闭流
*
* @param srcImg 源图像来源流
* @param srcImg 源图像来源流使用结束后需手动调用{@link #flush(Image)}释放资源
* @param destFile 缩放后的图像写出到的流
* @param scale 缩放比例比例大于1时为放大小于1大于0为缩小
* @throws IORuntimeException IO异常
@ -127,7 +138,7 @@ public class ImgUtil {
* 缩放图像按比例缩放<br>
* 缩放后默认为jpeg格式此方法并不关闭流
*
* @param srcImg 源图像来源流
* @param srcImg 源图像来源流使用结束后需手动调用{@link #flush(Image)}释放资源
* @param out 缩放后的图像写出到的流
* @param scale 缩放比例比例大于1时为放大小于1大于0为缩小
* @throws IORuntimeException IO异常
@ -141,7 +152,7 @@ public class ImgUtil {
* 缩放图像按比例缩放<br>
* 缩放后默认为jpeg格式此方法并不关闭流
*
* @param srcImg 源图像来源流
* @param srcImg 源图像来源流使用结束后需手动调用{@link #flush(Image)}释放资源
* @param destImageStream 缩放后的图像写出到的流
* @param scale 缩放比例比例大于1时为放大小于1大于0为缩小
* @throws IORuntimeException IO异常
@ -154,7 +165,7 @@ public class ImgUtil {
/**
* 缩放图像按比例缩放
*
* @param srcImg 源图像来源流
* @param srcImg 源图像来源流使用结束后需手动调用{@link #flush(Image)}释放资源
* @param scale 缩放比例比例大于1时为放大小于1大于0为缩小
* @return {@link Image}
* @since 3.1.0
@ -167,7 +178,7 @@ public class ImgUtil {
* 缩放图像按长宽缩放<br>
* 注意目标长宽与原图不成比例会变形
*
* @param srcImg 源图像来源流
* @param srcImg 源图像来源流使用结束后需手动调用{@link #flush(Image)}释放资源
* @param width 目标宽度
* @param height 目标高度
* @return {@link Image}
@ -189,10 +200,15 @@ public class ImgUtil {
* @throws IORuntimeException IO异常
*/
public static void scale(File srcImageFile, File destImageFile, int width, int height, Color fixedColor) throws IORuntimeException {
Img.from(srcImageFile)//
.setTargetImageType(FileUtil.extName(destImageFile))//
Img img = null;
try {
img = Img.from(srcImageFile);
img.setTargetImageType(FileUtil.extName(destImageFile))
.scale(width, height, fixedColor)//
.write(destImageFile);
} finally {
IoUtil.flush(img);
}
}
/**
@ -207,7 +223,13 @@ public class ImgUtil {
* @throws IORuntimeException IO异常
*/
public static void scale(InputStream srcStream, OutputStream destStream, int width, int height, Color fixedColor) throws IORuntimeException {
scale(read(srcStream), getImageOutputStream(destStream), width, height, fixedColor);
BufferedImage image = null;
try {
image = read(srcStream);
scale(image, getImageOutputStream(destStream), width, height, fixedColor);
} finally {
flush(image);
}
}
/**
@ -222,7 +244,13 @@ public class ImgUtil {
* @throws IORuntimeException IO异常
*/
public static void scale(ImageInputStream srcStream, ImageOutputStream destStream, int width, int height, Color fixedColor) throws IORuntimeException {
scale(read(srcStream), destStream, width, height, fixedColor);
BufferedImage image = null;
try {
image = read(srcStream);
scale(image, destStream, width, height, fixedColor);
} finally {
flush(image);
}
}
/**
@ -265,7 +293,13 @@ public class ImgUtil {
* @since 3.1.0
*/
public static void cut(File srcImgFile, File destImgFile, Rectangle rectangle) {
cut(read(srcImgFile), destImgFile, rectangle);
BufferedImage image = null;
try {
image = read(srcImgFile);
cut(image, destImgFile, rectangle);
} finally {
flush(image);
}
}
/**
@ -277,7 +311,13 @@ public class ImgUtil {
* @since 3.1.0
*/
public static void cut(InputStream srcStream, OutputStream destStream, Rectangle rectangle) {
cut(read(srcStream), destStream, rectangle);
BufferedImage image = null;
try {
image = read(srcStream);
cut(image, destStream, rectangle);
} finally {
flush(image);
}
}
/**
@ -289,13 +329,19 @@ public class ImgUtil {
* @since 3.1.0
*/
public static void cut(ImageInputStream srcStream, ImageOutputStream destStream, Rectangle rectangle) {
cut(read(srcStream), destStream, rectangle);
BufferedImage image = null;
try {
image = read(srcStream);
cut(image, destStream, rectangle);
} finally {
flush(image);
}
}
/**
* 图像切割(按指定起点坐标和宽高切割)此方法并不关闭流
*
* @param srcImage 源图像
* @param srcImage 源图像使用结束后需手动调用{@link #flush(Image)}释放资源
* @param destFile 输出的文件
* @param rectangle 矩形对象表示矩形区域的xywidthheight
* @throws IORuntimeException IO异常
@ -308,7 +354,7 @@ public class ImgUtil {
/**
* 图像切割(按指定起点坐标和宽高切割)此方法并不关闭流
*
* @param srcImage 源图像
* @param srcImage 源图像使用结束后需手动调用{@link #flush(Image)}释放资源
* @param out 切片后的图像输出流
* @param rectangle 矩形对象表示矩形区域的xywidthheight
* @throws IORuntimeException IO异常
@ -321,7 +367,7 @@ public class ImgUtil {
/**
* 图像切割(按指定起点坐标和宽高切割)此方法并不关闭流
*
* @param srcImage 源图像
* @param srcImage 源图像使用结束后需手动调用{@link #flush(Image)}释放资源
* @param destImageStream 切片后的图像输出流
* @param rectangle 矩形对象表示矩形区域的xywidthheight
* @throws IORuntimeException IO异常
@ -334,7 +380,7 @@ public class ImgUtil {
/**
* 图像切割(按指定起点坐标和宽高切割)
*
* @param srcImage 源图像
* @param srcImage 源图像使用结束后需手动调用{@link #flush(Image)}释放资源
* @param rectangle 矩形对象表示矩形区域的xywidthheight
* @return {@link BufferedImage}
* @since 3.1.0
@ -346,7 +392,7 @@ public class ImgUtil {
/**
* 图像切割(按指定起点坐标和宽高切割)填充满整个图片直径取长宽最小值
*
* @param srcImage 源图像
* @param srcImage 源图像使用结束后需手动调用{@link #flush(Image)}释放资源
* @param x 原图的x坐标起始位置
* @param y 原图的y坐标起始位置
* @return {@link Image}
@ -359,7 +405,7 @@ public class ImgUtil {
/**
* 图像切割(按指定起点坐标和宽高切割)
*
* @param srcImage 源图像
* @param srcImage 源图像使用结束后需手动调用{@link #flush(Image)}释放资源
* @param x 原图的x坐标起始位置
* @param y 原图的y坐标起始位置
* @param radius 半径小于0表示填充满整个图片直径取长宽最小值
@ -379,13 +425,19 @@ public class ImgUtil {
* @param destHeight 目标切片高度默认150
*/
public static void slice(File srcImageFile, File descDir, int destWidth, int destHeight) {
slice(read(srcImageFile), descDir, destWidth, destHeight);
BufferedImage image = null;
try {
image = read(srcImageFile);
slice(image, descDir, destWidth, destHeight);
} finally {
flush(image);
}
}
/**
* 图像切片指定切片的宽度和高度
*
* @param srcImage 源图像
* @param srcImage 源图像使用结束后需手动调用{@link #flush(Image)}释放资源
* @param descDir 切片目标文件夹
* @param destWidth 目标切片宽度默认200
* @param destHeight 目标切片高度默认150
@ -455,7 +507,13 @@ public class ImgUtil {
* @param cols 目标切片列数默认2必须是范围 [1, 20] 之内
*/
public static void sliceByRowsAndCols(File srcImageFile, File destDir, String format, int rows, int cols) {
sliceByRowsAndCols(read(srcImageFile), destDir, format, rows, cols);
BufferedImage image = null;
try {
image = read(srcImageFile);
sliceByRowsAndCols(image, destDir, format, rows, cols);
} finally {
flush(image);
}
}
/**
@ -531,7 +589,13 @@ public class ImgUtil {
FileUtil.copy(srcImageFile, destImageFile, true);
}
Img.from(srcImageFile).write(destImageFile);
Img img = null;
try {
img = Img.from(srcImageFile);
img.write(destImageFile);
} finally {
IoUtil.flush(img);
}
}
/**
@ -544,14 +608,20 @@ public class ImgUtil {
* @since 3.0.9
*/
public static void convert(InputStream srcStream, String formatName, OutputStream destStream) {
write(read(srcStream), formatName, getImageOutputStream(destStream));
BufferedImage image = null;
try {
image = read(srcStream);
write(image, formatName, getImageOutputStream(destStream));
} finally {
flush(image);
}
}
/**
* 图像类型转换GIF=JPGGIF=PNGPNG=JPGPNG=GIF(X)BMP=PNG<br>
* 此方法并不关闭流
*
* @param srcImage 源图像流
* @param srcImage 源图像流使用结束后需手动调用{@link #flush(Image)}释放资源
* @param formatName 包含格式非正式名称的 String如JPGJPEGGIF等
* @param destImageStream 目标图像输出流
* @since 4.1.14
@ -564,7 +634,7 @@ public class ImgUtil {
* 图像类型转换GIF=JPGGIF=PNGPNG=JPGPNG=GIF(X)BMP=PNG<br>
* 此方法并不关闭流
*
* @param srcImage 源图像流
* @param srcImage 源图像流使用结束后需手动调用{@link #flush(Image)}释放资源
* @param formatName 包含格式非正式名称的 String如JPGJPEGGIF等
* @param destImageStream 目标图像输出流
* @param isSrcPng 源图片是否为PNG格式参数无效
@ -584,7 +654,13 @@ public class ImgUtil {
* @param destImageFile 目标图像地址
*/
public static void gray(File srcImageFile, File destImageFile) {
gray(read(srcImageFile), destImageFile);
BufferedImage image = null;
try {
image = read(srcImageFile);
gray(image, destImageFile);
} finally {
flush(image);
}
}
/**
@ -596,7 +672,13 @@ public class ImgUtil {
* @since 3.0.9
*/
public static void gray(InputStream srcStream, OutputStream destStream) {
gray(read(srcStream), getImageOutputStream(destStream));
BufferedImage image = null;
try {
image = read(srcStream);
gray(image, destStream);
} finally {
flush(image);
}
}
/**
@ -608,13 +690,19 @@ public class ImgUtil {
* @since 3.0.9
*/
public static void gray(ImageInputStream srcStream, ImageOutputStream destStream) {
gray(read(srcStream), destStream);
BufferedImage image = null;
try {
image = read(srcStream);
gray(image, destStream);
} finally {
flush(image);
}
}
/**
* 彩色转为黑白
*
* @param srcImage 源图像流
* @param srcImage 源图像流使用结束后需手动调用{@link #flush(Image)}释放资源
* @param outFile 目标文件
* @since 3.2.2
*/
@ -626,7 +714,7 @@ public class ImgUtil {
* 彩色转为黑白<br>
* 此方法并不关闭流
*
* @param srcImage 源图像流
* @param srcImage 源图像流使用结束后需手动调用{@link #flush(Image)}释放资源
* @param out 目标图像流
* @since 3.2.2
*/
@ -638,7 +726,7 @@ public class ImgUtil {
* 彩色转为黑白<br>
* 此方法并不关闭流
*
* @param srcImage 源图像流
* @param srcImage 源图像流使用结束后需手动调用{@link #flush(Image)}释放资源
* @param destImageStream 目标图像流
* @throws IORuntimeException IO异常
* @since 3.0.9
@ -650,7 +738,7 @@ public class ImgUtil {
/**
* 彩色转为黑白
*
* @param srcImage 源图像流
* @param srcImage 源图像流使用结束后需手动调用{@link #flush(Image)}释放资源
* @return {@link Image}灰度后的图片
* @since 3.1.0
*/
@ -667,7 +755,13 @@ public class ImgUtil {
* @param destImageFile 目标图像地址
*/
public static void binary(File srcImageFile, File destImageFile) {
binary(read(srcImageFile), destImageFile);
BufferedImage image = null;
try {
image = read(srcImageFile);
binary(image, destImageFile);
} finally {
flush(image);
}
}
/**
@ -680,7 +774,13 @@ public class ImgUtil {
* @since 4.0.5
*/
public static void binary(InputStream srcStream, OutputStream destStream, String imageType) {
binary(read(srcStream), getImageOutputStream(destStream), imageType);
BufferedImage image = null;
try {
image = read(srcStream);
binary(image, getImageOutputStream(destStream), imageType);
} finally {
flush(image);
}
}
/**
@ -693,13 +793,19 @@ public class ImgUtil {
* @since 4.0.5
*/
public static void binary(ImageInputStream srcStream, ImageOutputStream destStream, String imageType) {
binary(read(srcStream), destStream, imageType);
BufferedImage image = null;
try {
image = read(srcStream);
binary(image, destStream, imageType);
} finally {
flush(image);
}
}
/**
* 彩色转为黑白二值化图片根据目标文件扩展名确定转换后的格式
*
* @param srcImage 源图像流
* @param srcImage 源图像使用结束后需手动调用{@link #flush(Image)}释放资源
* @param outFile 目标文件
* @since 4.0.5
*/
@ -711,7 +817,7 @@ public class ImgUtil {
* 彩色转为黑白二值化图片<br>
* 此方法并不关闭流输出JPG格式
*
* @param srcImage 源图像
* @param srcImage 源图像使用结束后需手动调用{@link #flush(Image)}释放资源
* @param out 目标图像流
* @param imageType 图片格式(扩展名)
* @since 4.0.5
@ -724,7 +830,7 @@ public class ImgUtil {
* 彩色转为黑白二值化图片<br>
* 此方法并不关闭流输出JPG格式
*
* @param srcImage 源图像
* @param srcImage 源图像使用结束后需手动调用{@link #flush(Image)}释放资源
* @param destImageStream 目标图像流
* @param imageType 图片格式(扩展名)
* @throws IORuntimeException IO异常
@ -737,7 +843,7 @@ public class ImgUtil {
/**
* 彩色转为黑白二值化图片
*
* @param srcImage 源图像
* @param srcImage 源图像使用结束后需手动调用{@link #flush(Image)}释放资源
* @return {@link Image}二值化后的图片
* @since 4.0.5
*/
@ -760,7 +866,13 @@ public class ImgUtil {
* @param alpha 透明度alpha 必须是范围 [0.0, 1.0] 之内包含边界值的一个浮点数字
*/
public static void pressText(File imageFile, File destFile, String pressText, Color color, Font font, int x, int y, float alpha) {
pressText(read(imageFile), destFile, pressText, color, font, x, y, alpha);
BufferedImage image = null;
try {
image = read(imageFile);
pressText(image, destFile, pressText, color, font, x, y, alpha);
} finally {
flush(image);
}
}
/**
@ -777,7 +889,13 @@ public class ImgUtil {
* @param alpha 透明度alpha 必须是范围 [0.0, 1.0] 之内包含边界值的一个浮点数字
*/
public static void pressText(InputStream srcStream, OutputStream destStream, String pressText, Color color, Font font, int x, int y, float alpha) {
pressText(read(srcStream), getImageOutputStream(destStream), pressText, color, font, x, y, alpha);
BufferedImage image = null;
try {
image = read(srcStream);
pressText(image, getImageOutputStream(destStream), pressText, color, font, x, y, alpha);
} finally {
flush(image);
}
}
/**
@ -794,14 +912,20 @@ public class ImgUtil {
* @param alpha 透明度alpha 必须是范围 [0.0, 1.0] 之内包含边界值的一个浮点数字
*/
public static void pressText(ImageInputStream srcStream, ImageOutputStream destStream, String pressText, Color color, Font font, int x, int y, float alpha) {
pressText(read(srcStream), destStream, pressText, color, font, x, y, alpha);
BufferedImage image = null;
try {
image = read(srcStream);
pressText(image, destStream, pressText, color, font, x, y, alpha);
} finally {
flush(image);
}
}
/**
* 给图片添加文字水印<br>
* 此方法并不关闭流
*
* @param srcImage 源图像
* @param srcImage 源图像使用结束后需手动调用{@link #flush(Image)}释放资源
* @param destFile 目标流
* @param pressText 水印文字
* @param color 水印的字体颜色
@ -820,7 +944,7 @@ public class ImgUtil {
* 给图片添加文字水印<br>
* 此方法并不关闭流
*
* @param srcImage 源图像
* @param srcImage 源图像使用结束后需手动调用{@link #flush(Image)}释放资源
* @param to 目标流
* @param pressText 水印文字
* @param color 水印的字体颜色
@ -839,7 +963,7 @@ public class ImgUtil {
* 给图片添加文字水印<br>
* 此方法并不关闭流
*
* @param srcImage 源图像
* @param srcImage 源图像使用结束后需手动调用{@link #flush(Image)}释放资源
* @param destImageStream 目标图像流
* @param pressText 水印文字
* @param color 水印的字体颜色
@ -857,7 +981,7 @@ public class ImgUtil {
* 给图片添加文字水印<br>
* 此方法并不关闭流
*
* @param srcImage 源图像
* @param srcImage 源图像使用结束后需手动调用{@link #flush(Image)}释放资源
* @param pressText 水印文字
* @param color 水印的字体颜色
* @param font {@link Font} 字体相关信息如果默认则为{@code null}
@ -882,7 +1006,13 @@ public class ImgUtil {
* @param alpha 透明度alpha 必须是范围 [0.0, 1.0] 之内包含边界值的一个浮点数字
*/
public static void pressImage(File srcImageFile, File destImageFile, Image pressImg, int x, int y, float alpha) {
pressImage(read(srcImageFile), destImageFile, pressImg, x, y, alpha);
BufferedImage image = null;
try {
image = read(srcImageFile);
pressImage(image, destImageFile, pressImg, x, y, alpha);
} finally {
flush(image);
}
}
/**
@ -897,7 +1027,13 @@ public class ImgUtil {
* @param alpha 透明度alpha 必须是范围 [0.0, 1.0] 之内包含边界值的一个浮点数字
*/
public static void pressImage(InputStream srcStream, OutputStream destStream, Image pressImg, int x, int y, float alpha) {
pressImage(read(srcStream), getImageOutputStream(destStream), pressImg, x, y, alpha);
BufferedImage image = null;
try {
image = read(srcStream);
pressImage(image, getImageOutputStream(destStream), pressImg, x, y, alpha);
} finally {
flush(image);
}
}
/**
@ -913,14 +1049,21 @@ public class ImgUtil {
* @throws IORuntimeException IO异常
*/
public static void pressImage(ImageInputStream srcStream, ImageOutputStream destStream, Image pressImg, int x, int y, float alpha) throws IORuntimeException {
pressImage(read(srcStream), destStream, pressImg, x, y, alpha);
BufferedImage image = null;
try {
image = read(srcStream);
pressImage(image, destStream, pressImg, x, y, alpha);
} finally {
flush(image);
}
}
/**
* 给图片添加图片水印<br>
* 此方法并不关闭流
*
* @param srcImage 源图像流
* @param srcImage 源图像流使用结束后需手动调用{@link #flush(Image)}释放资源
* @param outFile 写出文件
* @param pressImg 水印图片可以使用{@link ImageIO#read(File)}方法读取文件
* @param x 修正值 默认在中间偏移量相对于中间偏移
@ -937,7 +1080,7 @@ public class ImgUtil {
* 给图片添加图片水印<br>
* 此方法并不关闭流
*
* @param srcImage 源图像流
* @param srcImage 源图像流使用结束后需手动调用{@link #flush(Image)}释放资源
* @param out 目标图像流
* @param pressImg 水印图片可以使用{@link ImageIO#read(File)}方法读取文件
* @param x 修正值 默认在中间偏移量相对于中间偏移
@ -954,7 +1097,7 @@ public class ImgUtil {
* 给图片添加图片水印<br>
* 此方法并不关闭流
*
* @param srcImage 源图像流
* @param srcImage 源图像流使用结束后需手动调用{@link #flush(Image)}释放资源
* @param destImageStream 目标图像流
* @param pressImg 水印图片可以使用{@link ImageIO#read(File)}方法读取文件
* @param x 修正值 默认在中间偏移量相对于中间偏移
@ -970,7 +1113,7 @@ public class ImgUtil {
* 给图片添加图片水印<br>
* 此方法并不关闭流
*
* @param srcImage 源图像流
* @param srcImage 源图像流使用结束后需手动调用{@link #flush(Image)}释放资源
* @param pressImg 水印图片可以使用{@link ImageIO#read(File)}方法读取文件
* @param x 修正值 默认在中间偏移量相对于中间偏移
* @param y 修正值 默认在中间偏移量相对于中间偏移
@ -985,7 +1128,7 @@ public class ImgUtil {
* 给图片添加图片水印<br>
* 此方法并不关闭流
*
* @param srcImage 源图像流
* @param srcImage 源图像流使用结束后需手动调用{@link #flush(Image)}释放资源
* @param pressImg 水印图片可以使用{@link ImageIO#read(File)}方法读取文件
* @param rectangle 矩形对象表示矩形区域的xywidthheightx,y从背景图片中心计算
* @param alpha 透明度alpha 必须是范围 [0.0, 1.0] 之内包含边界值的一个浮点数字
@ -1009,14 +1152,20 @@ public class ImgUtil {
* @since 3.2.2
*/
public static void rotate(File imageFile, int degree, File outFile) throws IORuntimeException {
rotate(read(imageFile), degree, outFile);
BufferedImage image = null;
try {
image = read(imageFile);
rotate(image, degree, outFile);
} finally {
flush(image);
}
}
/**
* 旋转图片为指定角度<br>
* 此方法不会关闭输出流
*
* @param image 目标图像
* @param image 目标图像使用结束后需手动调用{@link #flush(Image)}释放资源
* @param degree 旋转角度
* @param outFile 输出文件
* @throws IORuntimeException IO异常
@ -1030,7 +1179,7 @@ public class ImgUtil {
* 旋转图片为指定角度<br>
* 此方法不会关闭输出流
*
* @param image 目标图像
* @param image 目标图像使用结束后需手动调用{@link #flush(Image)}释放资源
* @param degree 旋转角度
* @param out 输出流
* @throws IORuntimeException IO异常
@ -1044,7 +1193,7 @@ public class ImgUtil {
* 旋转图片为指定角度<br>
* 此方法不会关闭输出流输出格式为JPG
*
* @param image 目标图像
* @param image 图像使用结束后需手动调用{@link #flush(Image)}释放资源
* @param degree 旋转角度
* @param out 输出图像流
* @throws IORuntimeException IO异常
@ -1058,7 +1207,7 @@ public class ImgUtil {
* 旋转图片为指定角度<br>
* 来自<a href="http://blog.51cto.com/cping1982/130066">http://blog.51cto.com/cping1982/130066</a>
*
* @param image 目标图像
* @param image 图像使用结束后需手动调用{@link #flush(Image)}释放资源
* @param degree 旋转角度
* @return 旋转后的图片
* @since 3.2.2
@ -1078,13 +1227,19 @@ public class ImgUtil {
* @since 3.2.2
*/
public static void flip(File imageFile, File outFile) throws IORuntimeException {
flip(read(imageFile), outFile);
BufferedImage image = null;
try {
image = read(imageFile);
flip(image, outFile);
} finally {
flush(image);
}
}
/**
* 水平翻转图像
*
* @param image 图像
* @param image 图像使用结束后需手动调用{@link #flush(Image)}释放资源
* @param outFile 输出文件
* @throws IORuntimeException IO异常
* @since 3.2.2
@ -1096,7 +1251,7 @@ public class ImgUtil {
/**
* 水平翻转图像
*
* @param image 图像
* @param image 图像使用结束后需手动调用{@link #flush(Image)}释放资源
* @param out 输出
* @throws IORuntimeException IO异常
* @since 3.2.2
@ -1108,7 +1263,7 @@ public class ImgUtil {
/**
* 水平翻转图像写出格式为JPG
*
* @param image 图像
* @param image 图像使用结束后需手动调用{@link #flush(Image)}释放资源
* @param out 输出
* @throws IORuntimeException IO异常
* @since 3.2.2
@ -1120,7 +1275,7 @@ public class ImgUtil {
/**
* 水平翻转图像
*
* @param image 图像
* @param image 图像使用结束后需手动调用{@link #flush(Image)}释放资源
* @return 翻转后的图片
* @since 3.2.2
*/
@ -1140,7 +1295,13 @@ public class ImgUtil {
* @since 4.3.2
*/
public static void compress(File imageFile, File outFile, float quality) throws IORuntimeException {
Img.from(imageFile).setQuality(quality).write(outFile);
Img img = null;
try {
img = Img.from(imageFile);
img.setQuality(quality).write(outFile);
} finally {
IoUtil.flush(img);
}
}
// ---------------------------------------------------------------------------------------------------------------------- other
@ -1176,7 +1337,7 @@ public class ImgUtil {
* {@link Image} {@link RenderedImage}<br>
* 首先尝试强转否则新建一个{@link BufferedImage}后重新绘制使用 {@link BufferedImage#TYPE_INT_RGB} 模式
*
* @param img {@link Image}
* @param img {@link Image}
* @param imageType 目标图片类型例如jpg或png等
* @return {@link BufferedImage}
* @since 4.3.2
@ -1193,7 +1354,7 @@ public class ImgUtil {
* {@link Image} {@link BufferedImage}<br>
* 首先尝试强转否则新建一个{@link BufferedImage}后重新绘制使用 imageType 模式
*
* @param img {@link Image}
* @param img {@link Image}
* @param imageType 目标图片类型例如jpg或png等
* @return {@link BufferedImage}
*/
@ -1232,8 +1393,8 @@ public class ImgUtil {
*/
public static BufferedImage toBufferedImage(Image image, String imageType, Color backgroundColor) {
final int type = IMAGE_TYPE_PNG.equalsIgnoreCase(imageType)
? BufferedImage.TYPE_INT_ARGB
: BufferedImage.TYPE_INT_RGB;
? BufferedImage.TYPE_INT_ARGB
: BufferedImage.TYPE_INT_RGB;
return toBufferedImage(image, type, backgroundColor);
}
@ -1336,9 +1497,9 @@ public class ImgUtil {
img = new ImageIcon(img).getImage();
final BufferedImage bimage = new BufferedImage(
img.getWidth(null), img.getHeight(null), imageType);
img.getWidth(null), img.getHeight(null), imageType);
final Graphics2D bGr = GraphicsUtil.createGraphics(bimage, backgroundColor);
try{
try {
bGr.drawImage(img, 0, 0, null);
} finally {
bGr.dispose();
@ -1407,8 +1568,8 @@ public class ImgUtil {
*/
public static String toBase64DataUri(Image image, String imageType) {
return URLUtil.getDataUri(
"image/" + imageType, "base64",
toBase64(image, imageType));
"image/" + imageType, "base64",
toBase64(image, imageType));
}
/**
@ -1512,9 +1673,9 @@ public class ImgUtil {
*/
public static Rectangle2D getRectangle(String str, Font font) {
return font.getStringBounds(str,
new FontRenderContext(AffineTransform.getScaleInstance(1, 1),
false,
false));
new FontRenderContext(AffineTransform.getScaleInstance(1, 1),
false,
false));
}
/**
@ -2087,8 +2248,8 @@ public class ImgUtil {
*/
public static Point getPointBaseCentre(Rectangle rectangle, int backgroundWidth, int backgroundHeight) {
return new Point(
rectangle.x + (Math.abs(backgroundWidth - rectangle.width) / 2), //
rectangle.y + (Math.abs(backgroundHeight - rectangle.height) / 2)//
rectangle.x + (Math.abs(backgroundWidth - rectangle.width) / 2), //
rectangle.y + (Math.abs(backgroundHeight - rectangle.height) / 2)//
);
}
@ -2244,6 +2405,17 @@ public class ImgUtil {
*/
public static Image filter(ImageFilter filter, Image image) {
return Toolkit.getDefaultToolkit().createImage(
new FilteredImageSource(image.getSource(), filter));
new FilteredImageSource(image.getSource(), filter));
}
/**
* 刷新和释放{@link Image} 资源
*
* @param image {@link Image}
*/
public static void flush(Image image) {
if (null != image) {
image.flush();
}
}
}

View File

@ -13,6 +13,7 @@ import com.google.zxing.*;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.GlobalHistogramBinarizer;
import com.google.zxing.common.HybridBinarizer;
import com.sun.imageio.plugins.common.ImageUtil;
import java.awt.Color;
import java.awt.Image;
@ -459,7 +460,13 @@ public class QrCodeUtil {
* @return 解码文本
*/
public static String decode(InputStream qrCodeInputStream) {
return decode(ImgUtil.read(qrCodeInputStream));
BufferedImage image = null;
try{
image = ImgUtil.read(qrCodeInputStream);
return decode(image);
} finally {
ImgUtil.flush(image);
}
}
/**
@ -469,7 +476,13 @@ public class QrCodeUtil {
* @return 解码文本
*/
public static String decode(File qrCodeFile) {
return decode(ImgUtil.read(qrCodeFile));
BufferedImage image = null;
try{
image = ImgUtil.read(qrCodeFile);
return decode(image);
} finally {
ImgUtil.flush(image);
}
}
/**