/** * @Description TestImageUtil.java * @author 张军 * @date 2017年6月16日 下午6:10:01 * @version V1.0 */ package zj.image; import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.Image; import java.awt.RenderingHints; import java.awt.geom.AffineTransform; import java.awt.geom.RoundRectangle2D; import java.awt.image.AffineTransformOp; import java.awt.image.BufferedImage; import java.awt.image.ConvolveOp; import java.awt.image.Kernel; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.URL; import java.util.Collection; import javax.imageio.ImageIO; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; import org.apache.log4j.Logger; import zj.check.util.CheckUtil; import zj.common.exception.ServiceException; import zj.io.util.FileUtil; import zj.java.util.JavaUtil; import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGImageEncoder; /** * 纯JAVA实现的图片处理工具类 * @see 1、多个图片合成 * @see 2、裁剪图片 * @see 3、图片压缩 * @see 4、制作圆角 * @see 5、重调图片尺寸 * @see 6、获取图片尺寸 * @see 7、图片缩放 * @see 8、导入网络图片到缓冲区 * @version 1.00 (2014.09.15) * @author SHNKCS 张军 {@link <a target=_blank href="http://www.zhangjunbk.com">张军个人网站</a> <a target=_blank href="http://user.qzone.qq.com/360901061/">张军QQ空间</a>} */ public class ImageUtil { /** * Logger for this class */ private static final Logger logger = Logger.getLogger(ImageUtil.class); /** * 导入网络图片到缓冲区 * * @param imgUrl * 网络路径 * @author 张军 * @date 2015-11-03 21:59:00 * @modifiyNote * @version 1.0 * @return 图片缓冲区 */ public static BufferedImage loadImageUrl(String imgUrl) { try { // 获取网络地址 URL url = new URL(imgUrl); // 返回网络图片缓冲区 return ImageIO.read(url); } catch (Exception e) { logger.error("导入网络图片到缓冲区", e); } return null; } /** * 图片缩放 * * @see #resize(String, String, int, int) * @param src * 源文件路径 * @param dest * 目标文件路径 * @param width * 宽度 * @param height * 高度 */ @Deprecated public static void zoomImage(String src, String dest, int width, int height) { try { double wr = 0, hr = 0; File srcFile = new File(src); File destFile = new File(dest); File targetDir = destFile.getParentFile(); if (targetDir != null && !targetDir.exists()) { // 创建目标文件目录 targetDir.mkdirs(); } BufferedImage bufImg = ImageIO.read(srcFile); Image Itemp = bufImg.getScaledInstance(width, height, BufferedImage.SCALE_SMOOTH); wr = width * 1.0 / bufImg.getWidth(); hr = height * 1.0 / bufImg.getHeight(); AffineTransformOp ato = new AffineTransformOp(AffineTransform.getScaleInstance(wr, hr), null); Itemp = ato.filter(bufImg, null); ImageIO.write((BufferedImage) Itemp, dest.substring(dest.lastIndexOf(".") + 1), destFile); } catch (Exception e) { throw new ServiceException(e); } } /** * 压缩图片 * * @see #resize(String, String, int, int) * @param src * 源文件路径 * @param dest * 目标文件路径 * @param width * 宽度 * @param height * 高度 * @author 张军 * @date 2015-11-03 21:59:00 * @modifiyNote * @version 1.0 */ @Deprecated public static void imageScale(String src, String dest, int width, int height) { BufferedOutputStream output = null; try { File srcFile = new File(src); File destFile = new File(dest); File targetDir = destFile.getParentFile(); if (targetDir != null && !targetDir.exists()) { // 创建目标文件目录 targetDir.mkdirs(); } Image image = javax.imageio.ImageIO.read(srcFile); image = image.getScaledInstance(width, height, Image.SCALE_AREA_AVERAGING); // Make a BufferedImage from the Image. BufferedImage mBufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D g2 = mBufferedImage.createGraphics(); g2.drawImage(image, 0, 0, width, height, Color.WHITE, null); g2.dispose(); float[] kernelData2 = { -0.125f, -0.125f, -0.125f, -0.125f, 2, -0.125f, -0.125f, -0.125f, -0.125f }; Kernel kernel = new Kernel(3, 3, kernelData2); ConvolveOp cOp = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null); mBufferedImage = cOp.filter(mBufferedImage, null); output = new BufferedOutputStream(new FileOutputStream(destFile)); JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(output); encoder.encode(mBufferedImage); } catch (Exception e) { throw new ServiceException(e); } finally { IOUtils.closeQuietly(output); } } /** * 获取图片尺寸(宽,高) * * @param filePath * 文件路径 * @author 张军 * @date 2015-11-03 21:59:00 * @modifiyNote * @version 1.0 * @return [width,height] */ public static int[] getSizeInfo(String filePath) { try { // 获取图片文件 File file = new File(filePath); // 获取缓冲区 Image image = ImageIO.read(file); // 返回宽度 int width = image.getWidth(null); // 返回高度 int height = image.getHeight(null); return new int[] { width, height }; } catch (Exception e) { throw new ServiceException(e); } } /** * 重调图片尺寸 * * @param srcFile * 源文件 * @param destFile * 目标文件 * @param width * 新的宽度,小于1则忽略,按原图比例缩放 * @param height * 新的高度,小于1则忽略,按原图比例缩放 * @param maxWidth * 最大宽度,限制目标图片宽度,小于1则忽略此设置 * @param maxHeight * 最大高度,限制目标图片高度,小于1则忽略此设置 * @author 张军 * @date 2015-11-03 21:59:00 * @modifiyNote * @version 1.0 */ public static void resize(File srcFile, File destFile, int width, int height, int maxWidth, int maxHeight) { InputStream input = null; OutputStream output = null; try { FileUtil.fileMkdir(destFile); // 获取文件输入流 input = new BufferedInputStream(new FileInputStream(srcFile)); // 获取文件输出流 output = new BufferedOutputStream(new FileOutputStream(destFile)); if (width < 1 && height < 1 && maxWidth < 1 && maxHeight < 1) { // 如果全部小于1尺寸 IOUtils.copy(input, output); } // 获取源图片缓冲区 BufferedImage img = ImageIO.read(input); // 源图片宽度 double tempWidth = img.getWidth(null); // 源图片高度 double tempHeight = img.getHeight(null); // 目标图片宽度 int toWidth = -1; // 目标图片高度 int toHeight = -1; // 源图片宽高比例 double rate = tempWidth / tempHeight; if (width > 0 && height > 0) { // 如果输出的宽高大于0,比例设置为宽高比 rate = ((double) width) / ((double) height); // 设置目标图片宽高为输出的宽高 toWidth = width; toHeight = height; } else if (width > 0) { // 如果输出的宽大于0 // 设置目标图片宽为输出的宽 toWidth = width; // 设置目标图片高为输出的宽比上源图片宽高比 toHeight = (int) (toWidth / rate); } else if (height > 0) { // 如果输出的高大于0 // 设置目标图片高为输出的高 toHeight = height; // 设置目标图片宽为输出的高比上源图片宽高比 toWidth = (int) (toHeight * rate); } else { // 否则设置源图片宽 toWidth = ((Number) tempWidth).intValue(); // 否则设置源图片高 toHeight = ((Number) tempHeight).intValue(); } if (maxWidth > 0 && toWidth > maxWidth) { // 如果最大宽高大于 0并且输出的宽大于最大宽度 // 设置输出的宽为最大宽度 toWidth = maxWidth; // 设置输出的高为输出的宽比上源图片宽高比 toHeight = (int) (toWidth / rate); } if (maxHeight > 0 && toHeight > maxHeight) { // 如果最大高高大于 0并且输出的高大于最大高度 // 设置输出的高为最大高度 toHeight = maxHeight; // 设置输出的宽为输出的高比上源图片宽高比 toWidth = (int) (toHeight * rate); } // 判断透明色 boolean hasNotAlpha = img.getColorModel().hasAlpha(); // 获取透明色 int typeInt = hasNotAlpha ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB; // 创建一个带透明色的BufferedImage对象:BufferedImage.TYPE_INT_ARGB // 创建一个不带透明色的BufferedImage对象:BufferedImage.TYPE_INT_RGB // 源图片缓冲区 BufferedImage tag = new BufferedImage(toWidth, toHeight, typeInt); // Image.SCALE_SMOOTH 的缩略算法 生成缩略图片的平滑度的 优先级比速度高 生成的图片质量比较好 但速度慢 tag.getGraphics().drawImage(img.getScaledInstance(toWidth, toHeight, Image.SCALE_SMOOTH), 0, 0, null); // 获取源文件扩展名 String srcExtName = FilenameUtils.getExtension(srcFile.getName()); // 输出源图片缓冲区到输出的文件中 ImageIO.write(tag, srcExtName, output); } catch (Exception e) { throw new ServiceException(e); } finally { IOUtils.closeQuietly(input); IOUtils.closeQuietly(output); } } /** * 重调图片尺寸(此方法图片更清楚) * * @param src * 源文件路径 * @param dest * 目标文件路径 * @param width * 新的宽度,小于1则忽略,按原图比例缩放 * @param height * 新的高度,小于1则忽略,按原图比例缩放 * @param maxWidth * 新的最大宽度,限制目标图片宽度,按原图比例缩放 * @param maxHeight * 新的最大高度,限制目标图片高度,按原图比例缩放 * @author 张军 * @date 2015-11-03 21:59:00 * @modifiyNote * @version 1.0 */ public static void resize(String src, String dest, int width, int height, int maxWidth, int maxHeight) { resize(new File(src), new File(dest), width, height, maxWidth, maxHeight); } /** * 重调图片尺寸(此方法图片更清楚) * * @param srcFile * 源文件 * @param destFile * 目标文件 * @param width * 新的宽度,小于1则忽略,按原图比例缩放 * @param height * 新的高度,小于1则忽略,按原图比例缩放 * @author 张军 * @date 2015-11-03 21:59:00 * @modifiyNote * @version 1.0 */ public static void resize(File srcFile, File destFile, int width, int height) { resize(srcFile, destFile, width, height, -1, -1); } /** * 重调图片尺寸(此方法图片更清楚) * * @param src * 源文件路径 * @param dest * 目标文件路径 * @param width * 新的宽度,小于1则忽略,按原图比例缩放 * @param height * 新的高度,小于1则忽略,按原图比例缩放 * @author 张军 * @date 2015-11-03 21:59:00 * @modifiyNote * @version 1.0 */ public static void resize(String src, String dest, int width, int height) { resize(new File(src), new File(dest), width, height); } /** * 裁剪图片 * * @param srcFile * 源文件 * @param destFile * 目标文件 * @param x * x坐标 * @param y * y坐标 * @param width * 裁剪宽度 * @param height * 裁剪高度 * @author 张军 * @date 2015-11-03 21:59:00 * @modifiyNote * @version 1.0 */ public static void crop(File srcFile, File destFile, int x, int y, int width, int height) { OutputStream output = null; InputStream input = null; try { // 获取源图片输入流 input = new BufferedInputStream(new FileInputStream(srcFile)); // 获取目标图片输入流 output = new BufferedOutputStream(new FileOutputStream(destFile)); // 获取源图片缓冲区 BufferedImage srcImg = ImageIO.read(input); // 获取源图片宽度 int srcWidth = srcImg.getWidth(); // 获取源图片高度 int srcHeight = srcImg.getHeight(); // 计算临时x轴 int tempX = Math.min(srcWidth - 1, x); // 计算临时y轴 int tempY = Math.min(srcHeight - 1, y); // 输出的临时宽度 int tempWidth = width; if (tempX + width > srcWidth) { // 临时的x轴+输出的宽度大于源文件宽度 // 临时宽度设置源图片的宽度-临时x轴与1相比的最大值 tempWidth = Math.max(1, srcWidth - tempX); } // 输出的临时高度 int tempHeight = height; if (tempY + height > srcHeight) { // 临时的y轴+输出的高度大于源文件高度 // 临时高度设置源图片的高度-临时y轴与1相比的最大值 tempHeight = Math.max(1, srcHeight - tempY); } // 通过源图片的缓冲区获取目标文件缓冲区 BufferedImage dest = srcImg.getSubimage(tempX, tempY, tempWidth, tempHeight); // 判断透明色 boolean hasNotAlpha = srcImg.getColorModel().hasAlpha(); // 获取透明色 int typeInt = hasNotAlpha ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB; // 创建一个带透明色的BufferedImage对象:BufferedImage.TYPE_INT_ARGB // 创建一个不带透明色的BufferedImage对象:BufferedImage.TYPE_INT_RGB // 源图片缓冲区 BufferedImage tag = new BufferedImage(width, height, typeInt); // 开始裁剪 tag.getGraphics().drawImage(dest, 0, 0, null); // 获取源文件扩展名 String srcExtName = FilenameUtils.getExtension(srcFile.getName()); // 输出源图片缓冲区到输出的文件中 ImageIO.write(tag, srcExtName, output); } catch (Exception e) { throw new ServiceException(e); } finally { IOUtils.closeQuietly(input); IOUtils.closeQuietly(output); } } /** * 裁剪图片 * * @param src * 源文件路径 * @param dest * 目标文件路径 * @param x * x坐标 * @param y * y坐标 * @param width * 裁剪宽度 * @param height * 裁剪高度 * @author 张军 * @date 2015-11-03 21:59:00 * @modifiyNote * @version 1.0 */ public static void crop(String src, String dest, int x, int y, int width, int height) throws Exception { crop(new File(src), new File(dest), x, y, width, height); } /** * 制作圆角 * * @param srcFile * 源文件 * @param destFile * 目标文件 * @param cornerRadius * 角度 * @author 张军 * @date 2015-11-03 21:59:00 * @modifiyNote * @version 1.0 */ public static void makeRoundedCorner(File srcFile, File destFile, int cornerRadius) { InputStream input = null; OutputStream output = null; try { // 获取源图片输入流 input = new BufferedInputStream(new FileInputStream(srcFile)); // 获取目标图片输入流 output = new BufferedOutputStream(new FileOutputStream(destFile)); // 获取源图片缓冲区 BufferedImage srcImg = ImageIO.read(input); // 获取源图片宽度 int srcWidth = srcImg.getWidth(); // 获取源图片高度 int srcHeight = srcImg.getHeight(); cornerRadius = cornerRadius < 1 ? srcWidth / 4 : cornerRadius; // 创建一个带透明色的BufferedImage对象:BufferedImage.TYPE_INT_ARGB // 创建一个不带透明色的BufferedImage对象:BufferedImage.TYPE_INT_RGB // 源图片缓冲区 BufferedImage tag = new BufferedImage(srcWidth, srcHeight, BufferedImage.TYPE_INT_ARGB); // Graphics2D ,Graphics 类,提供了对几何形状、坐标转换、颜色管理和文本布局更为复杂的控制。 // 它是用于在 Java(tm) 平台上呈现二维形状、文本和图像的基础类。验证码生成可以用到此类。 // public abstract class Graphics2Dextends Graphics 此 Graphics2D 类扩展了 Graphics 类, // 提供了对几何形状、坐标转换、颜色管理和文本布局更为复杂的控制。 Graphics2D g2 = tag.createGraphics(); // This is what we want, but it only does hard-clipping, i.e. // aliasing // g2.setClip(new RoundRectangle2D ...) // so instead fake soft-clipping by first drawing the desired clip // shape // in fully opaque white with antialiasing enabled... // Java 2D允许分配透明(alpha)值,以便底层的图形可以显示出来。通常我们会创建一个java.awt.AlphaComposite对象,然后传入 setComposite()方法的实现。 g2.setComposite(AlphaComposite.Src); // 其他渲染hints适用在不同的环境下。如缩放图片时,为KEY_INTERPOLATION使用 VALUE_INTERPOLATION_BILINEAR。请查阅本类的Javadoc,详细了解各个选项所适用的环境。 g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // 设置颜色 g2.setColor(Color.WHITE); // 开始制作 // 前两个指定矩形的左上角的坐标 // 第3,4个指定矩形的宽度和高度 // 最后两个指定圆角弧形的宽度和高度 g2.fill(new RoundRectangle2D.Float(0, 0, srcWidth, srcHeight, cornerRadius, cornerRadius)); // ... then compositing the image on top, // using the white shape from above as alpha source // Java 2D允许分配透明(alpha)值,以便底层的图形可以显示出来。通常我们会创建一个java.awt.AlphaComposite对象,然后传入 setComposite()方法的实现。 g2.setComposite(AlphaComposite.SrcAtop); // 开始画图片 g2.drawImage(srcImg, 0, 0, null); // 释放资源 g2.dispose(); // 输出源图片缓冲区到输出的文件中(圆角只能是png) ImageIO.write(tag, "png", output); } catch (Exception e) { throw new ServiceException(e); } finally { IOUtils.closeQuietly(output); IOUtils.closeQuietly(input); } } /** * 制作圆角 * * @param srcFile * 源文件 * @param destFile * 目标文件 * @param cornerRadius * 角度 * @author 张军 * @date 2015-11-03 21:59:00 * @modifiyNote * @version 1.0 */ public static void makeRoundedCorner(String src, String dest, int cornerRadius) { makeRoundedCorner(new File(src), new File(dest), cornerRadius); } /** * 修改图片,返回修改后的图片缓冲区(只输出一行文本) * * @param srcFile * 源文件 * @param destFile * 目标文件 * @param font * 字体 * @param fontColor * 字体颜色 * @param fontSize * 字体大小 * @param x * x坐标 * @param y * y坐标 * @param onlyLine * 是否一行输出文本,默认false:多行输出 * @author 张军 * @date 2015-11-03 21:59:00 * @modifiyNote * @version 1.0 */ @SuppressWarnings("unchecked") public static void writeImageString(File srcFile, File destFile, Font font, Color fontColor, int fontSize, Object content, int x, int y, boolean onlyLine) { InputStream input = null; OutputStream output = null; try { // 获取源图片输入流 input = new BufferedInputStream(new FileInputStream(srcFile)); // 获取文件输出流 output = new BufferedOutputStream(new FileOutputStream(destFile)); // 获取源图片缓冲区 BufferedImage srcImg = ImageIO.read(input); // 获取源图片宽度 int srcWidth = srcImg.getWidth(); // 获取源图片高度 int srcHeight = srcImg.getHeight(); // Graphics2D ,Graphics 类,提供了对几何形状、坐标转换、颜色管理和文本布局更为复杂的控制。 // 它是用于在 Java(tm) 平台上呈现二维形状、文本和图像的基础类。验证码生成可以用到此类。 // public abstract class Graphics2Dextends Graphics 此 Graphics2D 类扩展了 Graphics 类, // 提供了对几何形状、坐标转换、颜色管理和文本布局更为复杂的控制。 Graphics2D g = srcImg.createGraphics(); // 设置背景为白色 g.setBackground(Color.WHITE); if (fontColor == null) { // 设置字体颜色为蓝色 fontColor = Color.BLUE; } // 设置字体颜色为蓝色 g.setColor(fontColor); // ont是JAVA中的字体类,PLAIN是Font类中的静态常量( static final ) , // 表示是:普通样式常量。其他可用样式为:BOLD :粗体样式常量 ,ITALIC: 斜体样式常量.如可以如下初始化对象: // Font textFont = new Font("宋体" , Font.BOLD , 23);该字体表示23磅粗体的宋体字。 if (font == null) { // 设置字体 font = new Font("微软雅黑", Font.PLAIN, fontSize); } // 设置字体 g.setFont(font); // 字体大小 // 计算临时x轴 int tempX = x; // 计算临时y轴 int tempY = y; // 验证输出位置的纵坐标和横坐标 if (x >= srcHeight || y >= srcWidth) { // 临时x轴为源图片高度-文字大小+2 tempX = srcHeight - fontSize + 2; // 临时y轴为源图片宽度 tempY = srcWidth; } if (content instanceof Collection) { Collection<String> contentColl = (Collection<String>) content; int contentLength = contentColl.size(); if (onlyLine) { boolean first = true; for (String scontent : contentColl) { if (first) { if (x < 0) { // 写到右下角 tempX = srcWidth - scontent.length() * contentLength - fontSize - 50; } if (y < 0) { // 写到右下角 tempY = srcHeight - fontSize - 10; } first = false; } g.drawString(scontent, tempX, tempY); tempX += scontent.length() * fontSize / 2 + 5;// 重新计算文本输出位置 } } else { boolean first = true; for (String scontent : contentColl) { if (first) { if (x < 0) { // 写到右下角 tempX = srcWidth - scontent.length() - fontSize - 50; } if (y < 0) { // 写到右下角 tempY = srcHeight - fontSize * contentLength - 10; } first = false; } g.drawString(scontent, tempX, tempY); tempY += fontSize + 2;// 重新计算文本输出位置 } } } else { String scontent = JavaUtil.objToStr(content); if (CheckUtil.isNotNull(scontent)) { if (x < 0) { // 写到右下角 tempX = srcWidth - scontent.length() - fontSize - 30; } if (y < 0) { // 写到右下角 tempY = srcHeight - fontSize - 10; } // 在图片上写文字 g.drawString(scontent, tempX, tempY); } } // 释放资源 g.dispose(); // 获取源文件扩展名 String srcExtName = FilenameUtils.getExtension(srcFile.getName()); // 输出源图片缓冲区到输出的文件中 ImageIO.write(srcImg, srcExtName, output); } catch (Exception e) { throw new ServiceException(e); } finally { IOUtils.closeQuietly(input); IOUtils.closeQuietly(output); } } /** * 修改图片,返回修改后的图片缓冲区(只输出一行文本) * * @param srcFile * 源文件 * @param destFile * 目标文件 * @param fontColor * 字体颜色 * @param fontSize * 字体大小 * @param x * x坐标 * @param y * y坐标 * @author 张军 * @date 2015-11-03 21:59:00 * @modifiyNote * @version 1.0 */ public static void writeImageString(File srcFile, File destFile, Color fontColor, int fontSize, Object content, int x, int y) { writeImageString(srcFile, destFile, null, fontColor, fontSize, content, x, y, false); } /** * 修改图片,返回修改后的图片缓冲区(只输出一行文本) * * @param src * 源文件路径 * @param dest * 目标文件路径 * @param fontColor * 字体颜色 * @param fontSize * 字体大小 * @param x * x坐标 * @param y * y坐标 * @author 张军 * @date 2015-11-03 21:59:00 * @modifiyNote * @version 1.0 */ public static void writeImageString(String src, String dest, Color fontColor, int fontSize, Object content, int x, int y) { writeImageString(new File(src), new File(dest), fontColor, fontSize, content, x, y); } /** * 修改图片,返回修改后的图片缓冲区(只输出一行文本) * * @param srcFile * 源文件 * @param destFile * 目标文件 * @param x * x坐标 * @param y * y坐标 * @author 张军 * @date 2015-11-03 21:59:00 * @modifiyNote * @version 1.0 */ public static void writeImageString(File srcFile, File destFile, Object content, int x, int y) { writeImageString(srcFile, destFile, null, 20, content, x, y); } /** * 修改图片,返回修改后的图片缓冲区(只输出一行文本) * * @param src * 源文件路径 * @param dest * 目标文件路径 * @param x * x坐标 * @param y * y坐标 * @author 张军 * @date 2015-11-03 21:59:00 * @modifiyNote * @version 1.0 */ public static void writeImageString(String src, String dest, Object content, int x, int y) { writeImageString(new File(src), new File(dest), content, x, y); } /** * 将两张图片合并后输出图片 * * @param fromFile * 合并来自文件 * @param toFile * 合并到文件 * @param destFile * 目标文件 * @param x * x坐标,默认合并到左上角,当x<0时,合并到右下角 * @param y * y坐标,默认合并到左上角,当y<0时,合并到右下角 * @author 张军 * @date 2015-11-03 21:59:00 * @modifiyNote * @version 1.0 */ public static void writeImageMerge(File fromFile, File toFile, File destFile, int x, int y) { InputStream frominput = null; InputStream toinput = null; OutputStream output = null; try { // 获取源图片输入流from frominput = new BufferedInputStream(new FileInputStream(fromFile)); // 获取源图片输入流to toinput = new BufferedInputStream(new FileInputStream(toFile)); // 获取文件输出流 output = new BufferedOutputStream(new FileOutputStream(destFile)); // 获取from图片缓冲区 BufferedImage fromImg = ImageIO.read(frominput); // 获取to图片缓冲区 BufferedImage toImg = ImageIO.read(toinput); // 获取from图片宽度 int fromWidth = fromImg.getWidth(); // 获取from图片高度 int fromHeight = fromImg.getHeight(); // 获取to图片宽度 int toWidth = toImg.getWidth(); // 获取to图片高度 int toHeight = toImg.getHeight(); // Graphics2D ,Graphics 类,提供了对几何形状、坐标转换、颜色管理和文本布局更为复杂的控制。 // 它是用于在 Java(tm) 平台上呈现二维形状、文本和图像的基础类。验证码生成可以用到此类。 // public abstract class Graphics2Dextends Graphics 此 Graphics2D 类扩展了 Graphics 类, // 提供了对几何形状、坐标转换、颜色管理和文本布局更为复杂的控制。 Graphics2D g = toImg.createGraphics(); // 合并图片 if (x < 0) { // 合并到右下角 x = toWidth - fromWidth; } if (y < 0) { // 合并到右下角 y = toHeight - fromHeight; } g.drawImage(fromImg, x, y, fromWidth, fromHeight, null); // 释放资源 g.dispose(); // 获取to文件扩展名 String toExtName = FilenameUtils.getExtension(toFile.getName()); // 输出to图片缓冲区到输出的文件中 ImageIO.write(toImg, toExtName, output); } catch (Exception e) { throw new ServiceException(e); } finally { IOUtils.closeQuietly(frominput); IOUtils.closeQuietly(toinput); IOUtils.closeQuietly(output); } } /** * 将两张图片合并后输出图片 * * @param fromFile * 合并来自文件 * @param toFile * 合并到文件 * @param destFile * 目标文件 * @author 张军 * @date 2015-11-03 21:59:00 * @modifiyNote * @version 1.0 */ public static void writeImageMerge(File fromFile, File toFile, File destFile) { writeImageMerge(fromFile, toFile, destFile, 0, 0); } /** * 将两张图片合并后输出图片 * * @param from * 合并来自文件路径 * @param to * 合并到文件路径 * @param dest * 目标文件路径 * @param x * x坐标,默认合并到左上角,当x<0时,合并到右下角 * @param y * y坐标,默认合并到左上角,当y<0时,合并到右下角 * @author 张军 * @date 2015-11-03 21:59:00 * @modifiyNote * @version 1.0 */ public static void writeImageMerge(String from, String to, String dest, int x, int y) { writeImageMerge(new File(from), new File(to), new File(dest), x, y); } /** * 将两张图片合并后输出图片 * * @param from * 合并来自文件路径 * @param to * 合并到文件路径 * @param dest * 目标文件路径 * @author 张军 * @date 2015-11-03 21:59:00 * @modifiyNote * @version 1.0 */ public static void writeImageMerge(String from, String to, String dest) { writeImageMerge(new File(from), new File(to), new File(dest), 0, 0); } }
本文为张军原创文章,转载无需和我联系,但请注明来自张军的军军小站,个人博客http://www.zhangjunbk.com