摘要:時間年月日星期五說明本文部分內容均來自慕課網。慕課網教學源碼無學習源碼第一章課程簡介引言通過一個項目案例的講解,如何在應用中實現圖片水印的添加。
時間:2017年07月21日星期五
說明:本文部分內容均來自慕課網。@慕課網:http://www.imooc.com
教學源碼:無
學習源碼:https://github.com/zccodere/s...
通過一個項目案例的講解,如何在JavaWeb應用中實現圖片水印的添加。
1-2 課程內容課程內容
1.Java圖片水印實現思路 2.課程項目案例介紹 框架 實現方式 結果演示 3.課程案例詳解 實現圖片添加單個文字水印 實現圖片添加單個圖片水印 實現圖片添加多個文字水印 實現圖片添加多個圖片水印 實現多圖片批量添加水印 4.課程總結1-3 課程目標
目標
1.了解Java圖片水印實現思路 2.掌握文字水印和圖片水印的思路 3.掌握多圖片批量水印的實現第二章:實現原理 2-1 實現思路
實現思路
1.創建緩存圖片對象 2.創建Java繪圖工具對象 3.使用繪圖工具對象將原圖繪制到緩存圖片對象 4.使用繪圖工具將水印(文字/圖片)繪制到緩存圖片對象 5.創建圖像編碼工具類 6.使用圖片編碼工具類,輸出緩存圖像到目標圖片文件2-2 實用工具類
實用工具類
1.BufferedImage:圖片緩存類 2.Graphics2D:對平面2D圖片進行操作 3.JPEGImageEncoder:對圖片文件進行編碼處理并輸出到磁盤文件中第三章:案例介紹 3-1 案例演示
項目案例
基于Strutus2框架的JavaWeb應用程序,允許一次上傳多個圖片,應用默認為上傳圖片添加水印,并將原圖與添加水印圖片對比展示。
說明
個人學習時,均使用SpringBoot框架相關技術
結果演示
默認首頁
點擊瀏覽并選中圖片
點擊上傳,結果如下
第四章:添加單個文字水印 4-1 搭建項目創建名為watermark的maven項目POM文件如下
4.0.0 com.myimooc watermark 0.0.1-SNAPSHOT jar watermark http://maven.apache.org org.springframework.boot spring-boot-starter-parent 1.5.1.RELEASE UTF-8 UTF-8 org.springframework.boot spring-boot-starter org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-freemarker commons-io commons-io 2.5 net.coobird thumbnailator 0.4.8 org.apache.maven.plugins maven-compiler-plugin 1.8
編寫配置類和啟動類,完成后項目結構如下
4-2 編寫頁面代碼演示:
4-3 編寫控制器類上傳文件 圖片上傳
代碼演示:
package com.myimooc.watermark.controller; import java.io.File; import java.util.ArrayList; import java.util.List; import javax.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.ModelAndView; import com.myimooc.watermark.domain.PicInfo; import com.myimooc.watermark.service.MarkService; import com.myimooc.watermark.service.UploadService; /** * WatermarkController 控制類 * * @author ZhangCheng on 2017-07-21 * */ @Controller public class WatermarkController { private static Logger logger = LoggerFactory.getLogger(WatermarkController.class); @Autowired private UploadService uploadService; @Autowired private MarkService markService; /*** * 單圖片上傳 * * @param image * @param request * @return */ @PostMapping("/watermark") public ModelAndView watermark(MultipartFile image, HttpServletRequest request) { ModelAndView mav = new ModelAndView("/watermark"); PicInfo picInfo = new PicInfo(); String uploadPath = "static/images/"; String realUploadPath = getClass().getClassLoader().getResource(uploadPath).getPath(); logger.info("上傳相對目錄:{}", uploadPath); logger.info("上傳絕對目錄:{}", uploadPath); String imageURL = uploadService.uploadImage(image, uploadPath, realUploadPath); File imageFile = new File(realUploadPath + image.getOriginalFilename()); String logoImageURL = markService.watermake(imageFile, image.getOriginalFilename(), uploadPath, realUploadPath); picInfo.setImageURL(imageURL); picInfo.setLogoImageURL(logoImageURL); mav.addObject("picInfo", picInfo); return mav; } /** * 圖片批量上傳 * * @param image * @param request * @return */ @PostMapping("/morewatermark") public ModelAndView morewatermark(List4-4 編寫水印接口image, HttpServletRequest request) { ModelAndView mav = new ModelAndView("/morewatermark"); String uploadPath = "static/images/"; String realUploadPath = getClass().getClassLoader().getResource(uploadPath).getPath(); logger.info("上傳相對目錄:{}", uploadPath); logger.info("上傳絕對目錄:{}", realUploadPath); if (image != null && image.size() > 0) { List picInfoList = new ArrayList (); for (MultipartFile imageFileTemp : image) { if(imageFileTemp == null || imageFileTemp.getSize() < 1){ continue; } PicInfo picInfo = new PicInfo(); String imageURL = uploadService.uploadImage(imageFileTemp, uploadPath, realUploadPath); File imageFile = new File(realUploadPath + imageFileTemp.getOriginalFilename()); String logoImageURL = markService.watermake(imageFile, imageFileTemp.getOriginalFilename(), uploadPath, realUploadPath); picInfo.setImageURL(imageURL); picInfo.setLogoImageURL(logoImageURL); picInfoList.add(picInfo); } mav.addObject("picInfoList", picInfoList); } return mav; } }
代碼演示:
package com.myimooc.watermark.service; import java.awt.Color; import java.awt.Font; import java.io.File; /** * 圖片水印服務類 * @author ZhangCheng on 2017-07-21 * */ public interface MarkService { /** 水印文字內容 */ public static final String MARK_TEXT = "妙手空空"; /** 水印文字類型 */ public static final String FONT_NAME = "微軟雅黑"; /** 水印文字樣式 */ public static final int FONT_STYLE = Font.BOLD; /** 水印文字大小 */ public static final int FONT_SIZE= 120;// 單位:像素 /** 水印文字顏色 */ public static final Color FONT_COLOR= Color.BLACK; /** 水印文字位置X軸 */ public static final int X = 10; /** 水印文字位置Y軸 */ public static final int Y = 10; /** 水印文字透明度*/ public static final float ALPHA = 0.3F; /** 水印圖片*/ public static final String LOGO = "logo.png"; /** * 功能:將傳入的圖片添加水印并保存到服務器中 * @param file * @param uploadPath * @param realUploadPath * @return 添加水印后圖片的URL相對地址 */ String watermake(File imageFile,String imageFileName,String uploadPath,String realUploadPath); }4-5 添加單個文字水印
代碼演示
package com.myimooc.watermark.service; import java.awt.AlphaComposite; import java.awt.Font; import java.awt.Graphics2D; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import javax.imageio.ImageIO; import org.springframework.stereotype.Service; import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGImageEncoder; /** * 圖片水印服務類,添加文字水印 * @author ZhangCheng on 2017-07-21 * */ //@Service @SuppressWarnings("unused") public class TextMarkServiceImpl implements MarkService { @Override public String watermake(File imageFile,String imageFileName, String uploadPath, String realUploadPath) { String logoFileName = "logo_" + imageFileName; OutputStream os = null; try { Image image = ImageIO.read(imageFile); int width = image.getWidth(null);// 原圖寬度 int height = image.getHeight(null);// 原圖高度 // 創建圖片緩存對象 BufferedImage bufferedImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB); // 創建繪繪圖工具對象 Graphics2D g = bufferedImage.createGraphics(); // 使用繪圖工具將原圖繪制到緩存圖片對象 g.drawImage(image, 0, 0, width,height,null); // 設置水印文字字體信息 g.setFont(new Font(FONT_NAME,FONT_STYLE,FONT_SIZE)); // 設置水印文字顏色 g.setColor(FONT_COLOR); int markWidth = FONT_SIZE * getTextLength(MARK_TEXT); int markHeight = FONT_SIZE; // 水印的高度和寬度之差 int widthDiff = width - markWidth; int heightDiff = height - markHeight; int x = X; int y = Y; // 判斷設置的值是否大于圖片大小 if(x > widthDiff){ x = widthDiff; } if(y > heightDiff){ y =heightDiff; } // 設置水印文字透明度 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, ALPHA)); // 添加水印 g.drawString(MARK_TEXT, x, y + FONT_SIZE); g.dispose(); os = new FileOutputStream(realUploadPath + "/" + logoFileName); JPEGImageEncoder en = JPEGCodec.createJPEGEncoder(os); en.encode(bufferedImage); } catch (Exception e) { e.printStackTrace(); } finally { if(os!=null){ try { os.close(); } catch (IOException e) { e.printStackTrace(); } } } return uploadPath + "/" + logoFileName; } /** * 功能:獲取文本長度。漢字為1:1,英文和數字為2:1 */ private int getTextLength(String text){ int length = text.length(); for(int i = 0 ; i < text.length(); i++){ String s = String.valueOf(text.charAt(i)); if(s.getBytes().length > 1){ length++; } } length = length % 2 == 0 ? length / 2 : length / 2 + 1; return length; } }第五章:添加單個圖片水印 5-1 圖片水印添加
代碼演示:
package com.myimooc.watermark.service; import java.awt.AlphaComposite; import java.awt.Graphics2D; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import javax.imageio.ImageIO; import org.springframework.stereotype.Service; import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGImageEncoder; /** * 圖片水印服務類,添加圖片水印 * @author ZhangCheng on 2017-07-22 * */ //@Service @SuppressWarnings("unused") public class ImageMarkServiceImpl implements MarkService { @Override public String watermake(File imageFile, String imageFileName, String uploadPath, String realUploadPath) { String logoFileName = "logo_" + imageFileName; OutputStream os = null; // 圖片地址 String logoPath = realUploadPath + "/" + LOGO; try { Image image = ImageIO.read(imageFile); int width = image.getWidth(null);// 原圖寬度 int height = image.getHeight(null);// 原圖高度 // 創建圖片緩存對象 BufferedImage bufferedImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB); // 創建繪繪圖工具對象 Graphics2D g = bufferedImage.createGraphics(); // 使用繪圖工具將原圖繪制到緩存圖片對象 g.drawImage(image, 0, 0, width,height,null); // 讀取Logo圖片 File logo = new File(logoPath); Image imageLogo = ImageIO.read(logo); // 獲取Logo圖片的寬度和高度 int markWidth = imageLogo.getWidth(null); int markHeight = imageLogo.getHeight(null); // 原圖和Logo圖片的高度和寬度之差 int widthDiff = width - markWidth; int heightDiff = height - markHeight; int x = X; int y = Y; // 判斷設置的值是否大于圖片大小 if(x > widthDiff){ x = widthDiff; } if(y > heightDiff){ y =heightDiff; } // 設置水印透明度 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, ALPHA)); // 添加水印 g.drawImage(imageLogo, x, y, null); g.dispose(); os = new FileOutputStream(realUploadPath + "/" + logoFileName); JPEGImageEncoder en = JPEGCodec.createJPEGEncoder(os); en.encode(bufferedImage); } catch (Exception e) { e.printStackTrace(); } finally { if(os!=null){ try { os.close(); } catch (IOException e) { e.printStackTrace(); } } } return uploadPath + "/" + logoFileName; } }第六章:添加多個文字水印 6-1 添加多個文字水印
代碼演示:
package com.myimooc.watermark.service; import java.awt.AlphaComposite; import java.awt.Font; import java.awt.Graphics2D; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import javax.imageio.ImageIO; import org.springframework.stereotype.Service; import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGImageEncoder; /** * 圖片水印服務類,添加多個文字水印 * @author ZhangCheng on 2017-07-22 * */ //@Service @SuppressWarnings("unused") public class MoreTextMarkServiceImpl implements MarkService { @Override public String watermake(File imageFile, String imageFileName, String uploadPath, String realUploadPath) { String logoFileName = "logo_" + imageFileName; OutputStream os = null; try { Image image = ImageIO.read(imageFile); int width = image.getWidth(null);// 原圖寬度 int height = image.getHeight(null);// 原圖高度 // 創建圖片緩存對象 BufferedImage bufferedImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB); // 創建繪繪圖工具對象 Graphics2D g = bufferedImage.createGraphics(); // 使用繪圖工具將原圖繪制到緩存圖片對象 g.drawImage(image, 0, 0, width,height,null); // 設置水印文字字體信息 g.setFont(new Font(FONT_NAME,FONT_STYLE,FONT_SIZE)); // 設置水印文字顏色 g.setColor(FONT_COLOR); int markWidth = FONT_SIZE * getTextLength(MARK_TEXT); int markHeight = FONT_SIZE; // 設置水印透明度 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, ALPHA)); // 旋轉圖片 g.rotate(Math.toRadians(30), bufferedImage.getWidth()/2, bufferedImage.getHeight()/2); int x = -width / 2; int y = -height / 2; int xmove = 200;// 水印之間的間隔 int ymove = 200;// 水印之間的間隔 // 循環添加 while (x < width * 1.5){ y = -height / 2; while(y < height * 1.5){ g.drawString(MARK_TEXT, x, y); y += markHeight + ymove; } x += markWidth + xmove; } g.dispose(); os = new FileOutputStream(realUploadPath + "/" + logoFileName); JPEGImageEncoder en = JPEGCodec.createJPEGEncoder(os); en.encode(bufferedImage); } catch (Exception e) { e.printStackTrace(); } finally { if(os!=null){ try { os.close(); } catch (IOException e) { e.printStackTrace(); } } } return uploadPath + "/" + logoFileName; } /** * 功能:獲取文本長度。漢字為1:1,英文和數字為2:1 */ private int getTextLength(String text){ int length = text.length(); for(int i = 0 ; i < text.length(); i++){ String s = String.valueOf(text.charAt(i)); if(s.getBytes().length > 1){ length++; } } length = length % 2 == 0 ? length / 2 : length / 2 + 1; return length; } }第七章:添加多個圖片水印 7-1 添加多個圖片水印
代碼演示:
package com.myimooc.watermark.service; import java.awt.AlphaComposite; import java.awt.Graphics2D; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import javax.imageio.ImageIO; import org.springframework.stereotype.Service; import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGImageEncoder; /** * 圖片水印服務類,添加多個圖片水印 * @author ZhangCheng on 2017-07-22 * */ @Service public class MoreImageMarkServiceImpl implements MarkService { @Override public String watermake(File imageFile, String imageFileName, String uploadPath, String realUploadPath) { String logoFileName = "logo_" + imageFileName; OutputStream os = null; try { Image image = ImageIO.read(imageFile); int width = image.getWidth(null);// 原圖寬度 int height = image.getHeight(null);// 原圖高度 // 創建圖片緩存對象 BufferedImage bufferedImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB); // 創建繪繪圖工具對象 Graphics2D g = bufferedImage.createGraphics(); // 使用繪圖工具將原圖繪制到緩存圖片對象 g.drawImage(image, 0, 0, width,height,null); // 圖片地址 String logoPath = realUploadPath + "/" + LOGO; // 讀取Logo圖片 File logo = new File(logoPath); Image imageLogo = ImageIO.read(logo); // Logo圖片的寬度和高度 int markWidth = imageLogo.getWidth(null); int markHeight = imageLogo.getHeight(null); // 設置水印透明度 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, ALPHA)); // 旋轉圖片 g.rotate(Math.toRadians(30), bufferedImage.getWidth()/2, bufferedImage.getHeight()/2); int x = -width / 2; int y = -height / 2; int xmove = 200;// 水印之間的間隔 int ymove = 200;// 水印之間的間隔 // 循環添加 while (x < width * 1.5){ y = -height / 2; while(y < height * 1.5){ // 添加水印 g.drawImage(imageLogo, x, y, null); y += markHeight + ymove; } x += markWidth + xmove; } g.dispose(); os = new FileOutputStream(realUploadPath + "/" + logoFileName); JPEGImageEncoder en = JPEGCodec.createJPEGEncoder(os); en.encode(bufferedImage); } catch (Exception e) { e.printStackTrace(); } finally { if(os!=null){ try { os.close(); } catch (IOException e) { e.printStackTrace(); } } } return uploadPath + "/" + logoFileName; } }第八章:批量添加圖片水印 8-1 批量添加圖片水印
代碼演示
1.編寫moreupload.html
上傳文件 圖片批量上傳
2.修改WatermarkController類
package com.myimooc.watermark.controller; import java.io.File; import java.util.ArrayList; import java.util.List; import javax.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.ModelAndView; import com.myimooc.watermark.domain.PicInfo; import com.myimooc.watermark.service.MarkService; import com.myimooc.watermark.service.UploadService; /** * WatermarkController 控制類 * * @author ZhangCheng on 2017-07-21 * */ @Controller public class WatermarkController { private static Logger logger = LoggerFactory.getLogger(WatermarkController.class); @Autowired private UploadService uploadService; @Autowired private MarkService markService; /*** * 單圖片上傳 * * @param image * @param request * @return */ @PostMapping("/watermark") public ModelAndView watermark(MultipartFile image, HttpServletRequest request) { ModelAndView mav = new ModelAndView("/watermark"); PicInfo picInfo = new PicInfo(); String uploadPath = "static/images/"; String realUploadPath = getClass().getClassLoader().getResource(uploadPath).getPath(); logger.info("上傳相對目錄:{}", uploadPath); logger.info("上傳絕對目錄:{}", uploadPath); String imageURL = uploadService.uploadImage(image, uploadPath, realUploadPath); File imageFile = new File(realUploadPath + image.getOriginalFilename()); String logoImageURL = markService.watermake(imageFile, image.getOriginalFilename(), uploadPath, realUploadPath); picInfo.setImageURL(imageURL); picInfo.setLogoImageURL(logoImageURL); mav.addObject("picInfo", picInfo); return mav; } /** * 圖片批量上傳 * * @param image * @param request * @return */ @PostMapping("/morewatermark") public ModelAndView morewatermark(Listimage, HttpServletRequest request) { ModelAndView mav = new ModelAndView("/morewatermark"); String uploadPath = "static/images/"; String realUploadPath = getClass().getClassLoader().getResource(uploadPath).getPath(); logger.info("上傳相對目錄:{}", uploadPath); logger.info("上傳絕對目錄:{}", realUploadPath); if (image != null && image.size() > 0) { List picInfoList = new ArrayList (); for (MultipartFile imageFileTemp : image) { if(imageFileTemp == null || imageFileTemp.getSize() < 1){ continue; } PicInfo picInfo = new PicInfo(); String imageURL = uploadService.uploadImage(imageFileTemp, uploadPath, realUploadPath); File imageFile = new File(realUploadPath + imageFileTemp.getOriginalFilename()); String logoImageURL = markService.watermake(imageFile, imageFileTemp.getOriginalFilename(), uploadPath, realUploadPath); picInfo.setImageURL(imageURL); picInfo.setLogoImageURL(logoImageURL); picInfoList.add(picInfo); } mav.addObject("picInfoList", picInfoList); } return mav; } }
3.編寫morewatermark.html
處理結果 操作結果
4.效果展示
訪問圖片批量上傳頁
選擇文件
點擊上傳圖片,結果如下
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/67449.html
時間:2017年07月09日星期日說明:本文部分內容均來自慕課網。@慕課網:http://www.imooc.com教學源碼:無學習源碼:https://github.com/zccodere/s... 第一章:概述 1-1 課程概述 主要內容 驗證碼歷史 課程內容 不同方案對比 設計與實現 總結 1-2 驗證碼歷史 驗證碼歷史 無驗證碼:垃圾騷擾 Luis von Ahn:Captcha 不斷...
摘要:時間年月日星期六說明本文部分內容均來自慕課網。可以更加專注于業務邏輯開發,縮短項目開發周期,提高項目開發速度。 時間:2017年07月15日星期六說明:本文部分內容均來自慕課網。@慕課網:http://www.imooc.com教學源碼:無學習源碼:https://github.com/zccodere/s... 第一章:課程介紹 1-1 課程介紹 在用戶進行信息概略瀏覽的時候,提供縮...
摘要:時間年月日星期五說明本文部分內容均來自慕課網。線性堆疊式二維碼示意圖矩陣式二維碼在一個矩形空間通過黑白像素在矩陣中的不同分布進行編碼。 時間:2017年06月23日星期五說明:本文部分內容均來自慕課網。@慕課網:http://www.imooc.com教學示例源碼:無個人學習源碼:https://github.com/zccodere/s... 第一章:二維碼的概念 1-1 二維碼概述...
摘要:時間年月日星期一說明本文部分內容均來自慕課網。多用于網絡加密。散列函數函數或消息摘要函數主要作用散列函數用來驗證數據的完整性。 時間:2017年4月10日星期一說明:本文部分內容均來自慕課網。@慕課網:http://www.imooc.com教學示例源碼:https://github.com/zccodere/s...個人學習源碼:https://github.com/zccodere...
閱讀 1772·2021-11-11 16:55
閱讀 2575·2021-08-27 13:11
閱讀 3632·2019-08-30 15:53
閱讀 2307·2019-08-30 15:44
閱讀 1396·2019-08-30 11:20
閱讀 1045·2019-08-30 10:55
閱讀 950·2019-08-29 18:40
閱讀 3042·2019-08-29 16:13