diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/GraphicsUtil.java b/hutool-swing/src/main/java/cn/hutool/swing/img/GraphicsUtil.java
index 9ba1a6c45..e090b058d 100755
--- a/hutool-swing/src/main/java/cn/hutool/swing/img/GraphicsUtil.java
+++ b/hutool-swing/src/main/java/cn/hutool/swing/img/GraphicsUtil.java
@@ -3,17 +3,7 @@ package cn.hutool.swing.img;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.swing.img.color.ColorUtil;
-import java.awt.AlphaComposite;
-import java.awt.Color;
-import java.awt.Dimension;
-import java.awt.Font;
-import java.awt.FontMetrics;
-import java.awt.Graphics;
-import java.awt.Graphics2D;
-import java.awt.Image;
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.awt.RenderingHints;
+import java.awt.*;
import java.awt.image.BufferedImage;
/**
@@ -34,7 +24,6 @@ public class GraphicsUtil {
*/
public static Graphics2D createGraphics(final BufferedImage image, final Color color) {
final Graphics2D g = image.createGraphics();
-
if (null != color) {
// 填充背景
g.setColor(color);
@@ -99,9 +88,7 @@ public class GraphicsUtil {
*/
public static Graphics drawString(final Graphics g, final String str, final Font font, final Color color, final int width, final int height) {
// 抗锯齿
- if (g instanceof Graphics2D) {
- ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
- }
+ enableAntialias(g);
// 创建字体
g.setFont(font);
@@ -168,9 +155,7 @@ public class GraphicsUtil {
*/
public static Graphics drawString(final Graphics g, final String str, final Font font, final Color color, final Point point) {
// 抗锯齿
- if (g instanceof Graphics2D) {
- ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
- }
+ enableAntialias(g);
g.setFont(font);
g.setColor(ObjUtil.defaultIfNull(color, Color.BLACK));
@@ -182,8 +167,8 @@ public class GraphicsUtil {
/**
* 绘制图片
*
- * @param g 画笔
- * @param img 要绘制的图片
+ * @param g 画笔
+ * @param img 要绘制的图片
* @param point 绘制的位置,基于左上角
* @return 画笔对象
*/
@@ -208,12 +193,27 @@ public class GraphicsUtil {
/**
* 设置画笔透明度
*
- * @param g 画笔
+ * @param g 画笔
* @param alpha 透明度:alpha 必须是范围 [0.0, 1.0] 之内(包含边界值)的一个浮点数字
* @return 画笔
*/
- public static Graphics2D setAlpha(final Graphics2D g, final float alpha){
+ public static Graphics2D setAlpha(final Graphics2D g, final float alpha) {
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
return g;
}
+
+ /**
+ * 打开抗锯齿和文本抗锯齿
+ *
+ * @param g {@link Graphics}
+ */
+ private static void enableAntialias(final Graphics g) {
+ if (g instanceof Graphics2D) {
+ ((Graphics2D) g).setRenderingHints(
+ RenderingHintsBuilder.of()
+ .setAntialiasing(RenderingHintsBuilder.Antialias.ON)
+ .setTextAntialias(RenderingHintsBuilder.TextAntialias.ON).build()
+ );
+ }
+ }
}
diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/Img.java b/hutool-swing/src/main/java/cn/hutool/swing/img/Img.java
index d1570a778..68ba7f834 100755
--- a/hutool-swing/src/main/java/cn/hutool/swing/img/Img.java
+++ b/hutool-swing/src/main/java/cn/hutool/swing/img/Img.java
@@ -706,11 +706,10 @@ public class Img implements Serializable {
* 结果类型设定见{@link #setTargetImageType(String)}
*
* @param out 写出到的目标流
- * @return 是否成功写出,如果返回false表示未找到合适的Writer
* @throws IORuntimeException IO异常
*/
- public boolean write(final OutputStream out) throws IORuntimeException {
- return write(ImgUtil.getImageOutputStream(out));
+ public void write(final OutputStream out) throws IORuntimeException {
+ write(ImgUtil.getImageOutputStream(out));
}
/**
@@ -718,27 +717,25 @@ public class Img implements Serializable {
* 结果类型设定见{@link #setTargetImageType(String)}
*
* @param targetImageStream 写出到的目标流
- * @return 是否成功写出,如果返回false表示未找到合适的Writer
* @throws IORuntimeException IO异常
*/
- public boolean write(final ImageOutputStream targetImageStream) throws IORuntimeException {
+ public void write(final ImageOutputStream targetImageStream) throws IORuntimeException {
Assert.notBlank(this.targetImageType, "Target image type is blank !");
Assert.notNull(targetImageStream, "Target output stream is null !");
final Image targetImage = (null == this.targetImage) ? this.srcImage : this.targetImage;
Assert.notNull(targetImage, "Target image is null !");
- return ImgUtil.write(targetImage, this.targetImageType, targetImageStream, this.quality, this.backgroundColor);
+ ImgUtil.write(targetImage, this.targetImageType, targetImageStream, this.quality, this.backgroundColor);
}
/**
* 写出图像为目标文件扩展名对应的格式
*
* @param targetFile 目标文件
- * @return 是否成功写出,如果返回false表示未找到合适的Writer
* @throws IORuntimeException IO异常
*/
- public boolean write(final File targetFile) throws IORuntimeException {
+ public void write(final File targetFile) throws IORuntimeException {
final String formatName = FileNameUtil.extName(targetFile);
if (StrUtil.isNotBlank(formatName)) {
this.targetImageType = formatName;
@@ -752,7 +749,7 @@ public class Img implements Serializable {
ImageOutputStream out = null;
try {
out = ImgUtil.getImageOutputStream(targetFile);
- return write(out);
+ write(out);
} finally {
IoUtil.close(out);
}
diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java
index c85350f2f..b16760b21 100755
--- a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java
+++ b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgUtil.java
@@ -10,7 +10,6 @@ import cn.hutool.core.lang.Assert;
import cn.hutool.core.math.NumberUtil;
import cn.hutool.core.net.url.URLUtil;
import cn.hutool.core.text.StrUtil;
-import cn.hutool.core.util.ObjUtil;
import javax.imageio.*;
import javax.imageio.stream.ImageInputStream;
@@ -502,6 +501,7 @@ public class ImgUtil {
Assert.notNull(destImageFile);
Assert.isFalse(srcImageFile.equals(destImageFile), "Src file is equals to dest file!");
+ // 通过扩展名检查图片类型,相同类型直接复制
final String srcExtName = FileNameUtil.extName(srcImageFile);
final String destExtName = FileNameUtil.extName(destImageFile);
if (StrUtil.equalsIgnoreCase(srcExtName, destExtName)) {
@@ -1430,15 +1430,8 @@ public class ImgUtil {
// 创建图片
final BufferedImage image = new BufferedImage(width, height, imageType);
- final Graphics g = image.getGraphics();
- if (null != backgroundColor) {
- // 先用背景色填充整张图片,也就是背景
- g.setColor(backgroundColor);
- g.fillRect(0, 0, width, height);
- }
- g.setColor(ObjUtil.defaultIfNull(fontColor, Color.BLACK));
- g.setFont(font);// 设置画笔字体
- g.drawString(str, 0, font.getSize());// 画出字符串
+ final Graphics g = GraphicsUtil.createGraphics(image, backgroundColor);
+ GraphicsUtil.drawString(g, str, font, fontColor, new Point(0, font.getSize()));
g.dispose();
return image;
@@ -1535,6 +1528,19 @@ public class ImgUtil {
write(image, imageType, getImageOutputStream(out));
}
+ /**
+ * 写出图像为目标文件扩展名对应的格式
+ *
+ * @param image {@link 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);
+ }
+
/**
* 写出图像为指定格式:GIF=》JPG、GIF=》PNG、PNG=》JPG、PNG=》GIF(X)、BMP=》PNG
* 此方法并不关闭流
@@ -1542,12 +1548,11 @@ public class ImgUtil {
* @param image {@link Image}
* @param imageType 图片类型(图片扩展名)
* @param destImageStream 写出到的目标流
- * @return 是否成功写出,如果返回false表示未找到合适的Writer
* @throws IORuntimeException IO异常
* @since 3.1.2
*/
- public static boolean write(final Image image, final String imageType, final ImageOutputStream destImageStream) throws IORuntimeException {
- return write(image, imageType, destImageStream, 1);
+ public static void write(final Image image, final String imageType, final ImageOutputStream destImageStream) throws IORuntimeException {
+ write(image, imageType, destImageStream, 1);
}
/**
@@ -1557,110 +1562,57 @@ public class ImgUtil {
* @param imageType 图片类型(图片扩展名)
* @param targetImageStream 写出到的目标流
* @param quality 质量,数字为0~1(不包括0和1)表示质量压缩比,除此数字外设置表示不压缩
- * @return 是否成功写出,如果返回false表示未找到合适的Writer
* @throws IORuntimeException IO异常
* @since 4.3.2
*/
- public static boolean write(final Image image, final String imageType, final ImageOutputStream targetImageStream,
- final float quality) throws IORuntimeException {
- return write(image, imageType, targetImageStream, quality, null);
+ public static void write(final Image image, final String imageType, final ImageOutputStream targetImageStream,
+ final float quality) throws IORuntimeException {
+ write(image, imageType, targetImageStream, quality, null);
}
/**
* 写出图像为指定格式
*
* @param image {@link Image}
- * @param imageType 图片类型(图片扩展名)
+ * @param imageType 图片类型(图片扩展名),{@code null}表示使用RGB模式(JPG)
* @param destImageStream 写出到的目标流
* @param quality 质量,数字为0~1(不包括0和1)表示质量压缩比,除此数字外设置表示不压缩
* @param backgroundColor 背景色{@link Color}
- * @return 是否成功写出,如果返回false表示未找到合适的Writer
* @throws IORuntimeException IO异常
* @since 4.3.2
*/
- public static boolean write(final Image image, String imageType, final ImageOutputStream destImageStream,
- final float quality, final Color backgroundColor) throws IORuntimeException {
- if (StrUtil.isBlank(imageType)) {
- imageType = IMAGE_TYPE_JPG;
- }
-
+ public static void write(final Image image, final String imageType, final ImageOutputStream destImageStream,
+ final float quality, final Color backgroundColor) throws IORuntimeException {
final BufferedImage bufferedImage = toBufferedImage(image, imageType, backgroundColor);
- final ImageWriter writer = getWriter(bufferedImage, imageType);
- return write(bufferedImage, writer, destImageStream, quality);
- }
-
- /**
- * 写出图像为目标文件扩展名对应的格式
- *
- * @param image {@link Image}
- * @param targetFile 目标文件
- * @throws IORuntimeException IO异常
- * @since 3.1.0
- */
- public static void write(final Image image, final File targetFile) throws IORuntimeException {
- FileUtil.touch(targetFile);
- ImageOutputStream out = null;
- try {
- out = getImageOutputStream(targetFile);
- write(image, FileNameUtil.extName(targetFile), out);
- } finally {
- IoUtil.close(out);
- }
+ write(bufferedImage, destImageStream, quality);
}
/**
* 通过{@link ImageWriter}写出图片到输出流
*
* @param image 图片
- * @param writer {@link ImageWriter}
* @param output 输出的Image流{@link ImageOutputStream}
* @param quality 质量,数字为0~1(不包括0和1)表示质量压缩比,除此数字外设置表示不压缩
- * @return 是否成功写出
* @since 4.3.2
*/
- public static boolean write(final Image image, final ImageWriter writer, final ImageOutputStream output, final float quality) {
- if (writer == null) {
- return false;
- }
-
- writer.setOutput(output);
- final RenderedImage renderedImage = toRenderedImage(image);
- // 设置质量
- ImageWriteParam imgWriteParams = null;
- if (quality > 0 && quality < 1) {
- imgWriteParams = writer.getDefaultWriteParam();
- if (imgWriteParams.canWriteCompressed()) {
- imgWriteParams.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
- imgWriteParams.setCompressionQuality(quality);
- final ColorModel colorModel = renderedImage.getColorModel();// ColorModel.getRGBdefault();
- imgWriteParams.setDestinationType(new ImageTypeSpecifier(colorModel, colorModel.createCompatibleSampleModel(16, 16)));
- }
- }
-
- try {
- if (null != imgWriteParams) {
- writer.write(null, new IIOImage(renderedImage, null, null), imgWriteParams);
- } else {
- writer.write(renderedImage);
- }
- output.flush();
- } catch (final IOException e) {
- throw new IORuntimeException(e);
- } finally {
- writer.dispose();
- }
- return true;
+ public static void write(final Image image, final ImageOutputStream output, final float quality) {
+ ImgWriter.of(image, null)
+ .setQuality(quality)
+ .write(output);
}
/**
* 根据给定的Image对象和格式获取对应的{@link ImageWriter},如果未找到合适的Writer,返回null
*
* @param img {@link Image}
- * @param formatName 图片格式,例如"jpg"、"png"
+ * @param formatName 图片格式,例如"jpg"、"png",{@code null}则使用默认值"jpg"
* @return {@link ImageWriter}
* @since 4.3.2
*/
- public static ImageWriter getWriter(final Image img, final String formatName) {
+ public static ImageWriter getWriter(final Image img, String formatName) {
+ if (null == formatName) {
+ formatName = IMAGE_TYPE_JPG;
+ }
final ImageTypeSpecifier type = ImageTypeSpecifier.createFromRenderedImage(toBufferedImage(img, formatName));
final Iterator iter = ImageIO.getImageWriters(type, formatName);
return iter.hasNext() ? iter.next() : null;
@@ -1669,11 +1621,15 @@ public class ImgUtil {
/**
* 根据给定的图片格式或者扩展名获取{@link ImageWriter},如果未找到合适的Writer,返回null
*
- * @param formatName 图片格式或扩展名,例如"jpg"、"png"
+ * @param formatName 图片格式或扩展名,例如"jpg"、"png",{@code null}则使用默认值"jpg"
* @return {@link ImageWriter}
* @since 4.3.2
*/
- public static ImageWriter getWriter(final String formatName) {
+ public static ImageWriter getWriter(String formatName) {
+ if (null == formatName) {
+ formatName = IMAGE_TYPE_JPG;
+ }
+
ImageWriter writer = null;
Iterator iter = ImageIO.getImageWritersByFormatName(formatName);
if (iter.hasNext()) {
diff --git a/hutool-swing/src/main/java/cn/hutool/swing/img/ImgWriter.java b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgWriter.java
new file mode 100644
index 000000000..0f07d572d
--- /dev/null
+++ b/hutool-swing/src/main/java/cn/hutool/swing/img/ImgWriter.java
@@ -0,0 +1,151 @@
+package cn.hutool.swing.img;
+
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.io.IORuntimeException;
+import cn.hutool.core.io.IoUtil;
+import cn.hutool.core.lang.Assert;
+
+import javax.imageio.IIOImage;
+import javax.imageio.ImageTypeSpecifier;
+import javax.imageio.ImageWriteParam;
+import javax.imageio.ImageWriter;
+import javax.imageio.stream.ImageOutputStream;
+import java.awt.Color;
+import java.awt.Image;
+import java.awt.image.ColorModel;
+import java.awt.image.RenderedImage;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * 图片写出封装
+ */
+public class ImgWriter {
+
+ /**
+ * 创建图片写出器
+ *
+ * @param image 图片
+ * @param imageType 图片类型(图片扩展名),{@code null}表示使用RGB模式(JPG)
+ * @param backgroundColor 背景色{@link Color},{@code null}表示黑色或透明
+ * @return {@code ImgWriter}
+ */
+ public static ImgWriter of(final Image image, final String imageType, final Color backgroundColor) {
+ return of(ImgUtil.toBufferedImage(image, imageType, backgroundColor), imageType);
+ }
+
+ /**
+ * 创建图片写出器
+ *
+ * @param image 图片
+ * @param imageType 图片类型(图片扩展名),{@code null}表示使用RGB模式(JPG)
+ * @return {@code ImgWriter}
+ */
+ public static ImgWriter of(final Image image, final String imageType) {
+ return new ImgWriter(image, imageType);
+ }
+
+ private final RenderedImage image;
+ private final ImageWriter writer;
+ private ImageWriteParam writeParam;
+
+ /**
+ * 构造
+ *
+ * @param image {@link Image}
+ * @param imageType 图片类型(图片扩展名),{@code null}表示使用RGB模式(JPG)
+ */
+ public ImgWriter(final Image image, final String imageType) {
+ this.image = ImgUtil.toRenderedImage(image);
+ this.writer = ImgUtil.getWriter(image, imageType);
+ }
+
+ /**
+ * 设置写出质量,数字为0~1(不包括0和1)表示质量压缩比,除此数字外设置表示不压缩
+ *
+ * @param quality 写出质量,数字为0~1(不包括0和1)表示质量压缩比,除此数字外设置表示不压缩
+ * @return this
+ */
+ public ImgWriter setQuality(final float quality) {
+ this.writeParam = buildParam(this.image, this.writer, quality);
+ return this;
+ }
+
+ /**
+ * 写出图像:GIF=》JPG、GIF=》PNG、PNG=》JPG、PNG=》GIF(X)、BMP=》PNG
+ * 此方法并不关闭流
+ *
+ * @param out 写出到的目标流
+ * @throws IORuntimeException IO异常
+ */
+ public void write(final OutputStream out) throws IORuntimeException {
+ write(ImgUtil.getImageOutputStream(out));
+ }
+
+ /**
+ * 写出图像为目标文件扩展名对应的格式
+ *
+ * @param targetFile 目标文件
+ * @throws IORuntimeException IO异常
+ */
+ public void write(final File targetFile) throws IORuntimeException {
+ FileUtil.touch(targetFile);
+ ImageOutputStream out = null;
+ try {
+ out = ImgUtil.getImageOutputStream(targetFile);
+ write(out);
+ } finally {
+ IoUtil.close(out);
+ }
+ }
+
+ /**
+ * 通过{@link ImageWriter}写出图片到输出流
+ *
+ * @param output 输出的Image流{@link ImageOutputStream}, 非空
+ */
+ public void write(final ImageOutputStream output) {
+ Assert.notNull(output);
+
+ final ImageWriter writer = this.writer;
+ final RenderedImage image = this.image;
+ writer.setOutput(output);
+ // 设置质量
+ try {
+ if (null != this.writeParam) {
+ writer.write(null, new IIOImage(image, null, null), this.writeParam);
+ } else {
+ writer.write(image);
+ }
+ output.flush();
+ } catch (final IOException e) {
+ throw new IORuntimeException(e);
+ } finally {
+ writer.dispose();
+ }
+ }
+
+ /**
+ * 构建图片写出参数
+ *
+ * @param renderedImage 图片
+ * @param writer {@link ImageWriter}
+ * @param quality 质量,范围0~1
+ * @return {@link ImageWriteParam} or {@code null}
+ */
+ private static ImageWriteParam buildParam(final RenderedImage renderedImage, final ImageWriter writer, final float quality) {
+ // 设置质量
+ ImageWriteParam imgWriteParams = null;
+ if (quality > 0 && quality < 1) {
+ imgWriteParams = writer.getDefaultWriteParam();
+ if (imgWriteParams.canWriteCompressed()) {
+ imgWriteParams.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
+ imgWriteParams.setCompressionQuality(quality);
+ final ColorModel colorModel = renderedImage.getColorModel();// ColorModel.getRGBdefault();
+ imgWriteParams.setDestinationType(new ImageTypeSpecifier(colorModel, colorModel.createCompatibleSampleModel(16, 16)));
+ }
+ }
+ return imgWriteParams;
+ }
+}