From 436b9199ef6ef150b66414e64198adc8ece832c0 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 28 Mar 2024 21:57:41 +0800 Subject: [PATCH] fix code --- .../org/dromara/hutool/swing/DesktopUtil.java | 22 +- .../org/dromara/hutool/swing/RobotUtil.java | 8 +- .../hutool/swing/captcha/AbstractCaptcha.java | 13 +- .../hutool/swing/img/BackgroundRemoval.java | 67 +- .../dromara/hutool/swing/img/FontUtil.java | 18 + .../hutool/swing/img/GraphicsUtil.java | 4 +- .../org/dromara/hutool/swing/img/Img.java | 14 +- .../org/dromara/hutool/swing/img/ImgUtil.java | 669 +++++++++++------- .../dromara/hutool/swing/img/ImgWriter.java | 14 +- .../org/dromara/hutool/swing/img/ImgTest.java | 1 + 10 files changed, 523 insertions(+), 307 deletions(-) diff --git a/hutool-swing/src/main/java/org/dromara/hutool/swing/DesktopUtil.java b/hutool-swing/src/main/java/org/dromara/hutool/swing/DesktopUtil.java index b0095a284..2af642757 100644 --- a/hutool-swing/src/main/java/org/dromara/hutool/swing/DesktopUtil.java +++ b/hutool-swing/src/main/java/org/dromara/hutool/swing/DesktopUtil.java @@ -34,7 +34,7 @@ public class DesktopUtil { * * @return {@link Desktop} */ - public static Desktop getDsktop() { + public static Desktop getDesktop() { return Desktop.getDesktop(); } @@ -54,9 +54,9 @@ public class DesktopUtil { * @since 4.6.3 */ public static void browse(final URI uri) { - final Desktop dsktop = getDsktop(); + final Desktop desktop = getDesktop(); try { - dsktop.browse(uri); + desktop.browse(uri); } catch (final IOException e) { throw new IORuntimeException(e); } @@ -68,9 +68,9 @@ public class DesktopUtil { * @param file URL地址 */ public static void open(final File file) { - final Desktop dsktop = getDsktop(); + final Desktop desktop = getDesktop(); try { - dsktop.open(file); + desktop.open(file); } catch (final IOException e) { throw new IORuntimeException(e); } @@ -82,9 +82,9 @@ public class DesktopUtil { * @param file 文件 */ public static void edit(final File file) { - final Desktop dsktop = getDsktop(); + final Desktop desktop = getDesktop(); try { - dsktop.edit(file); + desktop.edit(file); } catch (final IOException e) { throw new IORuntimeException(e); } @@ -96,9 +96,9 @@ public class DesktopUtil { * @param file 文件 */ public static void print(final File file) { - final Desktop dsktop = getDsktop(); + final Desktop desktop = getDesktop(); try { - dsktop.print(file); + desktop.print(file); } catch (final IOException e) { throw new IORuntimeException(e); } @@ -110,9 +110,9 @@ public class DesktopUtil { * @param mailAddress 邮件地址 */ public static void mail(final String mailAddress) { - final Desktop dsktop = getDsktop(); + final Desktop desktop = getDesktop(); try { - dsktop.mail(UrlUtil.toURI(mailAddress)); + desktop.mail(UrlUtil.toURI(mailAddress)); } catch (final IOException e) { throw new IORuntimeException(e); } diff --git a/hutool-swing/src/main/java/org/dromara/hutool/swing/RobotUtil.java b/hutool-swing/src/main/java/org/dromara/hutool/swing/RobotUtil.java index a63fac5e3..f92ee125f 100644 --- a/hutool-swing/src/main/java/org/dromara/hutool/swing/RobotUtil.java +++ b/hutool-swing/src/main/java/org/dromara/hutool/swing/RobotUtil.java @@ -201,7 +201,13 @@ public class RobotUtil { * @return 写出到的文件 */ public static File captureScreen(final File outFile) { - ImgUtil.write(captureScreen(), outFile); + BufferedImage image = null; + try{ + image = captureScreen(); + ImgUtil.write(image, outFile); + } finally { + ImgUtil.flush(image); + } return outFile; } diff --git a/hutool-swing/src/main/java/org/dromara/hutool/swing/captcha/AbstractCaptcha.java b/hutool-swing/src/main/java/org/dromara/hutool/swing/captcha/AbstractCaptcha.java index 1af6ee501..81edaa76f 100644 --- a/hutool-swing/src/main/java/org/dromara/hutool/swing/captcha/AbstractCaptcha.java +++ b/hutool-swing/src/main/java/org/dromara/hutool/swing/captcha/AbstractCaptcha.java @@ -112,7 +112,15 @@ public abstract class AbstractCaptcha implements ICaptcha { generateCode(); final ByteArrayOutputStream out = new ByteArrayOutputStream(); - ImgUtil.writePng(createImage(this.code), out); + + Image image = null; + try{ + image = createImage(this.code); + ImgUtil.writePng(image, out); + } finally { + ImgUtil.flush(image); + } + this.imageBytes = out.toByteArray(); } @@ -189,7 +197,8 @@ public abstract class AbstractCaptcha implements ICaptcha { } /** - * 获取验证码图 + * 获取验证码图
+ * 注意返回的{@link BufferedImage}使用完毕后需要调用{@link BufferedImage#flush()}释放资源 * * @return 验证码图 */ diff --git a/hutool-swing/src/main/java/org/dromara/hutool/swing/img/BackgroundRemoval.java b/hutool-swing/src/main/java/org/dromara/hutool/swing/img/BackgroundRemoval.java index 8c73a371f..88433727a 100644 --- a/hutool-swing/src/main/java/org/dromara/hutool/swing/img/BackgroundRemoval.java +++ b/hutool-swing/src/main/java/org/dromara/hutool/swing/img/BackgroundRemoval.java @@ -12,9 +12,10 @@ package org.dromara.hutool.swing.img; +import org.dromara.hutool.core.array.ArrayUtil; import org.dromara.hutool.core.io.IORuntimeException; import org.dromara.hutool.core.io.file.FileTypeUtil; -import org.dromara.hutool.core.array.ArrayUtil; +import org.dromara.hutool.core.lang.Assert; import org.dromara.hutool.core.text.StrUtil; import org.dromara.hutool.swing.img.color.ColorUtil; @@ -33,9 +34,7 @@ import java.util.List; import java.util.Map; /** - *

图片背景识别处理、背景替换、背景设置为矢量图

- *

根据一定规则算出图片背景色的RGB值,进行替换

- *

2020-05-21 16:36

+ * 图片背景识别处理、背景替换、背景设置为矢量图,根据一定规则算出图片背景色的RGB值,进行替换 * * @author Dai Yuanchuan **/ @@ -45,7 +44,7 @@ public class BackgroundRemoval { * 目前暂时支持的图片类型数组 * 其他格式的不保证结果 */ - public static String[] IMAGES_TYPE = {"jpg", "png"}; + public static String[] IMAGES_TYPE = {ImgUtil.IMAGE_TYPE_JPG, ImgUtil.IMAGE_TYPE_JPEG, ImgUtil.IMAGE_TYPE_PNG}; /** * 背景移除 @@ -59,10 +58,9 @@ public class BackgroundRemoval { * @param inputPath 要处理图片的路径 * @param outputPath 输出图片的路径 * @param tolerance 容差值[根据图片的主题色,加入容差值,值的范围在0~255之间] - * @return 返回处理结果 true:图片处理完成 false:图片处理失败 */ - public static boolean backgroundRemoval(final String inputPath, final String outputPath, final int tolerance) { - return backgroundRemoval(new File(inputPath), new File(outputPath), tolerance); + public static void backgroundRemoval(final String inputPath, final String outputPath, final int tolerance) { + backgroundRemoval(new File(inputPath), new File(outputPath), tolerance); } /** @@ -77,10 +75,9 @@ public class BackgroundRemoval { * @param input 需要进行操作的图片 * @param output 最后输出的文件 * @param tolerance 容差值[根据图片的主题色,加入容差值,值的取值范围在0~255之间] - * @return 返回处理结果 true:图片处理完成 false:图片处理失败 */ - public static boolean backgroundRemoval(final File input, final File output, final int tolerance) { - return backgroundRemoval(input, output, null, tolerance); + public static void backgroundRemoval(final File input, final File output, final int tolerance) { + backgroundRemoval(input, output, null, tolerance); } /** @@ -93,22 +90,20 @@ public class BackgroundRemoval { * 发现相同则将颜色不透明度设置为0,使颜色完全透明. * * @param input 需要进行操作的图片 - * @param output 最后输出的文件 + * @param output 最后输出的文件,必须为.png * @param override 指定替换成的背景颜色 为null时背景为透明 * @param tolerance 容差值[根据图片的主题色,加入容差值,值的取值范围在0~255之间] - * @return 返回处理结果 true:图片处理完成 false:图片处理失败 */ - public static boolean backgroundRemoval(final File input, final File output, final Color override, final int tolerance) { - if (fileTypeValidation(input, IMAGES_TYPE)) { - return false; - } + public static void backgroundRemoval(final File input, final File output, final Color override, final int tolerance) { + fileTypeValidation(input, IMAGES_TYPE); + BufferedImage bufferedImage = null; try { // 获取图片左上、中上、右上、右中、右下、下中、左下、左中、8个像素点rgb的16进制值 - final BufferedImage bufferedImage = ImageIO.read(input); + bufferedImage = ImgUtil.read(input); // 图片输出的格式为 png - return ImageIO.write(backgroundRemoval(bufferedImage, override, tolerance), "png", output); - } catch (final IOException e) { - throw new IORuntimeException(e); + ImgUtil.write(backgroundRemoval(bufferedImage, override, tolerance), output); + } finally { + ImgUtil.flush(bufferedImage); } } @@ -132,7 +127,7 @@ public class BackgroundRemoval { // 绘制icon final ImageIcon imageIcon = new ImageIcon(bufferedImage); final BufferedImage image = new BufferedImage(imageIcon.getIconWidth(), imageIcon.getIconHeight(), - BufferedImage.TYPE_4BYTE_ABGR); + BufferedImage.TYPE_4BYTE_ABGR); // 绘图工具 final Graphics graphics = image.getGraphics(); graphics.drawImage(imageIcon.getImage(), 0, 0, imageIcon.getImageObserver()); @@ -147,7 +142,7 @@ public class BackgroundRemoval { int rgb = image.getRGB(x, y); final String hex = ColorUtil.toHex((rgb & 0xff0000) >> 16, (rgb & 0xff00) >> 8, (rgb & 0xff)); final boolean isTrue = ArrayUtil.contains(removeRgb, hex) || - areColorsWithinTolerance(hexToRgb(mainColor), new Color(Integer.parseInt(hex.substring(1), 16)), tolerance); + areColorsWithinTolerance(hexToRgb(mainColor), new Color(Integer.parseInt(hex.substring(1), 16)), tolerance); if (isTrue) { rgb = override == null ? ((alpha + 1) << 24) | (rgb & 0x00ffffff) : override.getRGB(); } @@ -254,13 +249,13 @@ public class BackgroundRemoval { */ public static boolean areColorsWithinTolerance(final Color color1, final Color color2, final Color tolerance) { return (color1.getRed() - color2.getRed() < tolerance.getRed() && color1 - .getRed() - color2.getRed() > -tolerance.getRed()) - && (color1.getBlue() - color2.getBlue() < tolerance - .getBlue() && color1.getBlue() - color2.getBlue() > -tolerance - .getBlue()) - && (color1.getGreen() - color2.getGreen() < tolerance - .getGreen() && color1.getGreen() - - color2.getGreen() > -tolerance.getGreen()); + .getRed() - color2.getRed() > -tolerance.getRed()) + && (color1.getBlue() - color2.getBlue() < tolerance + .getBlue() && color1.getBlue() - color2.getBlue() > -tolerance + .getBlue()) + && (color1.getGreen() - color2.getGreen() < tolerance + .getGreen() && color1.getGreen() + - color2.getGreen() > -tolerance.getGreen()); } /** @@ -335,7 +330,7 @@ public class BackgroundRemoval { final int rgbLength = 3; if (strings.length == rgbLength) { return ColorUtil.toHex(Integer.parseInt(strings[0]), Integer.parseInt(strings[1]), - Integer.parseInt(strings[2])); + Integer.parseInt(strings[2])); } return StrUtil.EMPTY; } @@ -348,18 +343,14 @@ public class BackgroundRemoval { * * @param input 需要进行验证的文件 * @param imagesType 文件包含的类型数组 - * @return 返回布尔值 false:给定文件的文件类型在文件数组中 true:给定文件的文件类型 不在给定数组中。 */ - private static boolean fileTypeValidation(final File input, final String[] imagesType) { - if (!input.exists()) { - throw new IllegalArgumentException("给定文件为空"); - } + private static void fileTypeValidation(final File input, final String[] imagesType) { + Assert.isTrue(input.exists(), "File {} not exist!", input); // 获取图片类型 final String type = FileTypeUtil.getType(input); // 类型对比 if (!ArrayUtil.contains(imagesType, type)) { - throw new IllegalArgumentException(StrUtil.format("文件类型{}不支持", type)); + throw new IllegalArgumentException(StrUtil.format("Format {} of File not supported!", type)); } - return false; } } diff --git a/hutool-swing/src/main/java/org/dromara/hutool/swing/img/FontUtil.java b/hutool-swing/src/main/java/org/dromara/hutool/swing/img/FontUtil.java index 85d588e72..3020933f4 100644 --- a/hutool-swing/src/main/java/org/dromara/hutool/swing/img/FontUtil.java +++ b/hutool-swing/src/main/java/org/dromara/hutool/swing/img/FontUtil.java @@ -19,6 +19,9 @@ import java.awt.Dimension; import java.awt.Font; import java.awt.FontFormatException; import java.awt.FontMetrics; +import java.awt.font.FontRenderContext; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -119,4 +122,19 @@ public class FontUtil { return new Dimension(width, height); } + /** + * 获取font的样式应用在str上的整个矩形 + * + * @param str 字符串,必须非空 + * @param font 字体,必须非空 + * @return {@link Rectangle2D} + * @since 5.3.3 + */ + public static Rectangle2D getRectangle(final String str, final Font font) { + return font.getStringBounds(str, + new FontRenderContext(AffineTransform.getScaleInstance(1, 1), + false, + false)); + } + } diff --git a/hutool-swing/src/main/java/org/dromara/hutool/swing/img/GraphicsUtil.java b/hutool-swing/src/main/java/org/dromara/hutool/swing/img/GraphicsUtil.java index d1bbbf668..cd3baa4dc 100644 --- a/hutool-swing/src/main/java/org/dromara/hutool/swing/img/GraphicsUtil.java +++ b/hutool-swing/src/main/java/org/dromara/hutool/swing/img/GraphicsUtil.java @@ -185,8 +185,8 @@ public class GraphicsUtil { * @return 画笔对象 */ public static Graphics drawImg(final Graphics g, final Image img, final Point point) { - return drawImg(g, img, - new Rectangle(point.x, point.y, img.getWidth(null), img.getHeight(null))); + g.drawImage(img, point.x, point.y, null); + return g; } /** diff --git a/hutool-swing/src/main/java/org/dromara/hutool/swing/img/Img.java b/hutool-swing/src/main/java/org/dromara/hutool/swing/img/Img.java index e9f860833..1d35fb811 100644 --- a/hutool-swing/src/main/java/org/dromara/hutool/swing/img/Img.java +++ b/hutool-swing/src/main/java/org/dromara/hutool/swing/img/Img.java @@ -758,10 +758,13 @@ public class Img implements Flushable, Serializable { * 结果类型设定见{@link #setTargetImageType(String)} * * @param out 写出到的目标流 + * @return this * @throws IORuntimeException IO异常 */ - public void write(final OutputStream out) throws IORuntimeException { + public Img write(final OutputStream out) throws IORuntimeException { write(ImgUtil.getImageOutputStream(out)); + + return this; } /** @@ -769,9 +772,10 @@ public class Img implements Flushable, Serializable { * 结果类型设定见{@link #setTargetImageType(String)} * * @param targetImageStream 写出到的目标流 + * @return this * @throws IORuntimeException IO异常 */ - public void write(final ImageOutputStream targetImageStream) throws IORuntimeException { + public Img write(final ImageOutputStream targetImageStream) throws IORuntimeException { Assert.notBlank(this.targetImageType, "Target image type is blank !"); Assert.notNull(targetImageStream, "Target output stream is null !"); @@ -779,6 +783,8 @@ public class Img implements Flushable, Serializable { Assert.notNull(targetImage, "Target image is null !"); ImgUtil.write(targetImage, this.targetImageType, targetImageStream, this.quality, this.backgroundColor); + + return this; } /** @@ -786,8 +792,9 @@ public class Img implements Flushable, Serializable { * * @param targetFile 目标文件 * @throws IORuntimeException IO异常 + * @return this */ - public void write(final File targetFile) throws IORuntimeException { + public Img write(final File targetFile) throws IORuntimeException { final String formatName = FileNameUtil.extName(targetFile); if (StrUtil.isNotBlank(formatName)) { this.targetImageType = formatName; @@ -805,6 +812,7 @@ public class Img implements Flushable, Serializable { } finally { IoUtil.closeQuietly(out); } + return this; } @Override diff --git a/hutool-swing/src/main/java/org/dromara/hutool/swing/img/ImgUtil.java b/hutool-swing/src/main/java/org/dromara/hutool/swing/img/ImgUtil.java index 74cd43c8a..1aebce731 100644 --- a/hutool-swing/src/main/java/org/dromara/hutool/swing/img/ImgUtil.java +++ b/hutool-swing/src/main/java/org/dromara/hutool/swing/img/ImgUtil.java @@ -34,7 +34,6 @@ import javax.imageio.stream.ImageOutputStream; import javax.swing.ImageIcon; 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.*; @@ -88,7 +87,13 @@ public class ImgUtil { * @param scale 缩放比例。比例大于1时为放大,小于1大于0为缩小 */ public static void scale(final File srcImageFile, final File destImageFile, final float scale) { - scale(read(srcImageFile), destImageFile, scale); + BufferedImage image = null; + try { + image = read(srcImageFile); + scale(image, destImageFile, scale); + } finally { + flush(image); + } } /** @@ -101,27 +106,39 @@ public class ImgUtil { * @since 3.0.9 */ public static void scale(final InputStream srcStream, final OutputStream destStream, final float scale) { - scale(read(srcStream), destStream, scale); + BufferedImage image = null; + try { + image = read(srcStream); + scale(image, destStream, scale); + } finally { + flush(image); + } } /** * 缩放图像(按比例缩放)
* 缩放后默认为jpeg格式,此方法并不关闭流 * - * @param srcStream 源图像来源流 - * @param destStream 缩放后的图像写出到的流 - * @param scale 缩放比例。比例大于1时为放大,小于1大于0为缩小 + * @param srcStream 源图像来源流 + * @param targetStream 缩放后的图像写出到的流 + * @param scale 缩放比例。比例大于1时为放大,小于1大于0为缩小 * @since 3.1.0 */ - public static void scale(final ImageInputStream srcStream, final ImageOutputStream destStream, final float scale) { - scale(read(srcStream), destStream, scale); + public static void scale(final ImageInputStream srcStream, final ImageOutputStream targetStream, final float scale) { + BufferedImage image = null; + try { + image = read(srcStream); + scale(image, targetStream, scale); + } finally { + flush(image); + } } /** * 缩放图像(按比例缩放)
* 缩放后默认为jpeg格式,此方法并不关闭流 * - * @param srcImg 源图像来源流 + * @param srcImg 源图像来源流,使用结束后需手动调用{@link #flush(Image)}释放资源 * @param destFile 缩放后的图像写出到的流 * @param scale 缩放比例。比例大于1时为放大,小于1大于0为缩小 * @throws IORuntimeException IO异常 @@ -135,7 +152,7 @@ public class ImgUtil { * 缩放图像(按比例缩放)
* 缩放后默认为jpeg格式,此方法并不关闭流 * - * @param srcImg 源图像来源流 + * @param srcImg 源图像来源流,使用结束后需手动调用{@link #flush(Image)}释放资源 * @param out 缩放后的图像写出到的流 * @param scale 缩放比例。比例大于1时为放大,小于1大于0为缩小 * @throws IORuntimeException IO异常 @@ -149,7 +166,7 @@ public class ImgUtil { * 缩放图像(按比例缩放)
* 缩放后默认为jpeg格式,此方法并不关闭流 * - * @param srcImg 源图像来源流 + * @param srcImg 源图像来源流,使用结束后需手动调用{@link #flush(Image)}释放资源 * @param destImageStream 缩放后的图像写出到的流 * @param scale 缩放比例。比例大于1时为放大,小于1大于0为缩小 * @throws IORuntimeException IO异常 @@ -162,7 +179,7 @@ public class ImgUtil { /** * 缩放图像(按比例缩放) * - * @param srcImg 源图像来源流 + * @param srcImg 源图像来源流,使用结束后需手动调用{@link #flush(Image)}释放资源 * @param scale 缩放比例。比例大于1时为放大,小于1大于0为缩小 * @return {@link Image} * @since 3.1.0 @@ -175,7 +192,7 @@ public class ImgUtil { * 缩放图像(按长宽缩放)
* 注意:目标长宽与原图不成比例会变形 * - * @param srcImg 源图像来源流 + * @param srcImg 源图像来源流,使用结束后需手动调用{@link #flush(Image)}释放资源 * @param width 目标宽度 * @param height 目标高度 * @return {@link Image} @@ -189,18 +206,23 @@ public class ImgUtil { * 缩放图像(按高度和宽度缩放)
* 缩放后默认格式与源图片相同,无法识别原图片默认JPG * - * @param srcImageFile 源图像文件地址 - * @param destImageFile 缩放后的图像地址 - * @param width 缩放后的宽度 - * @param height 缩放后的高度 - * @param fixedColor 补充的颜色,不补充为{@code null} + * @param srcImageFile 源图像文件地址 + * @param targetImageFile 缩放后的图像地址 + * @param width 缩放后的宽度 + * @param height 缩放后的高度 + * @param fixedColor 补充的颜色,不补充为{@code null} * @throws IORuntimeException IO异常 */ - public static void scale(final File srcImageFile, final File destImageFile, final int width, final int height, final Color fixedColor) throws IORuntimeException { - Img.from(srcImageFile)// - .setTargetImageType(FileNameUtil.extName(destImageFile))// - .scale(width, height, fixedColor)// - .write(destImageFile); + public static void scale(final File srcImageFile, final File targetImageFile, final int width, final int height, final Color fixedColor) throws IORuntimeException { + Img img = null; + try { + img = Img.from(srcImageFile); + img.setTargetImageType(FileNameUtil.extName(targetImageFile)) + .scale(width, height, fixedColor)// + .write(targetImageFile); + } finally { + IoUtil.flush(img); + } } /** @@ -222,15 +244,21 @@ public class ImgUtil { * 缩放图像(按高度和宽度缩放)
* 缩放后默认为jpeg格式,此方法并不关闭流 * - * @param srcStream 源图像流 - * @param destStream 缩放后的图像目标流 - * @param width 缩放后的宽度 - * @param height 缩放后的高度 - * @param fixedColor 比例不对时补充的颜色,不补充为{@code null} + * @param srcStream 源图像流 + * @param targetStream 缩放后的图像目标流 + * @param width 缩放后的宽度 + * @param height 缩放后的高度 + * @param fixedColor 比例不对时补充的颜色,不补充为{@code null} * @throws IORuntimeException IO异常 */ - public static void scale(final ImageInputStream srcStream, final ImageOutputStream destStream, final int width, final int height, final Color fixedColor) throws IORuntimeException { - scale(read(srcStream), destStream, width, height, fixedColor); + public static void scale(final ImageInputStream srcStream, final ImageOutputStream targetStream, final int width, final int height, final Color fixedColor) throws IORuntimeException { + BufferedImage image = null; + try { + image = read(srcStream); + scale(image, targetStream, width, height, fixedColor); + } finally { + flush(image); + } } /** @@ -274,37 +302,55 @@ public class ImgUtil { * @since 3.1.0 */ public static void cut(final File srcImgFile, final File destImgFile, final Rectangle rectangle) { - cut(read(srcImgFile), destImgFile, rectangle); + BufferedImage image = null; + try { + image = read(srcImgFile); + cut(image, destImgFile, rectangle); + } finally { + flush(image); + } } /** * 图像切割(按指定起点坐标和宽高切割),此方法并不关闭流 * - * @param srcStream 源图像流 - * @param destStream 切片后的图像输出流 - * @param rectangle 矩形对象,表示矩形区域的x,y,width,height + * @param srcStream 源图像流 + * @param targetStream 切片后的图像输出流 + * @param rectangle 矩形对象,表示矩形区域的x,y,width,height * @since 3.1.0 */ - public static void cut(final InputStream srcStream, final OutputStream destStream, final Rectangle rectangle) { - cut(read(srcStream), destStream, rectangle); + public static void cut(final InputStream srcStream, final OutputStream targetStream, final Rectangle rectangle) { + BufferedImage image = null; + try { + image = read(srcStream); + cut(image, targetStream, rectangle); + } finally { + flush(image); + } } /** * 图像切割(按指定起点坐标和宽高切割),此方法并不关闭流 * - * @param srcStream 源图像流 - * @param destStream 切片后的图像输出流 - * @param rectangle 矩形对象,表示矩形区域的x,y,width,height + * @param srcStream 源图像流 + * @param targetStream 切片后的图像输出流 + * @param rectangle 矩形对象,表示矩形区域的x,y,width,height * @since 3.1.0 */ - public static void cut(final ImageInputStream srcStream, final ImageOutputStream destStream, final Rectangle rectangle) { - cut(read(srcStream), destStream, rectangle); + public static void cut(final ImageInputStream srcStream, final ImageOutputStream targetStream, final Rectangle rectangle) { + BufferedImage image = null; + try { + image = read(srcStream); + cut(image, targetStream, rectangle); + } finally { + flush(image); + } } /** * 图像切割(按指定起点坐标和宽高切割),此方法并不关闭流 * - * @param srcImage 源图像 + * @param srcImage 源图像,使用结束后需手动调用{@link #flush(Image)}释放资源 * @param destFile 输出的文件 * @param rectangle 矩形对象,表示矩形区域的x,y,width,height * @throws IORuntimeException IO异常 @@ -330,20 +376,20 @@ public class ImgUtil { /** * 图像切割(按指定起点坐标和宽高切割),此方法并不关闭流 * - * @param srcImage 源图像 - * @param destImageStream 切片后的图像输出流 - * @param rectangle 矩形对象,表示矩形区域的x,y,width,height + * @param srcImage 源图像,使用结束后需手动调用{@link #flush(Image)}释放资源 + * @param targetImageStream 切片后的图像输出流 + * @param rectangle 矩形对象,表示矩形区域的x,y,width,height * @throws IORuntimeException IO异常 * @since 3.1.0 */ - public static void cut(final Image srcImage, final ImageOutputStream destImageStream, final Rectangle rectangle) throws IORuntimeException { - writeJpg(cut(srcImage, rectangle), destImageStream); + public static void cut(final Image srcImage, final ImageOutputStream targetImageStream, final Rectangle rectangle) throws IORuntimeException { + writeJpg(cut(srcImage, rectangle), targetImageStream); } /** * 图像切割(按指定起点坐标和宽高切割) * - * @param srcImage 源图像 + * @param srcImage 源图像,使用结束后需手动调用{@link #flush(Image)}释放资源 * @param rectangle 矩形对象,表示矩形区域的x,y,width,height * @return {@link BufferedImage} * @since 3.1.0 @@ -355,7 +401,7 @@ public class ImgUtil { /** * 图像切割(按指定起点坐标和宽高切割),填充满整个图片(直径取长宽最小值) * - * @param srcImage 源图像 + * @param srcImage 源图像,使用结束后需手动调用{@link #flush(Image)}释放资源 * @param x 原图的x坐标起始位置 * @param y 原图的y坐标起始位置 * @return {@link Image} @@ -368,7 +414,7 @@ public class ImgUtil { /** * 图像切割(按指定起点坐标和宽高切割) * - * @param srcImage 源图像 + * @param srcImage 源图像,使用结束后需手动调用{@link #flush(Image)}释放资源 * @param x 原图的x坐标起始位置 * @param y 原图的y坐标起始位置 * @param radius 半径,小于0表示填充满整个图片(直径取长宽最小值) @@ -384,50 +430,56 @@ public class ImgUtil { * * @param srcImageFile 源图像 * @param descDir 切片目标文件夹 - * @param destWidth 目标切片宽度。默认200 - * @param destHeight 目标切片高度。默认150 + * @param targetWidth 目标切片宽度。默认200 + * @param targetHeight 目标切片高度。默认150 */ - public static void slice(final File srcImageFile, final File descDir, final int destWidth, final int destHeight) { - slice(read(srcImageFile), descDir, destWidth, destHeight); + public static void slice(final File srcImageFile, final File descDir, final int targetWidth, final int targetHeight) { + BufferedImage image = null; + try { + image = read(srcImageFile); + slice(image, descDir, targetWidth, targetHeight); + } finally { + flush(image); + } } /** * 图像切片(指定切片的宽度和高度) * - * @param srcImage 源图像 - * @param descDir 切片目标文件夹 - * @param destWidth 目标切片宽度。默认200 - * @param destHeight 目标切片高度。默认150 + * @param srcImage 源图像,使用结束后需手动调用{@link #flush(Image)}释放资源 + * @param descDir 切片目标文件夹 + * @param targetWidth 目标切片宽度。默认200 + * @param targetHeight 目标切片高度。默认150 */ - public static void slice(final Image srcImage, final File descDir, int destWidth, int destHeight) { - if (destWidth <= 0) { - destWidth = 200; // 切片宽度 + public static void slice(final Image srcImage, final File descDir, int targetWidth, int targetHeight) { + if (targetWidth <= 0) { + targetWidth = 200; // 切片宽度 } - if (destHeight <= 0) { - destHeight = 150; // 切片高度 + if (targetHeight <= 0) { + targetHeight = 150; // 切片高度 } final int srcWidth = srcImage.getWidth(null); // 源图宽度 final int srcHeight = srcImage.getHeight(null); // 源图高度 - if (srcWidth < destWidth) { - destWidth = srcWidth; + if (srcWidth < targetWidth) { + targetWidth = srcWidth; } - if (srcHeight < destHeight) { - destHeight = srcHeight; + if (srcHeight < targetHeight) { + targetHeight = srcHeight; } final int cols; // 切片横向数量 final int rows; // 切片纵向数量 // 计算切片的横向和纵向数量 - if (srcWidth % destWidth == 0) { - cols = srcWidth / destWidth; + if (srcWidth % targetWidth == 0) { + cols = srcWidth / targetWidth; } else { - cols = (int) Math.floor((double) srcWidth / destWidth) + 1; + cols = (int) Math.floor((double) srcWidth / targetWidth) + 1; } - if (srcHeight % destHeight == 0) { - rows = srcHeight / destHeight; + if (srcHeight % targetHeight == 0) { + rows = srcHeight / targetHeight; } else { - rows = (int) Math.floor((double) srcHeight / destHeight) + 1; + rows = (int) Math.floor((double) srcHeight / targetHeight) + 1; } // 循环建立切片 Image tag; @@ -435,7 +487,7 @@ public class ImgUtil { for (int j = 0; j < cols; j++) { // 四个参数分别为图像起点坐标和宽高 // 即: CropImageFilter(int x,int y,int width,int height) - tag = cut(srcImage, new Rectangle(j * destWidth, i * destHeight, destWidth, destHeight)); + tag = cut(srcImage, new Rectangle(j * targetWidth, i * targetHeight, targetWidth, targetHeight)); // 输出为文件 write(tag, FileUtil.file(descDir, "_r" + i + "_c" + j + ".jpg")); } @@ -452,13 +504,19 @@ public class ImgUtil { * @param cols 目标切片列数。默认2,必须是范围 [1, 20] 之内 */ public static void sliceByRowsAndCols(final File srcImageFile, final File targetDir, final String formatName, final int rows, final int cols) { - sliceByRowsAndCols(read(srcImageFile), targetDir, formatName, rows, cols); + BufferedImage image = null; + try { + image = read(srcImageFile); + sliceByRowsAndCols(image, targetDir, formatName, rows, cols); + } finally { + flush(image); + } } /** * 图像切割(指定切片的行数和列数),默认RGB模式 * - * @param srcImage 源图像,如果非{@link BufferedImage},则默认使用RGB模式 + * @param srcImage 源图像,如果非{@link BufferedImage},则默认使用RGB模式,使用结束后需手动调用{@link #flush(Image)}释放资源 * @param destDir 切片目标文件夹 * @param formatName 格式名称,即图片格式后缀 * @param rows 目标切片行数。默认2,必须是范围 [1, 20] 之内 @@ -517,7 +575,13 @@ public class ImgUtil { FileUtil.copy(srcImageFile, targetImageFile, true); } - Img.from(srcImageFile).write(targetImageFile); + Img img = null; + try { + img = Img.from(srcImageFile); + img.write(targetImageFile); + } finally { + IoUtil.flush(img); + } } /** @@ -530,14 +594,20 @@ public class ImgUtil { * @since 3.0.9 */ public static void convert(final InputStream srcStream, final String formatName, final OutputStream targetStream) { - write(read(srcStream), formatName, getImageOutputStream(targetStream)); + BufferedImage image = null; + try { + image = read(srcStream); + write(image, formatName, getImageOutputStream(targetStream)); + } finally { + flush(image); + } } /** * 图像类型转换:GIF=》JPG、GIF=》PNG、PNG=》JPG、PNG=》GIF(X)、BMP=》PNG
* 此方法并不关闭流 * - * @param srcImage 源图像流 + * @param srcImage 源图像流,使用结束后需手动调用{@link #flush(Image)}释放资源 * @param formatName 包含格式非正式名称的 String:如JPG、JPEG、GIF等 * @param targetImageStream 目标图像输出流 * @since 4.1.14 @@ -552,41 +622,59 @@ public class ImgUtil { /** * 彩色转为黑白 * - * @param srcImageFile 源图像地址 - * @param destImageFile 目标图像地址 + * @param srcImageFile 源图像地址 + * @param targetImageFile 目标图像地址 */ - public static void gray(final File srcImageFile, final File destImageFile) { - gray(read(srcImageFile), destImageFile); + public static void gray(final File srcImageFile, final File targetImageFile) { + BufferedImage image = null; + try { + image = read(srcImageFile); + gray(image, targetImageFile); + } finally { + flush(image); + } } /** * 彩色转为黑白
* 此方法并不关闭流 * - * @param srcStream 源图像流 - * @param destStream 目标图像流 + * @param srcStream 源图像流 + * @param targetStream 目标图像流 * @since 3.0.9 */ - public static void gray(final InputStream srcStream, final OutputStream destStream) { - gray(read(srcStream), getImageOutputStream(destStream)); + public static void gray(final InputStream srcStream, final OutputStream targetStream) { + BufferedImage image = null; + try { + image = read(srcStream); + gray(image, targetStream); + } finally { + flush(image); + } } /** * 彩色转为黑白
* 此方法并不关闭流 * - * @param srcStream 源图像流 - * @param destStream 目标图像流 + * @param srcStream 源图像流 + * @param targetStream 目标图像流 * @since 3.0.9 */ - public static void gray(final ImageInputStream srcStream, final ImageOutputStream destStream) { - gray(read(srcStream), destStream); + public static void gray(final ImageInputStream srcStream, final ImageOutputStream targetStream) { + BufferedImage image = null; + try { + image = read(srcStream); + gray(image, targetStream); + } finally { + flush(image); + } } /** * 彩色转为黑白 * - * @param srcImage 源图像流 + * @param srcImage 源图像流,使用结束后需手动调用{@link #flush(Image)}释放资源 * @param outFile 目标文件 * @since 3.2.2 */ @@ -598,7 +686,7 @@ public class ImgUtil { * 彩色转为黑白
* 此方法并不关闭流 * - * @param srcImage 源图像流 + * @param srcImage 源图像流,使用结束后需手动调用{@link #flush(Image)}释放资源 * @param out 目标图像流 * @since 3.2.2 */ @@ -610,19 +698,19 @@ public class ImgUtil { * 彩色转为黑白
* 此方法并不关闭流 * - * @param srcImage 源图像流 - * @param destImageStream 目标图像流 + * @param srcImage 源图像流,使用结束后需手动调用{@link #flush(Image)}释放资源 + * @param targetImageStream 目标图像流 * @throws IORuntimeException IO异常 * @since 3.0.9 */ - public static void gray(final Image srcImage, final ImageOutputStream destImageStream) throws IORuntimeException { - writeJpg(gray(srcImage), destImageStream); + public static void gray(final Image srcImage, final ImageOutputStream targetImageStream) throws IORuntimeException { + writeJpg(gray(srcImage), targetImageStream); } /** * 彩色转为黑白 * - * @param srcImage 源图像流 + * @param srcImage 源图像流,使用结束后需手动调用{@link #flush(Image)}释放资源 * @return {@link Image}灰度后的图片 * @since 3.1.0 */ @@ -636,11 +724,17 @@ public class ImgUtil { /** * 彩色转为黑白二值化图片,根据目标文件扩展名确定转换后的格式 * - * @param srcImageFile 源图像地址 - * @param destImageFile 目标图像地址 + * @param srcImageFile 源图像地址 + * @param targetImageFile 目标图像地址 */ - public static void binary(final File srcImageFile, final File destImageFile) { - binary(read(srcImageFile), destImageFile); + public static void binary(final File srcImageFile, final File targetImageFile) { + BufferedImage image = null; + try { + image = read(srcImageFile); + binary(image, targetImageFile); + } finally { + flush(image); + } } /** @@ -653,26 +747,38 @@ public class ImgUtil { * @since 4.0.5 */ public static void binary(final InputStream srcStream, final OutputStream destStream, final String imageType) { - binary(read(srcStream), getImageOutputStream(destStream), imageType); + BufferedImage image = null; + try { + image = read(srcStream); + binary(image, getImageOutputStream(destStream), imageType); + } finally { + flush(image); + } } /** * 彩色转为黑白黑白二值化图片
* 此方法并不关闭流 * - * @param srcStream 源图像流 - * @param destStream 目标图像流 - * @param imageType 图片格式(扩展名) + * @param srcStream 源图像流 + * @param targetStream 目标图像流 + * @param imageType 图片格式(扩展名) * @since 4.0.5 */ - public static void binary(final ImageInputStream srcStream, final ImageOutputStream destStream, final String imageType) { - binary(read(srcStream), destStream, imageType); + public static void binary(final ImageInputStream srcStream, final ImageOutputStream targetStream, final String imageType) { + BufferedImage image = null; + try { + image = read(srcStream); + binary(image, targetStream, imageType); + } finally { + flush(image); + } } /** * 彩色转为黑白二值化图片,根据目标文件扩展名确定转换后的格式 * - * @param srcImage 源图像流 + * @param srcImage 源图像流,使用结束后需手动调用{@link #flush(Image)}释放资源 * @param outFile 目标文件 * @since 4.0.5 */ @@ -684,7 +790,7 @@ public class ImgUtil { * 彩色转为黑白二值化图片
* 此方法并不关闭流,输出JPG格式 * - * @param srcImage 源图像流 + * @param srcImage 源图像流,使用结束后需手动调用{@link #flush(Image)}释放资源 * @param out 目标图像流 * @param imageType 图片格式(扩展名) * @since 4.0.5 @@ -697,20 +803,20 @@ public class ImgUtil { * 彩色转为黑白二值化图片
* 此方法并不关闭流,输出JPG格式 * - * @param srcImage 源图像流 - * @param destImageStream 目标图像流 - * @param imageType 图片格式(扩展名) + * @param srcImage 源图像流,使用结束后需手动调用{@link #flush(Image)}释放资源 + * @param targetImageStream 目标图像流 + * @param imageType 图片格式(扩展名) * @throws IORuntimeException IO异常 * @since 4.0.5 */ - public static void binary(final Image srcImage, final ImageOutputStream destImageStream, final String imageType) throws IORuntimeException { - write(binary(srcImage), imageType, destImageStream); + public static void binary(final Image srcImage, final ImageOutputStream targetImageStream, final String imageType) throws IORuntimeException { + write(binary(srcImage), imageType, targetImageStream); } /** * 彩色转为黑白二值化图片 * - * @param srcImage 源图像流 + * @param srcImage 源图像流,使用结束后需手动调用{@link #flush(Image)}释放资源 * @return {@link Image}二值化后的图片 * @since 4.0.5 */ @@ -724,45 +830,57 @@ public class ImgUtil { /** * 给图片添加文字水印 * - * @param imageFile 源图像文件 - * @param destFile 目标图像文件 - * @param pressText 水印文字 + * @param imageFile 源图像文件 + * @param targetFile 目标图像文件 + * @param pressText 水印文字 */ - public static void pressText(final File imageFile, final File destFile, final DisplayText pressText) { - pressText(read(imageFile), destFile, pressText); + public static void pressText(final File imageFile, final File targetFile, final DisplayText pressText) { + BufferedImage image = null; + try { + image = read(imageFile); + pressText(image, targetFile, pressText); + } finally { + flush(image); + } } /** * 给图片添加文字水印
* 此方法并不关闭流 * - * @param srcStream 源图像流 - * @param destStream 目标图像流 - * @param pressText 水印文本信息 + * @param srcStream 源图像流 + * @param targetStream 目标图像流 + * @param pressText 水印文本信息 */ - public static void pressText(final InputStream srcStream, final OutputStream destStream, final DisplayText pressText) { - pressText(read(srcStream), getImageOutputStream(destStream), pressText); + public static void pressText(final InputStream srcStream, final OutputStream targetStream, final DisplayText pressText) { + BufferedImage image = null; + try { + image = read(srcStream); + pressText(image, getImageOutputStream(targetStream), pressText); + } finally { + flush(image); + } } /** * 给图片添加文字水印
* 此方法并不关闭流 * - * @param srcImage 源图像 - * @param destFile 目标流 - * @param pressText 水印文字信息 + * @param srcImage 源图像,使用结束后需手动调用{@link #flush(Image)}释放资源 + * @param targetFile 目标流 + * @param pressText 水印文字信息 * @throws IORuntimeException IO异常 * @since 3.2.2 */ - public static void pressText(final Image srcImage, final File destFile, final DisplayText pressText) throws IORuntimeException { - write(pressText(srcImage, pressText), destFile); + public static void pressText(final Image srcImage, final File targetFile, final DisplayText pressText) throws IORuntimeException { + write(pressText(srcImage, pressText), targetFile); } /** * 给图片添加文字水印
* 此方法并不关闭流 * - * @param srcImage 源图像 + * @param srcImage 源图像,使用结束后需手动调用{@link #flush(Image)}释放资源 * @param to 目标流 * @param pressText 水印文字信息 * @throws IORuntimeException IO异常 @@ -776,20 +894,20 @@ public class ImgUtil { * 给图片添加文字水印
* 此方法并不关闭流 * - * @param srcImage 源图像 - * @param destImageStream 目标图像流 - * @param pressText 水印文字信息 + * @param srcImage 源图像,使用结束后需手动调用{@link #flush(Image)}释放资源 + * @param targetImageStream 目标图像流 + * @param pressText 水印文字信息 * @throws IORuntimeException IO异常 */ - public static void pressText(final Image srcImage, final ImageOutputStream destImageStream, final DisplayText pressText) throws IORuntimeException { - writeJpg(pressText(srcImage, pressText), destImageStream); + public static void pressText(final Image srcImage, final ImageOutputStream targetImageStream, final DisplayText pressText) throws IORuntimeException { + writeJpg(pressText(srcImage, pressText), targetImageStream); } /** * 给图片添加文字水印
* 此方法并不关闭流 * - * @param srcImage 源图像 + * @param srcImage 源图像,使用结束后需手动调用{@link #flush(Image)}释放资源 * @param pressText 水印文字信息 * @return 处理后的图像 * @since 3.2.2 @@ -802,7 +920,7 @@ public class ImgUtil { * 给图片添加全屏文字水印
* 此方法并不关闭流 * - * @param srcImage 源图像 + * @param srcImage 源图像,使用结束后需手动调用{@link #flush(Image)}释放资源 * @param pressText 水印文字 * @param color 水印的字体颜色 * @param font {@link Font} 字体相关信息,如果默认则为{@code null} @@ -819,37 +937,49 @@ public class ImgUtil { /** * 给图片添加图片水印 * - * @param srcImageFile 源图像文件 - * @param destImageFile 目标图像文件 - * @param pressImg 水印图片 - * @param x 修正值。 默认在中间,偏移量相对于中间偏移 - * @param y 修正值。 默认在中间,偏移量相对于中间偏移 - * @param alpha 透明度:alpha 必须是范围 [0.0, 1.0] 之内(包含边界值)的一个浮点数字 + * @param srcImageFile 源图像文件 + * @param targetImageFile 目标图像文件 + * @param pressImg 水印图片,使用结束后需手动调用{@link #flush(Image)}释放资源 + * @param x 修正值。 默认在中间,偏移量相对于中间偏移 + * @param y 修正值。 默认在中间,偏移量相对于中间偏移 + * @param alpha 透明度:alpha 必须是范围 [0.0, 1.0] 之内(包含边界值)的一个浮点数字 */ - public static void pressImage(final File srcImageFile, final File destImageFile, final Image pressImg, final int x, final int y, final float alpha) { - pressImage(read(srcImageFile), destImageFile, pressImg, x, y, alpha); + public static void pressImage(final File srcImageFile, final File targetImageFile, final Image pressImg, final int x, final int y, final float alpha) { + BufferedImage image = null; + try { + image = read(srcImageFile); + pressImage(image, targetImageFile, pressImg, x, y, alpha); + } finally { + flush(image); + } } /** * 给图片添加图片水印
* 此方法并不关闭流 * - * @param srcStream 源图像流 - * @param destStream 目标图像流 - * @param pressImg 水印图片,可以使用{@link ImageIO#read(File)}方法读取文件 - * @param x 修正值。 默认在中间,偏移量相对于中间偏移 - * @param y 修正值。 默认在中间,偏移量相对于中间偏移 - * @param alpha 透明度:alpha 必须是范围 [0.0, 1.0] 之内(包含边界值)的一个浮点数字 + * @param srcStream 源图像流 + * @param targetStream 目标图像流 + * @param pressImg 水印图片,可以使用{@link ImageIO#read(File)}方法读取文件 + * @param x 修正值。 默认在中间,偏移量相对于中间偏移 + * @param y 修正值。 默认在中间,偏移量相对于中间偏移 + * @param alpha 透明度:alpha 必须是范围 [0.0, 1.0] 之内(包含边界值)的一个浮点数字 */ - public static void pressImage(final InputStream srcStream, final OutputStream destStream, final Image pressImg, final int x, final int y, final float alpha) { - pressImage(read(srcStream), getImageOutputStream(destStream), pressImg, x, y, alpha); + public static void pressImage(final InputStream srcStream, final OutputStream targetStream, final Image pressImg, final int x, final int y, final float alpha) { + BufferedImage image = null; + try { + image = read(srcStream); + pressImage(image, getImageOutputStream(targetStream), pressImg, x, y, alpha); + } finally { + flush(image); + } } /** * 给图片添加图片水印
* 此方法并不关闭流 * - * @param srcImage 源图像流 + * @param srcImage 源图像流,使用结束后需手动调用{@link #flush(Image)}释放资源 * @param outFile 写出文件 * @param pressImg 水印图片,可以使用{@link ImageIO#read(File)}方法读取文件 * @param x 修正值。 默认在中间,偏移量相对于中间偏移 @@ -863,10 +993,10 @@ public class ImgUtil { } /** - * 给图片添加图片水印
+ * 给图片添加图片水印,写出目标图片格式为JPG
* 此方法并不关闭流 * - * @param srcImage 源图像流 + * @param srcImage 源图像流,使用结束后需手动调用{@link #flush(Image)}释放资源 * @param out 目标图像流 * @param pressImg 水印图片,可以使用{@link ImageIO#read(File)}方法读取文件 * @param x 修正值。 默认在中间,偏移量相对于中间偏移 @@ -880,26 +1010,26 @@ public class ImgUtil { } /** - * 给图片添加图片水印
+ * 给图片添加图片水印,写出目标图片格式为JPG
* 此方法并不关闭流 * - * @param srcImage 源图像流 - * @param destImageStream 目标图像流 - * @param pressImg 水印图片,可以使用{@link ImageIO#read(File)}方法读取文件 - * @param x 修正值。 默认在中间,偏移量相对于中间偏移 - * @param y 修正值。 默认在中间,偏移量相对于中间偏移 - * @param alpha 透明度:alpha 必须是范围 [0.0, 1.0] 之内(包含边界值)的一个浮点数字 + * @param srcImage 源图像流,使用结束后需手动调用{@link #flush(Image)}释放资源 + * @param targetImageStream 目标图像流 + * @param pressImg 水印图片,可以使用{@link ImageIO#read(File)}方法读取文件 + * @param x 修正值。 默认在中间,偏移量相对于中间偏移 + * @param y 修正值。 默认在中间,偏移量相对于中间偏移 + * @param alpha 透明度:alpha 必须是范围 [0.0, 1.0] 之内(包含边界值)的一个浮点数字 * @throws IORuntimeException IO异常 */ - public static void pressImage(final Image srcImage, final ImageOutputStream destImageStream, final Image pressImg, final int x, final int y, final float alpha) throws IORuntimeException { - writeJpg(pressImage(srcImage, pressImg, x, y, alpha), destImageStream); + public static void pressImage(final Image srcImage, final ImageOutputStream targetImageStream, final Image pressImg, final int x, final int y, final float alpha) throws IORuntimeException { + writeJpg(pressImage(srcImage, pressImg, x, y, alpha), targetImageStream); } /** * 给图片添加图片水印
* 此方法并不关闭流 * - * @param srcImage 源图像流 + * @param srcImage 源图像流,使用结束后需手动调用{@link #flush(Image)}释放资源 * @param pressImg 水印图片,可以使用{@link ImageIO#read(File)}方法读取文件 * @param x 修正值。 默认在中间,偏移量相对于中间偏移 * @param y 修正值。 默认在中间,偏移量相对于中间偏移 @@ -914,7 +1044,7 @@ public class ImgUtil { * 给图片添加图片水印
* 此方法并不关闭流 * - * @param srcImage 源图像流 + * @param srcImage 源图像流,使用结束后需手动调用{@link #flush(Image)}释放资源 * @param pressImg 水印图片,可以使用{@link ImageIO#read(File)}方法读取文件 * @param rectangle 矩形对象,表示矩形区域的x,y,width,height,x,y从背景图片中心计算 * @param alpha 透明度:alpha 必须是范围 [0.0, 1.0] 之内(包含边界值)的一个浮点数字 @@ -926,44 +1056,56 @@ public class ImgUtil { } /** - * 给图片添加全屏图片水印
+ * 给图片添加全屏图片水印 * * @param imageFile 源图像文件 - * @param destFile 目标图像文件 + * @param targetFile 目标图像文件 * @param pressImageFile 水印图像文件 * @param lineHeight 行高 * @param degree 水印图像旋转角度,(单位:弧度),以圆点(0,0)为圆心,正代表顺时针,负代表逆时针 * @param alpha 透明度:alpha 必须是范围 [0.0, 1.0] 之内(包含边界值)的一个浮点数字 * @throws IORuntimeException IO异常 */ - public static void pressImageFull(final File imageFile, final File destFile, final File pressImageFile, + public static void pressImageFull(final File imageFile, final File targetFile, final File pressImageFile, final int lineHeight, final int degree, final float alpha) throws IORuntimeException { - write(pressImageFull(read(imageFile), read(pressImageFile), lineHeight, degree, alpha), destFile); + BufferedImage image = null; + try { + image = read(imageFile); + write(pressImageFull(image, read(pressImageFile), lineHeight, degree, alpha), targetFile); + } finally { + flush(image); + } } /** - * 给图片添加全屏图像水印
+ * 给图片添加全屏图像水印,写出格式为JPG
* 此方法并不关闭流 * - * @param srcStream 源图像流 - * @param destStream 目标图像流 - * @param pressStream 水印图像流 - * @param lineHeight 行高 - * @param degree 水印图像旋转角度,(单位:弧度),以圆点(0,0)为圆心,正代表顺时针,负代表逆时针 - * @param alpha 透明度:alpha 必须是范围 [0.0, 1.0] 之内(包含边界值)的一个浮点数字 + * @param srcStream 源图像流 + * @param targetStream 目标图像流 + * @param pressStream 水印图像流 + * @param lineHeight 行高 + * @param degree 水印图像旋转角度,(单位:弧度),以圆点(0,0)为圆心,正代表顺时针,负代表逆时针 + * @param alpha 透明度:alpha 必须是范围 [0.0, 1.0] 之内(包含边界值)的一个浮点数字 * @throws IORuntimeException IO异常 */ - public static void pressImageFull(final InputStream srcStream, final OutputStream destStream, + public static void pressImageFull(final InputStream srcStream, final OutputStream targetStream, final InputStream pressStream, final int lineHeight, final int degree, final float alpha) throws IORuntimeException { - writeJpg(pressImageFull(read(srcStream), read(pressStream), lineHeight, degree, alpha), destStream); + BufferedImage image = null; + try { + image = read(srcStream); + writeJpg(pressImageFull(image, read(pressStream), lineHeight, degree, alpha), targetStream); + } finally { + flush(image); + } } /** * 给图片添加全屏图像水印
* 此方法并不关闭流 * - * @param srcImage 源图像 - * @param pressImage 水印图像 + * @param srcImage 源图像,使用结束后需手动调用{@link #flush(Image)}释放资源 + * @param pressImage 水印图像,使用结束后需手动调用{@link #flush(Image)}释放资源 * @param lineHeight 行高 * @param degree 水印图像旋转角度,(单位:弧度),以圆点(0,0)为圆心,正代表顺时针,负代表逆时针,(单位:弧度),以圆点(0,0)为圆心,正代表顺时针,负代表逆时针 * @param alpha 透明度:alpha 必须是范围 [0.0, 1.0] 之内(包含边界值)的一个浮点数字 @@ -987,14 +1129,20 @@ public class ImgUtil { * @since 3.2.2 */ public static void rotate(final File imageFile, final int degree, final File outFile) throws IORuntimeException { - rotate(read(imageFile), degree, outFile); + BufferedImage image = null; + try { + image = read(imageFile); + rotate(image, degree, outFile); + } finally { + flush(image); + } } /** * 旋转图片为指定角度
* 此方法不会关闭输出流 * - * @param image 目标图像 + * @param image 需要旋转的图像,使用结束后需手动调用{@link #flush(Image)}释放资源 * @param degree 旋转角度 * @param outFile 输出文件 * @throws IORuntimeException IO异常 @@ -1008,7 +1156,7 @@ public class ImgUtil { * 旋转图片为指定角度
* 此方法不会关闭输出流 * - * @param image 目标图像 + * @param image 需要旋转的图像,使用结束后需手动调用{@link #flush(Image)}释放资源 * @param degree 旋转角度 * @param out 输出流 * @throws IORuntimeException IO异常 @@ -1022,7 +1170,7 @@ public class ImgUtil { * 旋转图片为指定角度
* 此方法不会关闭输出流,输出格式为JPG * - * @param image 目标图像 + * @param image 需要旋转的图像,使用结束后需手动调用{@link #flush(Image)}释放资源 * @param degree 旋转角度 * @param out 输出图像流 * @throws IORuntimeException IO异常 @@ -1036,7 +1184,7 @@ public class ImgUtil { * 旋转图片为指定角度
* 来自:http://blog.51cto.com/cping1982/130066 * - * @param image 目标图像 + * @param image 需要旋转的图像,使用结束后需手动调用{@link #flush(Image)}释放资源 * @param degree 旋转角度 * @return 旋转后的图片 * @since 3.2.2 @@ -1057,13 +1205,19 @@ public class ImgUtil { * @since 3.2.2 */ public static void flip(final File imageFile, final 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 @@ -1075,7 +1229,7 @@ public class ImgUtil { /** * 水平翻转图像 * - * @param image 图像 + * @param image 图像,使用结束后需手动调用{@link #flush(Image)}释放资源 * @param out 输出 * @throws IORuntimeException IO异常 * @since 3.2.2 @@ -1087,7 +1241,7 @@ public class ImgUtil { /** * 水平翻转图像,写出格式为JPG * - * @param image 图像 + * @param image 图像,使用结束后需手动调用{@link #flush(Image)}释放资源 * @param out 输出 * @throws IORuntimeException IO异常 * @since 3.2.2 @@ -1099,7 +1253,7 @@ public class ImgUtil { /** * 水平翻转图像 * - * @param image 图像 + * @param image 图像,使用结束后需手动调用{@link #flush(Image)}释放资源 * @return 翻转后的图片 * @since 3.2.2 */ @@ -1120,7 +1274,13 @@ public class ImgUtil { * @since 4.3.2 */ public static void compress(final File imageFile, final File outFile, final 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); + } } // endregion @@ -1230,6 +1390,8 @@ public class ImgUtil { } // endregion + // region ----- copyImage + /** * 将已有Image复制新的一份出来 * @@ -1285,13 +1447,21 @@ public class ImgUtil { img.getWidth(null), img.getHeight(null), imageType); + final Graphics2D bGr = GraphicsUtil.createGraphics(bImage, backgroundColor); - bGr.drawImage(img, 0, 0, null); - bGr.dispose(); + try { + GraphicsUtil.drawImg(bGr, img, new Point()); + } finally { + bGr.dispose(); + } return bImage; } + // endregion + + // region ----- toXXX + /** * 将Base64编码的图像信息转为 {@link BufferedImage} * @@ -1366,6 +1536,8 @@ public class ImgUtil { return out.toByteArrayZeroCopyIfPossible(); } + // endregion + // region ----- createImage /** @@ -1373,7 +1545,7 @@ public class ImgUtil { * * @param width 宽度 * @param height 高度 - * @param transparency 透明模式,见 {@link java.awt.Transparency} + * @param transparency 透明模式,见 {@link Transparency} * @return {@link BufferedImage} * @since 5.7.13 */ @@ -1394,7 +1566,13 @@ public class ImgUtil { * @throws IORuntimeException IO异常 */ public static void createTransparentImage(final String str, final Font font, final Color fontColor, final ImageOutputStream out) throws IORuntimeException { - writePng(createImage(str, font, null, fontColor, BufferedImage.TYPE_INT_ARGB), out); + BufferedImage image = null; + try { + image = createImage(str, font, null, fontColor, BufferedImage.TYPE_INT_ARGB); + writePng(image, out); + } finally { + flush(image); + } } /** @@ -1408,7 +1586,13 @@ public class ImgUtil { * @throws IORuntimeException IO异常 */ public static void createImage(final String str, final Font font, final Color backgroundColor, final Color fontColor, final ImageOutputStream out) throws IORuntimeException { - writePng(createImage(str, font, backgroundColor, fontColor, BufferedImage.TYPE_INT_ARGB), out); + BufferedImage image = null; + try { + image = createImage(str, font, backgroundColor, fontColor, BufferedImage.TYPE_INT_ARGB); + writePng(image, out); + } finally { + flush(image); + } } /** @@ -1424,7 +1608,7 @@ public class ImgUtil { */ public static BufferedImage createImage(final String str, final Font font, final Color backgroundColor, final Color fontColor, final int imageType) throws IORuntimeException { // 获取font的样式应用在str上的整个矩形 - final Rectangle2D r = getRectangle(str, font); + final Rectangle2D r = FontUtil.getRectangle(str, font); // 获取单个字符的高度 final int unitHeight = (int) Math.floor(r.getHeight()); // 获取整个str用了font样式的宽度这里用四舍五入后+1保证宽度绝对能容纳这个字符串作为图片的宽度 @@ -1442,49 +1626,34 @@ public class ImgUtil { } // endregion - /** - * 获取font的样式应用在str上的整个矩形 - * - * @param str 字符串,必须非空 - * @param font 字体,必须非空 - * @return {@link Rectangle2D} - * @since 5.3.3 - */ - public static Rectangle2D getRectangle(final String str, final Font font) { - return font.getStringBounds(str, - new FontRenderContext(AffineTransform.getScaleInstance(1, 1), - false, - false)); - } - // region ----- write /** * 写出图像为JPG格式 * - * @param image {@link Image} - * @param destImageStream 写出到的目标流 + * @param image {@link Image} + * @param targetImageStream 写出到的目标流 * @throws IORuntimeException IO异常 */ - public static void writeJpg(final Image image, final ImageOutputStream destImageStream) throws IORuntimeException { - write(image, IMAGE_TYPE_JPG, destImageStream); + public static void writeJpg(final Image image, final ImageOutputStream targetImageStream) throws IORuntimeException { + write(image, IMAGE_TYPE_JPG, targetImageStream); } /** * 写出图像为PNG格式 * - * @param image {@link Image} - * @param destImageStream 写出到的目标流 + * @param image {@link Image},使用结束后需手动调用{@link #flush(Image)}释放资源 + * @param targetImageStream 写出到的目标流 * @throws IORuntimeException IO异常 */ - public static void writePng(final Image image, final ImageOutputStream destImageStream) throws IORuntimeException { - write(image, IMAGE_TYPE_PNG, destImageStream); + public static void writePng(final Image image, final ImageOutputStream targetImageStream) throws IORuntimeException { + write(image, IMAGE_TYPE_PNG, targetImageStream); } /** * 写出图像为JPG格式 * - * @param image {@link Image} + * @param image {@link Image},使用结束后需手动调用{@link #flush(Image)}释放资源 * @param out 写出到的目标流 * @throws IORuntimeException IO异常 * @since 4.0.10 @@ -1496,7 +1665,7 @@ public class ImgUtil { /** * 写出图像为PNG格式 * - * @param image {@link Image} + * @param image {@link Image},使用结束后需手动调用{@link #flush(Image)}释放资源 * @param out 写出到的目标流 * @throws IORuntimeException IO异常 * @since 4.0.10 @@ -1509,20 +1678,26 @@ public class ImgUtil { * 按照目标格式写出图像:GIF=》JPG、GIF=》PNG、PNG=》JPG、PNG=》GIF(X)、BMP=》PNG
* 此方法并不关闭流 * - * @param srcStream 源图像流 - * @param formatName 包含格式非正式名称的 String:如JPG、JPEG、GIF等 - * @param destStream 目标图像输出流 + * @param srcStream 源图像流 + * @param formatName 包含格式非正式名称的 String:如JPG、JPEG、GIF等 + * @param targetStream 目标图像输出流 * @since 5.0.0 */ - public static void write(final ImageInputStream srcStream, final String formatName, final ImageOutputStream destStream) { - write(read(srcStream), formatName, destStream); + public static void write(final ImageInputStream srcStream, final String formatName, final ImageOutputStream targetStream) { + BufferedImage image = null; + try { + image = read(srcStream); + write(image, formatName, targetStream); + } finally { + flush(image); + } } /** * 写出图像:GIF=》JPG、GIF=》PNG、PNG=》JPG、PNG=》GIF(X)、BMP=》PNG
* 此方法并不关闭流 * - * @param image {@link Image} + * @param image {@link Image},使用结束后需手动调用{@link #flush(Image)}释放资源 * @param imageType 图片类型(图片扩展名) * @param out 写出到的目标流 * @throws IORuntimeException IO异常 @@ -1535,22 +1710,21 @@ public class ImgUtil { /** * 写出图像为目标文件扩展名对应的格式 * - * @param image {@link Image} + * @param image {@link Image},使用结束后需手动调用{@link #flush(Image)}释放资源 * @param targetFile 目标文件 * @throws IORuntimeException IO异常 * @since 3.1.0 */ public static void write(final Image image, final File targetFile) throws IORuntimeException { - final String imageType = FileNameUtil.extName(targetFile); - ImgWriter.of(image, imageType).write(targetFile); + ImgWriter.of(image, FileNameUtil.extName(targetFile)).write(targetFile); } /** * 写出图像为指定格式:GIF=》JPG、GIF=》PNG、PNG=》JPG、PNG=》GIF(X)、BMP=》PNG
* 此方法并不关闭流 * - * @param image {@link Image} - * @param imageType 图片类型(图片扩展名) + * @param image {@link Image},使用结束后需手动调用{@link #flush(Image)}释放资源 + * @param imageType 图片类型(图片扩展名) * @param targetImageStream 写出到的目标流 * @throws IORuntimeException IO异常 * @since 3.1.2 @@ -1562,7 +1736,7 @@ public class ImgUtil { /** * 写出图像为指定格式 * - * @param image {@link Image} + * @param image {@link Image},使用结束后需手动调用{@link #flush(Image)}释放资源 * @param imageType 图片类型(图片扩展名),{@code null}表示使用RGB模式(JPG) * @param out 写出到的目标流 * @param quality 质量,数字为0~1(不包括0和1)表示质量压缩比,除此数字外设置表示不压缩 @@ -1579,7 +1753,7 @@ public class ImgUtil { /** * 通过{@link ImageWriter}写出图片到输出流 * - * @param image 图片 + * @param image 图片,使用结束后需手动调用{@link #flush(Image)}释放资源 * @param imageType 图片类型 * @param output 输出的Image流{@link ImageOutputStream} * @param quality 质量,数字为0~1(不包括0和1)表示质量压缩比,除此数字外设置表示不压缩 @@ -1594,7 +1768,7 @@ public class ImgUtil { /** * 根据给定的Image对象和格式获取对应的{@link ImageWriter},如果未找到合适的Writer,返回null * - * @param img {@link Image} + * @param img {@link Image},使用结束后需手动调用{@link #flush(Image)}释放资源 * @param formatName 图片格式,例如"jpg"、"png",{@code null}则使用默认值"jpg" * @return {@link ImageWriter} * @since 4.3.2 @@ -1909,10 +2083,9 @@ public class ImgUtil { * @param inputPath 要处理图片的路径 * @param outputPath 输出图片的路径 * @param tolerance 容差值[根据图片的主题色,加入容差值,值的范围在0~255之间] - * @return 返回处理结果 true:图片处理完成 false:图片处理失败 */ - public static boolean backgroundRemoval(final String inputPath, final String outputPath, final int tolerance) { - return BackgroundRemoval.backgroundRemoval(inputPath, outputPath, tolerance); + public static void backgroundRemoval(final String inputPath, final String outputPath, final int tolerance) { + BackgroundRemoval.backgroundRemoval(inputPath, outputPath, tolerance); } /** @@ -1927,10 +2100,9 @@ public class ImgUtil { * @param input 需要进行操作的图片 * @param output 最后输出的文件 * @param tolerance 容差值[根据图片的主题色,加入容差值,值的取值范围在0~255之间] - * @return 返回处理结果 true:图片处理完成 false:图片处理失败 */ - public static boolean backgroundRemoval(final File input, final File output, final int tolerance) { - return BackgroundRemoval.backgroundRemoval(input, output, tolerance); + public static void backgroundRemoval(final File input, final File output, final int tolerance) { + BackgroundRemoval.backgroundRemoval(input, output, tolerance); } /** @@ -1946,10 +2118,9 @@ public class ImgUtil { * @param output 最后输出的文件 * @param override 指定替换成的背景颜色 为null时背景为透明 * @param tolerance 容差值[根据图片的主题色,加入容差值,值的取值范围在0~255之间] - * @return 返回处理结果 true:图片处理完成 false:图片处理失败 */ - public static boolean backgroundRemoval(final File input, final File output, final Color override, final int tolerance) { - return BackgroundRemoval.backgroundRemoval(input, output, override, tolerance); + public static void backgroundRemoval(final File input, final File output, final Color override, final int tolerance) { + BackgroundRemoval.backgroundRemoval(input, output, override, tolerance); } /** diff --git a/hutool-swing/src/main/java/org/dromara/hutool/swing/img/ImgWriter.java b/hutool-swing/src/main/java/org/dromara/hutool/swing/img/ImgWriter.java index c613d22ac..3066a60af 100644 --- a/hutool-swing/src/main/java/org/dromara/hutool/swing/img/ImgWriter.java +++ b/hutool-swing/src/main/java/org/dromara/hutool/swing/img/ImgWriter.java @@ -24,16 +24,18 @@ import javax.imageio.ImageWriter; import javax.imageio.stream.ImageOutputStream; import java.awt.Color; import java.awt.Image; +import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.RenderedImage; import java.io.File; +import java.io.Flushable; import java.io.IOException; import java.io.OutputStream; /** * 图片写出封装 */ -public class ImgWriter { +public class ImgWriter implements Flushable { /** * 创建图片写出器 @@ -138,6 +140,16 @@ public class ImgWriter { } } + @Override + public void flush() { + final RenderedImage renderedImage = this.image; + if(renderedImage instanceof BufferedImage){ + ImgUtil.flush((BufferedImage) renderedImage); + } else if(renderedImage instanceof Image){ + ImgUtil.flush((Image) renderedImage); + } + } + /** * 构建图片写出参数 * diff --git a/hutool-swing/src/test/java/org/dromara/hutool/swing/img/ImgTest.java b/hutool-swing/src/test/java/org/dromara/hutool/swing/img/ImgTest.java index 9dfd060c4..0d1901610 100644 --- a/hutool-swing/src/test/java/org/dromara/hutool/swing/img/ImgTest.java +++ b/hutool-swing/src/test/java/org/dromara/hutool/swing/img/ImgTest.java @@ -107,6 +107,7 @@ public class ImgTest { final Image img = ImgUtil.getImage(UrlUtil.getURL(file)); ImgUtil.scale(img, fileScale, 0.8f); + ImgUtil.flush(img); } @Test