Java實(shí)現(xiàn)畫圖的詳細(xì)步驟(完整代碼)
更新時(shí)間:2021年06月22日 11:03:15 作者:Java工程師time
今天給大家?guī)淼氖顷P(guān)于Java的相關(guān)知識,文章圍繞著Java實(shí)現(xiàn)畫圖的詳細(xì)步驟展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
一、導(dǎo)入依賴
<dependency> <groupId>net.coobird</groupId> <artifactId>thumbnailator</artifactId> <version>0.4.13</version> </dependency>
二、工具類
package com.geidco.dcp.util; import net.coobird.thumbnailator.Thumbnails; import net.coobird.thumbnailator.filters.ImageFilter; import net.coobird.thumbnailator.geometry.Coordinate; import org.apache.commons.lang3.StringUtils; import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.*; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; import java.util.List; /** * @author XuPengFei */ public class ImageUtil { public static BufferedImage watermarkImgBase64(String base64, List<ImageWatermark> images, List<ImageFontText> texts) throws Exception { InputStream inputStream = null; base64 = base64.replaceFirst("data:image\\/.*;base64,", ""); Base64.Decoder decoder = Base64.getDecoder(); try { byte[] bytes = decoder.decode(base64); ByteArrayInputStream bais = new ByteArrayInputStream(bytes); inputStream = bais; } catch (Exception e) { e.printStackTrace(); } BufferedImage destImage = ImageIO.read(inputStream); BufferedImage tempImage = null; int w1 = destImage.getWidth(), h1 = destImage.getHeight(), startX, startY, endX, endY; System.out.println("w1" + w1); System.out.println("h1" + h1); //水印位置 Coordinate coordinate = null; //水印位置坐標(biāo)左上、右下 List<Integer> points = null; for (ImageWatermark imageWatermark : images) { inputStream = getInputStream(imageWatermark.getImageUrl()); if (null == inputStream) { continue; } points = imageWatermark.getPoints(); startX = new BigDecimal(points.get(0)).intValue(); startY = new BigDecimal(points.get(1)).intValue(); endX = new BigDecimal(points.get(2)).intValue(); endY = new BigDecimal(points.get(3)).intValue(); //設(shè)置水印位置 coordinate = new Coordinate(startX, startY); tempImage = Thumbnails.of(ImageIO.read(inputStream)).size(endX - startX, endY - startY).keepAspectRatio(false).asBufferedImage(); // tempImage = Thumbnails.of(ImageIO.read(inputStream)).size(180,180).keepAspectRatio(false).asBufferedImage(); // destImage = Thumbnails.of(destImage).size(w1,h1).watermark(coordinate,tempImage,1f).asBufferedImage(); destImage = Thumbnails.of(destImage).size(w1, h1).watermark(coordinate, tempImage, 1f).asBufferedImage(); } for (ImageFontText fontText : texts) { startX = new BigDecimal(fontText.getStartX()).intValue(); startY = new BigDecimal(fontText.getStartY()).intValue(); destImage = mergeFontText(destImage, fontText, startX, startY); } destImage = Thumbnails.of(destImage).addFilter(new ThumbnailsImgFilter()).size(w1, h1).asBufferedImage(); return destImage; } public static BufferedImage watermarkImg(String baseImgUrl, List<ImageWatermark> images, List<ImageFontText> texts) throws Exception { InputStream inputStream = getInputStream(baseImgUrl); if (null == inputStream) { throw new RuntimeException("海報(bào)圖片生成失敗"); } BufferedImage destImage = ImageIO.read(inputStream); BufferedImage tempImage = null; int w1 = destImage.getWidth(), h1 = destImage.getHeight(), startX, startY, endX, endY; System.out.println("w1" + w1); System.out.println("h1" + h1); //水印位置 Coordinate coordinate = null; //水印位置坐標(biāo)左上、右下 List<Integer> points = null; for (ImageWatermark imageWatermark : images) { inputStream = getInputStream(imageWatermark.getImageUrl()); if (null == inputStream) { continue; } points = imageWatermark.getPoints(); startX = new BigDecimal(points.get(0)).intValue(); startY = new BigDecimal(points.get(1)).intValue(); endX = new BigDecimal(points.get(2)).intValue(); endY = new BigDecimal(points.get(3)).intValue(); //設(shè)置水印位置 coordinate = new Coordinate(startX, startY); tempImage = Thumbnails.of(ImageIO.read(inputStream)).size(endX - startX, endY - startY).keepAspectRatio(false).asBufferedImage(); // tempImage = Thumbnails.of(ImageIO.read(inputStream)).size(180,180).keepAspectRatio(false).asBufferedImage(); // destImage = Thumbnails.of(destImage).size(w1,h1).watermark(coordinate,tempImage,1f).asBufferedImage(); destImage = Thumbnails.of(destImage).addFilter(new ThumbnailsImgFilter()).size(w1, h1).watermark(coordinate, tempImage, 1f).asBufferedImage(); } for (ImageFontText fontText : texts) { startX = new BigDecimal(fontText.getStartX()).intValue(); startY = new BigDecimal(fontText.getStartY()).intValue(); destImage = mergeFontText(destImage, fontText, startX, startY); } return destImage; } private static BufferedImage mergeFontText(BufferedImage bufferedImage, ImageFontText fontText, int left, int top) throws Exception { Graphics2D g = bufferedImage.createGraphics(); g.setColor(getColor(fontText.getTextColor())); Font font = new Font(fontText.getTextFont(), Font.BOLD, fontText.getTextSize()); g.setFont(font); g.setBackground(Color.white); if (fontText.getStartX() == -1) { //昵稱居中設(shè)置 FontMetrics fmNick = g.getFontMetrics(font); int nickWidth = fmNick.stringWidth(fontText.getText()); int nickWidthX = (bufferedImage.getWidth() - nickWidth) / 2; //繪制文字 g.drawString(new String(fontText.getText().getBytes(), "utf-8"), nickWidthX, top); } else { g.drawString(new String(fontText.getText().getBytes(), "utf-8"), left, top); } g.dispose(); return bufferedImage; // AttributedString ats = new AttributedString("我是\n小雨哈哈哈"); // ats.addAttribute(TextAttribute.FOREGROUND, f, 0,2 ); // AttributedCharacterIterator iter = ats.getIterator(); // g.drawString(iter,left,top); } private static Color getColor(String color) { if (StringUtils.isBlank(color) || color.length() < 7) { return null; } try { int r = Integer.parseInt(color.substring(1, 3), 16); int g = Integer.parseInt(color.substring(3, 5), 16); int b = Integer.parseInt(color.substring(5), 16); return new Color(r, g, b); } catch (NumberFormatException nfe) { return null; } } public static InputStream getInputStream(String baseUrl) { if (StringUtils.isBlank(baseUrl)) { return null; } try { InputStream inputStream = new FileInputStream(baseUrl); return inputStream; } catch (IOException e) { e.printStackTrace(); } // try { // URL url = new URL(baseUrl); // HttpURLConnection connection = (HttpURLConnection) url.openConnection(); // connection.setConnectTimeout(6000); // connection.setReadTimeout(6000); // int code = connection.getResponseCode(); // if (HttpURLConnection.HTTP_OK == code) { // return connection.getInputStream(); // } // } catch (Exception e) { // e.printStackTrace(); // } return null; } /** * 將透明背景設(shè)置為白色 */ public static class ThumbnailsImgFilter implements ImageFilter { @Override public BufferedImage apply(BufferedImage img) { int w = img.getWidth(); int h = img.getHeight(); BufferedImage newImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); Graphics2D graphic = newImage.createGraphics(); graphic.setColor(Color.white);//背景設(shè)置為白色 graphic.fillRect(0, 0, w, h); graphic.drawRenderedImage(img, null); graphic.dispose(); return newImage; } } }
三、工具類
package com.geidco.dcp.util; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; /** * @author XuPengFei */ @Data @NoArgsConstructor @AllArgsConstructor public class ImageFontText { private String text; private Integer textSize = 50; private String textColor = "#ff0000"; private String textFont = "宋體"; private Integer startX; private Integer startY; }
四、工具類
package com.geidco.dcp.util; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.util.List; /** * @author XuPengFei */ @Data @NoArgsConstructor @AllArgsConstructor public class ImageWatermark { /** * 圖片地址 */ private String imageUrl; /** * 水印圖片左上、右下標(biāo) */ private List<Integer> points; }
五、測試接口
package com.geidco.dcp.controller.meetingApply; import com.geidco.dcp.pojo.meetingApply.MeetingApply; import com.geidco.dcp.pojo.meetingApply.MeetingGuestCardTemplate; import com.geidco.dcp.service.meetingApply.MeetingApplyService; import com.geidco.dcp.service.meetingApply.MeetingGuestCardTemplateService; import com.geidco.dcp.util.*; import com.xlkh.cloud.platform.common.annotation.Log; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.util.ResourceUtils; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.imageio.ImageIO; import javax.servlet.http.HttpServletResponse; import java.awt.image.BufferedImage; import java.io.*; import java.text.SimpleDateFormat; import java.util.*; @RestController @RequestMapping("/meetingGuestCard") public class MeetingGuestCardController { @Value("${config.ldir}") String ldir; @Value("${config.wdir}") String wdir; @Autowired private MeetingApplyService meetingApplyService; @Autowired private IdWorker idWorker; @Autowired private MeetingGuestCardTemplateService meetingGuestCardTemplateService; @PostMapping("/generateGuestCard") @Log("繪制電子嘉賓證") public void generateGuestCard(@RequestBody Map<String, String> formData, HttpServletResponse response) { String templateId = formData.get("templateId"); String ids = formData.get("meetingApplyId"); List<String> meetingApplyIds = Arrays.asList(ids.split(",")); List<MeetingApply> meetingApplys = meetingApplyService.getByKeys(meetingApplyIds); String uuid = UUID.randomUUID().toString().replaceAll("-", ""); String datePath = new SimpleDateFormat("yyyy/MM/dd").format(new Date()) + "/" + uuid + "/"; String zipPath = SysMeetingUtil.getAnnexFilePath() + "generateGuestCard/" + datePath; File file = new File(zipPath); if (!file.exists()) { file.mkdirs(); } // 上傳的位置 String path = System.getProperty("os.name").toLowerCase().indexOf("win") >= 0 ? wdir : ldir; MeetingGuestCardTemplate cardTemplate = meetingGuestCardTemplateService.findById(templateId); // 底圖 String baseImgUrl = cardTemplate.getBaseMapUrl(); try { for (int i = 0; i < meetingApplys.size(); i++) { MeetingApply meetingApply = meetingApplys.get(i); String name = null; String unitName = null; String postName = null; String photoUrl = path; if ("zh".equals(meetingApply.getApplyWay())) { name = meetingApply.getName(); unitName = meetingApply.getUnitName(); postName = meetingApply.getPositionName(); photoUrl = photoUrl + meetingApply.getPhotoUrl(); } else { name = meetingApply.getNameEn(); unitName = meetingApply.getUnitNameEn(); postName = meetingApply.getPositionNameEn(); photoUrl = photoUrl + meetingApply.getPhotoUrl(); } List<ImageWatermark> images = new ArrayList<>(); List<ImageFontText> texts = new ArrayList<>(); // 查詢模板詳情 List<MeetingGuestCardTemplate> templates = meetingGuestCardTemplateService.findByTemplateId(templateId); for (MeetingGuestCardTemplate template : templates) { String dict = template.getElementTypeDict(); if ("1".equals(dict)) { ImageFontText imageFontText = new ImageFontText(name, StringUtils.isNotBlank(template.getFontSize()) ? Integer.parseInt(template.getFontSize()) : 30, StringUtils.isNotBlank(template.getFontColor()) ? template.getFontColor() : "#333333", StringUtils.isNotBlank(template.getFontType()) ? template.getFontType() : "宋體", template.getStartX(), template.getStartY()); texts.add(imageFontText); } if ("2".equals(dict)) { ImageFontText imageFontText = new ImageFontText(unitName, StringUtils.isNotBlank(template.getFontSize()) ? Integer.parseInt(template.getFontSize()) : 30, StringUtils.isNotBlank(template.getFontColor()) ? template.getFontColor() : "#333333", StringUtils.isNotBlank(template.getFontType()) ? template.getFontType() : "宋體", template.getStartX(), template.getStartY()); texts.add(imageFontText); } if ("3".equals(dict)) { ImageFontText imageFontText = new ImageFontText(postName, StringUtils.isNotBlank(template.getFontSize()) ? Integer.parseInt(template.getFontSize()) : 30, StringUtils.isNotBlank(template.getFontColor()) ? template.getFontColor() : "#333333", StringUtils.isNotBlank(template.getFontType()) ? template.getFontType() : "宋體", template.getStartX(), template.getStartY()); texts.add(imageFontText); } if ("100".equals(dict)) { Integer startX = template.getStartX(); Integer startY = template.getStartY(); Integer endX = template.getEndX(); Integer endY = template.getEndY(); List<Integer> imagePoints = Arrays.asList(startX, startY, endX, endY); ImageWatermark image = new ImageWatermark(photoUrl, imagePoints); images.add(image); } } try { BufferedImage bufferedImage = ImageUtil.watermarkImgBase64(baseImgUrl, images, texts); OutputStream os = new FileOutputStream(zipPath + String.valueOf(i + 1) + name + ".jpg"); ImageIO.write(bufferedImage, "jpg", os); //更新meetingApply的狀態(tài) MeetingApply apply = new MeetingApply(); apply.setId(meetingApply.getId()); apply.setCreateCardDate(new Date()); apply.setIsCreateCard("Yes"); apply.setCardUrl("generateGuestCard/" + datePath + String.valueOf(i + 1) + name + ".jpg"); meetingApplyService.update(apply); } catch (Exception e) { e.printStackTrace(); } } String zipFile = CompressUtil.zipFile(new File(zipPath), "zip"); response.setContentType("APPLICATION/OCTET-STREAM"); String fileName = "guestCard" + uuid + ".zip"; response.setHeader("Content-Disposition", "attachment; filename=" + fileName); //ZipOutputStream out = new ZipOutputStream(response.getOutputStream()); OutputStream out = response.getOutputStream(); File ftp = ResourceUtils.getFile(zipFile); InputStream in = new FileInputStream(ftp); // 循環(huán)取出流中的數(shù)據(jù) byte[] b = new byte[100]; int len; while ((len = in.read(b)) != -1) { out.write(b, 0, len); } in.close(); out.close(); } catch (Exception e) { e.printStackTrace(); } } }
六、頁面效果
到此這篇關(guān)于Java實(shí)現(xiàn)畫圖的詳細(xì)步驟(完整代碼)的文章就介紹到這了,更多相關(guān)Java實(shí)現(xiàn)畫圖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java NIO Path接口和Files類配合操作文件的實(shí)例
下面小編就為大家分享一篇Java NIO Path接口和Files類配合操作文件的實(shí)例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2017-11-11JAVA多線程實(shí)現(xiàn)生產(chǎn)者消費(fèi)者的實(shí)例詳解
這篇文章主要介紹了JAVA多線程實(shí)現(xiàn)生產(chǎn)者消費(fèi)者的實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-06-06Java封裝數(shù)組之改進(jìn)為泛型數(shù)組操作詳解
這篇文章主要介紹了Java封裝數(shù)組之改進(jìn)為泛型數(shù)組操作,結(jié)合實(shí)例形式詳細(xì)分析了Java封裝數(shù)組為泛型數(shù)組相關(guān)原理、操作技巧與注意事項(xiàng),需要的朋友可以參考下2020-03-03Spring boot搭建web應(yīng)用集成thymeleaf模板實(shí)現(xiàn)登陸
這篇文章主要介紹了Spring boot搭建web應(yīng)用集成thymeleaf模板實(shí)現(xiàn)登陸,頁面使用bootstrap,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12