人在碼上走,需求天天有。這不,今天前端讓我返回一個帶自定義水印的背景圖片。一通google,有現成的代碼,但是基本是直接在源圖上添加水印,生成出來的文字樣式也沒有控制好,看來又只有自己造輪子了。
過程有點曲折,直接上最終代碼:
import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.Transparency; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; /** * 圖片處理工具類 基於https://blog.csdn.net/beinlife/article/details/53665152 改造 */ public class ImageUtil { /** * 生成背景透明的 文字水印,文字位於透明區域正中央,可設置旋轉角度 * * @param width 生成圖片寬度 * @param heigth 生成圖片高度 * @param text 水印文字 * @param color 顏色對象 * @param font awt字體 * @param degree 水印文字旋轉角度 * @param alpha 水印不透明度0f-1.0f */ public static BufferedImage waterMarkByText(int width, int heigth, String text, Color color, Font font, Double degree, float alpha) { BufferedImage buffImg = new BufferedImage(width, heigth, BufferedImage.TYPE_INT_RGB); /**2、得到畫筆對象*/ Graphics2D g2d = buffImg.createGraphics(); // ---------- 增加下面的代碼使得背景透明 ----------------- buffImg = g2d.getDeviceConfiguration() .createCompatibleImage(width, heigth, Transparency.TRANSLUCENT); g2d.dispose(); g2d = buffImg.createGraphics(); // ---------- 背景透明代碼結束 ----------------- // 設置對線段的鋸齒狀邊緣處理 g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); //把源圖片寫入 // g2d.drawImage(srcImg.getScaledInstance(srcImg.getWidth(null), // srcImg.getHeight(null), Image.SCALE_SMOOTH), 0, 0,null); // 設置水印旋轉 if (null != degree) { //注意rotate函數參數theta,為弧度制,故需用Math.toRadians轉換一下 //以矩形區域中央為圓心旋轉 g2d.rotate(Math.toRadians(degree), (double) buffImg.getWidth() / 2, (double) buffImg.getHeight() / 2); } // 設置顏色 g2d.setColor(color); // 設置 Font g2d.setFont(font); //設置透明度:1.0f為透明度 ,值從0-1.0,依次變得不透明 g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha)); //獲取真實寬度 float realWidth = getRealFontWidth(text); float fontSize = font.getSize(); //計算繪圖偏移x、y,使得使得水印文字在圖片中居中 //這里需要理解x、y坐標是基於Graphics2D.rotate過后的坐標系 float x = 0.5f * width - 0.5f * fontSize * realWidth; float y = 0.5f * heigth + 0.5f * fontSize; //取繪制的字串寬度、高度中間點進行偏移,使得文字在圖片坐標中居中 g2d.drawString(text, x, y); //釋放資源 g2d.dispose(); // System.out.println("添加水印文字完成!"); return buffImg; } public static BufferedImage waterMarkByText(int width, int heigth, String text, Color color, float alpha) { //jdk默認字體 Font font = new Font("Dialog", Font.ROMAN_BASELINE, 33); return waterMarkByText(width, heigth, text, color,font, -30d, alpha); } public static BufferedImage waterMarkByText(int width, int heigth, String text, float alpha) { return waterMarkByText(width, heigth, text, Color.GRAY, alpha); } public static BufferedImage waterMarkByText(int width, int heigth, String text) { return waterMarkByText(width, heigth, text, 0.2f); } public static BufferedImage waterMarkByText(String text) { return waterMarkByText(200, 150, text); } /** * 獲取真實字符串寬度,ascii字符占用0.5,中文字符占用1.0 */ private static float getRealFontWidth(String text) { int len = text.length(); float width = 0f; for (int i = 0; i < len; i++) { if (text.charAt(i) < 256) { width += 0.5f; } else { width += 1.0f; } } return width; } public static void main(String[] args) { int width = 200; int heigth = 150; Font font = new Font("微軟雅黑", Font.ROMAN_BASELINE, 33);//字體 BufferedImage bi1 = waterMarkByText(width, heigth, "測試aB~,", Color.GRAY, font, -30d, 0.2f);//給圖片添加文字水印 // BufferedImage bi = waterMarkByText(width, heigth, "測試aB~,", Color.GRAY, -30d, // 0.2f);//給圖片添加文字水印 // BufferedImage bi2 = waterMarkByText(width, heigth, "測試aB~,");//給圖片添加文字水印 // BufferedImage bi3 = waterMarkByText("測試aB~,"); try { ImageIO.write(bi1, "png", new File("D:/test.png"));//寫入文件 System.out.println(Color.decode("#00bcd4")); } catch (IOException e) { e.printStackTrace(); } } }
最終效果如下:
完美解決~