package demotest; import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.font.FontRenderContext; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.imageio.IIOImage; import javax.imageio.ImageIO; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; public class ImageUtil { /** * 颜色转换 */ private static Color fromStrToARGB(String str) { String str1 = str.substring(1, 3); String str2 = str.substring(3, 5); String str3 = str.substring(5, 7); int red = Integer.parseInt(str1, 16); int green = Integer.parseInt(str2, 16); int blue = Integer.parseInt(str3, 16); if (str.length() == 9) { String str4 = str.substring(7, 9); int alpha = Integer.parseInt(str4, 16); return new Color(red, green, blue, alpha); } else { return new Color(red, green, blue); } } /** * 创建Graphics2D * * @param bgBufImage * 底图 * @return Graphics2D */ private static Graphics2D createG2D(BufferedImage bgBufImage) { Graphics2D bgBufImageGraphics = bgBufImage.createGraphics(); bgBufImageGraphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); return bgBufImageGraphics; } /** * 绘制海报底色(默认微软雅黑/PLAIN/32) * * @param bgBufImage * 底图 * @param color * 颜色 */ private static void setBackGroup(BufferedImage bgBufImage, String color) { Graphics2D bgBufImageGraphics = createG2D(bgBufImage); bgBufImageGraphics.setBackground(fromStrToARGB(color));// 填充整个屏幕 bgBufImageGraphics.clearRect(0, 0, bgBufImage.getWidth(), bgBufImage.getHeight()); bgBufImageGraphics.dispose(); } /** * 绘制海报文字(默认微软雅黑/PLAIN/32) * * @param basebBI * 底图 * @param text * 文本 * @param x * 坐标 x * @param y * 坐标 y * @param color * 颜色 * @param font * 字体 */ private static void drawText(BufferedImage basebBI, String text, int x, int y, String color, Font font) { // 抗锯齿 if (font == null) { font = new Font("微软雅黑", Font.PLAIN, 32); } Graphics2D g2D = createG2D(basebBI); g2D.setFont(font); g2D.setPaint(new Color(0, 0, 0, 64)); // 先绘制一遍底色 g2D.drawString(text, x, y); g2D.setPaint(fromStrToARGB(color)); // 再绘制一遍文字 // 由于部分情况会出现文字模糊的情况,保险起见才出此对策。 g2D.drawString(text, x, y); g2D.dispose(); } /** * * 绘制海报文字(换行) * * @param basebBI * 底图 * @param text * 文本 * @param x * 位置:x * @param y * 位置:y * @param lineHeight * 单行行高 * @param lineWidth * 单行行宽 * @param color * 文本颜色 * @param font * 文本字体 * @param limitLineNum * 限制行数 * @param backgroundWidth * 底背位置(多行文字绘制时,出现为单行时居中的区域宽度。) */ private static void drawTextNewLine(BufferedImage basebBI, String text, int x, int y, int lineHeight, int lineWidth, String color, Font font, int limitLineNum, int backgroundWidth) { Graphics2D graphics = createG2D(basebBI); if (font == null) { font = new Font("微软雅黑", Font.PLAIN, 32); } graphics.setFont(font); graphics.setPaint(fromStrToARGB(color)); // 计算字符串所占屏幕长度 FontRenderContext frc = graphics.getFontRenderContext(); graphics.getFontRenderContext(); // 记录行数 List<String> lineList = new ArrayList<String>(); if (backgroundWidth > 0) { x = (backgroundWidth - lineWidth) / 2; } int stringIndex = 0; StringBuilder tmpLineString = new StringBuilder(""); while (stringIndex < text.length()) { String tmp_char = text.substring(stringIndex, stringIndex + 1); Rectangle2D tempStringBounds = font.getStringBounds(tmpLineString + tmp_char, frc); double width = tempStringBounds.getWidth(); if (width > lineWidth) { lineList.add(tmpLineString.toString()); tmpLineString = new StringBuilder(""); } tmpLineString = tmpLineString.append(tmp_char); stringIndex++; } // Color.BLACK 。字体颜色 graphics.setPaint(fromStrToARGB(color)); if (lineHeight == 0) { lineHeight = 35; } for (int i = 0; i < lineList.size(); i++) { String lineStr = lineList.get(i); double width = font.getStringBounds(lineStr, frc).getWidth(); double diffWidth = font.getStringBounds("...", frc).getWidth(); if (i > limitLineNum - 1) { break; } else if (i == limitLineNum - 1 && lineWidth - width < diffWidth) { lineStr = lineStr.substring(0, lineStr.length() - 2) + "..."; } graphics.drawString(lineStr, x, y + (i + 1) * lineHeight); graphics.drawString(lineStr, x, y + (i + 1) * lineHeight); } graphics.dispose(); } /** * * 绘制海报图片 * * @param basebBI * 底图 * @param path * 图片地址 * @param x * 位置:x * @param y * 位置:y * @param width * 图片宽度 * @param height * 图片高度 */ private static void drawImage(BufferedImage basebBI, String path, int x, int y, int width, int height) throws Exception { BufferedImage qrCodeImage = ImageIO.read(new URL(path)); drawImage(basebBI, qrCodeImage, x, y, width, height); } /** * * 绘制海报图片 * * @param basebBI * 底图 * @param imageBI * 图片 BufferedImage * @param x * 位置:x * @param y * 位置:y * @param width * 图片宽度 * @param height * 图片高度 */ private static void drawImage(BufferedImage basebBI, BufferedImage imageBI, int x, int y, int width, int height) { Graphics2D g2D = createG2D(basebBI); if (width == -1) { width = imageBI.getWidth(); } if (height == -1) { height = imageBI.getHeight(); } g2D.drawImage(imageBI, x, y, width, height, null); g2D.dispose(); } /** * 创建带圆角的图片 * * @param path * 图片地址 * @param ratioWith * 水平直径 -1 表示圆型 * @param ratioHeith * 垂直直径 -1 表示圆型 */ private static BufferedImage getRoundImage(String path, int ratioWith, int ratioHeith) throws Exception { BufferedImage qrCodeImage = ImageIO.read(new URL(path)); BufferedImage image = new BufferedImage(qrCodeImage.getWidth(), qrCodeImage.getHeight(), BufferedImage.TYPE_INT_ARGB); Graphics2D image2D = createG2D(image); if (ratioWith <= -1) { ratioWith = qrCodeImage.getWidth(); } if (ratioHeith <= -1) { ratioHeith = qrCodeImage.getHeight(); } image2D.fillRoundRect(0, 0, qrCodeImage.getWidth(), qrCodeImage.getHeight(), ratioWith, ratioHeith); image2D.setComposite(AlphaComposite.SrcIn); image2D.drawImage(qrCodeImage, 0, 0, qrCodeImage.getWidth(), qrCodeImage.getHeight(), null); image2D.dispose(); return image; } private static BufferedImage getRoundImageFromFile(String path, int ratioWith, int ratioHeith) throws Exception { BufferedImage qrCodeImage = getFromPath(path); BufferedImage image = new BufferedImage(qrCodeImage.getWidth(), qrCodeImage.getHeight(), BufferedImage.TYPE_INT_ARGB); Graphics2D image2D = createG2D(image); if (ratioWith <= -1) { ratioWith = qrCodeImage.getWidth(); } if (ratioHeith <= -1) { ratioHeith = qrCodeImage.getHeight(); } image2D.fillRoundRect(0, 0, qrCodeImage.getWidth(), qrCodeImage.getHeight(), ratioWith, ratioHeith); image2D.setComposite(AlphaComposite.SrcIn); image2D.drawImage(qrCodeImage, 0, 0, qrCodeImage.getWidth(), qrCodeImage.getHeight(), null); image2D.dispose(); return image; } /** * 输出图片 * * @param bgBufImage * 底图 * @param path * 图片输出地址 */ private static void saveImage(BufferedImage bgBufImage, String path) throws Exception { Iterator<ImageWriter> iterator = ImageIO.getImageWritersByFormatName("jpeg"); ImageWriter imageWriter = iterator.next(); ImageWriteParam imageWriteParam = imageWriter.getDefaultWriteParam(); imageWriteParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); imageWriteParam.setCompressionQuality(1); imageWriter.setOutput(ImageIO.createImageOutputStream(new FileOutputStream(new File(path)))); IIOImage iio_image = new IIOImage(bgBufImage, null, null); imageWriter.write(null, iio_image, imageWriteParam); imageWriter.dispose(); } private static BufferedImage getFromUrl(String url) throws MalformedURLException, IOException { return ImageIO.read(new URL(url)); } private static BufferedImage getFromPath(String path) throws MalformedURLException, IOException { return ImageIO.read(new FileInputStream(new File(path))); } public static void drawImage() throws Exception { // 二维码 String headUrl = "https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTL4BMa9N95tib3hae2XmIAhylV5Ex8GCekv0o6Rib55FLUvvnk1hMhBNZbqbUn5mXokt9DS7V2WSCkQ/132"; // 头像 String code = "e:\1.jpg"; // BufferedImage bgBufImage = new BufferedImage(750, 1334, // BufferedImage.TYPE_INT_RGB); // setBackGroup(bgBufImage, "#FF0000"); // drawImage(bgBufImage, qrCodeImageUrl, bgBufImage.getWidth() - 200, 10, -1, // -1); // drawImage(bgBufImage, getRoundImage(headUrl, -1, -1), 100, 100, 200, 200); // drawText(bgBufImage, "测试", 0, 100, "#000000", null); // drawTextNewLine(bgBufImage, "测试圣诞快乐数据库里搭街坊卡拉手机打开拉萨奥斯陆冬季开发了喀什假大空立法解释考虑", 0, // 100, 35, 200, "#000000", null, 3, // 750); // BufferedImage bgBufImage = ImageIO.read(new URL(headUrl)); // drawText(bgBufImage, "测试", 0, 100, "#000000", null); // saveImage(bgBufImage, "E:\demo1.jpeg"); BufferedImage bgBufImage = getFromPath(code); BufferedImage headImage = getRoundImage(headUrl, 20, 20); drawImage(bgBufImage, headImage, 100, 100, 100, 100); saveImage(bgBufImage, "E:\demo2.jpeg"); } public static Font getFontFromFile(String path) throws Exception { InputStream is = new FileInputStream(path); return Font.createFont(Font.TRUETYPE_FONT, is); } public static void main(String[] args) { try { // drawImage(); String text = "娄山关路 设备编号: LSG-XG-6-001"; BufferedImage codeimg = getFromPath("e:\11.jpg"); Graphics2D g = codeimg.createGraphics(); // g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, // RenderingHints.VALUE_ANTIALIAS_ON); g.setBackground(Color.white); g.setColor(Color.white); g.fillRect(50, 460, 380, 50); // 画圆 // g.fillOval(175, 175, 120, 120); BufferedImage logoimg = getRoundImageFromFile("e:\logo.jpg", 120, 120); g.drawImage(logoimg, 175, 175, 120, 120, null); // g.drawImage(codeimg, 50, 460, 380, 50, null); // Font font = new Font("Serif", Font.BOLD, 20); Font font = getFontFromFile("e:\simhei.ttf"); font = font.deriveFont(20.0f); font.deriveFont(Font.BOLD); g.setColor(Color.red); g.setFont(font); // // 居中显示 FontMetrics fm = g.getFontMetrics(font); int textWidth = fm.stringWidth(text); int widthX = (430 - textWidth) / 2; g.drawString(text, widthX, 480); // saveImage(codeimg, "E:\demo2.jpeg"); ImageIO.write(codeimg, "jpg", new File("E:\demo2.jpg")); } catch (Exception e) { e.printStackTrace(); } } }