Java使用Graphics2D畫圖,畫圓,矩形,透明度等實現

背景

如上圖,需要使用Java生成一個圖片,?并以base64編碼的形式返回給前端展示。

使用Graphics2D類,來進行畫圖,其中需要畫方框、原型、插入圖標、寫入文字等,同時需要設置透明度等細節點?

環境:Jdk17,springboot2.7.13

代碼如下

有詳細的注釋

package com.demo;import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.FileUtil;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.ThreadLocalRandom;/*** <p>* 功能描述:* </p>** @author MILLA* @version 1.0* @since 2024/06/24 9:14*/
@Slf4j
public class ImageDemo {/*** 每個div的高度*/private static final int LINE_HEIGHT = 80;private static final double COLOR_WIDTH = 0.7;/*** 處方箋圖片寬*/private static final int PIC_WIDTH = 1200;/*** 頂部與底部留白*/private static final int MARGIN_Y = 52;/*** 左右留白*/private static final int MARGIN_X = 50;/*** 生成圖片后綴*/private static final String FILE_SUFFIX = ".jpg";public static void main(String[] args) throws Exception {List<Object> objects = Lists.newArrayList(1, 2, 3, 4, 5, 6);String base64 = new ImageDemo().getImage(objects);System.out.println(base64);}/*** 初始化** @param image    畫布* @param graphics 畫筆*/private void initiation(BufferedImage image, Graphics2D graphics) {int width = image.getWidth();int height = image.getHeight();graphics.setClip(0, 0, width, height);// 設置畫筆顏色graphics.setColor(Color.white);// 繪制背景graphics.fillRect(0, 0, width, height);// 設置抗鋸齒graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);}private String getImage(List<Object> objects) throws IOException {//讀取圖標流InputStream stream = this.getClass().getClassLoader().getResourceAsStream("static/icon.png");BufferedImage avatar = ImageIO.read(stream);// 新建圖片BufferedImage image = new BufferedImage(PIC_WIDTH, objects.size() * LINE_HEIGHT + MARGIN_Y * 2, BufferedImage.TYPE_INT_BGR);// 創建畫筆Graphics2D graphics = image.createGraphics();// 初始化背景色initiation(image, graphics);// 定義marginMargin margin = new Margin(MARGIN_Y, MARGIN_Y, MARGIN_X, MARGIN_X);// 初始化坐標Point point = new Point(margin.getLeft(), margin.getTop());ThreadLocalRandom random = ThreadLocalRandom.current();for (int i = 0; i < objects.size(); i++) {Color color = new Color(random.nextInt(0, 255), random.nextInt(0, 255), random.nextInt(0, 255));drawDiv(point, image, graphics, color, avatar, "顏色名稱: " + (i + 1), "P", "顏色編碼:" + (i + 1));}// 銷毀畫筆,結束繪制graphics.dispose();byte[] bytes = toByteArray(image);//文件生成log.info("文件路徑", FileUtil.writeBytes(bytes, "test" + FILE_SUFFIX));String prefix = "data:image/jpg;base64,";return prefix + Base64.encode(bytes);}private void drawDiv(Point point, BufferedImage image, Graphics2D graphics, Color color, BufferedImage avatar, String name, String type, String code) {Font font = new Font("宋體", Font.BOLD, 28);int width = image.getWidth() - 2 * point.getX();// 設置div的繪制區域graphics.setClip(point.getX(), point.getY(), width, LINE_HEIGHT);
//         設置畫筆顏色graphics.setColor(color);int firstWidth = (int) (COLOR_WIDTH * width);
//         繪制背景 一行的前半部分graphics.fillRect(point.getX(), point.getY() + 1, firstWidth, LINE_HEIGHT - 2);// 設置畫筆int nameX = point.getX() + 18;drawContent(name, graphics, nameX, point.getY(), Color.WHITE, image.getWidth(), point, font);int circleX = firstWidth - 15;drawCircle(point, graphics, circleX);font = new Font("宋體", Font.BOLD, 23);drawContent(type.toUpperCase(Locale.ROOT), graphics, circleX + 5, point.getY(), Color.WHITE, image.getWidth(), point, font);// 繪制背景 一行的后半部分--外部矩形框Color outerColor = new Color(Integer.parseInt("DDDDDD", 16));graphics.setColor(outerColor);int secondWidth = (int) ((1 - COLOR_WIDTH) * width);graphics.fillRect(point.getX() + firstWidth, point.getY(), secondWidth, LINE_HEIGHT);// 繪制背景 一行的后半部分---內部矩形框Color innerColor = new Color(Integer.parseInt("F4F4F4", 16));graphics.setColor(innerColor);graphics.fillRect(point.getX() + firstWidth + 1, point.getY() + 1, secondWidth - 2, LINE_HEIGHT - 2);//圖標int avatarHeight = avatar.getHeight() / 2;int avatarX = point.getX() + firstWidth + 31;graphics.drawImage(avatar, avatarX, point.getY() + 1 + (LINE_HEIGHT - avatarHeight) / 2, avatar.getWidth() / 2, avatarHeight, innerColor, null);//圖標 --文字int codTextX = avatarX + avatar.getWidth() / 3 + 33;font = new Font("宋體", Font.PLAIN, 20);drawContent(code, graphics, codTextX, point.getY(), Color.BLACK, image.getWidth(), point, font);point.setY(point.y + LINE_HEIGHT - 1);}private void drawCircle(Point point, Graphics2D graphics, int circleX) {Composite composite = graphics.getComposite();//透明度設置AlphaComposite instance = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f);graphics.setComposite(instance);graphics.setColor(Color.BLACK);graphics.fillOval(circleX, point.getY() + (LINE_HEIGHT - 32) / 2, 32, 32);//恢復原來的透明度graphics.setComposite(composite);}private void drawContent(String text, Graphics2D cs, int x, int y, Color color, int width, Point point, Font font) {//臨時將需要裁剪區域置空cs.setClip(null);//設置文本顏色cs.setColor(color);//設置文本字體cs.setFont(font);//文本抗鋸齒cs.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);cs.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);//為畫布添加文字,并居中FontMetrics fm = cs.getFontMetrics(font);int ascent = fm.getAscent();int descent = fm.getDescent();cs.drawString(text, x + 5, y + (LINE_HEIGHT - (ascent + descent)) / 2 + ascent);//恢復之前的裁剪區域cs.setClip(point.getX(), point.getY(), width - 2 * point.getX(), LINE_HEIGHT);}private byte[] toByteArray(BufferedImage image) throws IOException {// 輸出png圖片ByteArrayOutputStream os = new ByteArrayOutputStream();image.flush();ImageIO.write(image, "png", os);return os.toByteArray();}@Data@AllArgsConstructorpublic static class Margin {/*** 上*/private int top;/*** 底*/private int bottom;/*** 左*/private int left;/*** 右*/private int right;}@Data@AllArgsConstructorpublic static class Point {private int x;private int y;}}

?PS:生成的圖片如文頭,base64編碼如下圖

?

?但是在移植到docker容器中部署的時候,報以下錯誤

2024-06-25 16:26:31.019 [http-nio-10008-exec-7] ERROR com.a.mybatis.common.exception.RestfulExceptionHandler - 異常堆棧:
jakarta.servlet.ServletException: Handler dispatch failed: java.lang.UnsatisfiedLinkError: /opt/java/openjdk/lib/libfontmanager.so: Error loading shared library libfreetype.so.6: No such file or directory (needed by /opt/java/openjdk/lib/libfontmanager.so)at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1096)at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:974)at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1011)at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903)at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:705)at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:814)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:223)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)at com.github.xiaoymin.knife4j.extend.filter.basic.JakartaServletSecurityBasicAuthFilter.doFilter(JakartaServletSecurityBasicAuthFilter.java:55)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)at com.huanyu.common.config.filter.TokenFilter.doFilter(TokenFilter.java:58)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:177)at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:119)at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:400)at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:859)at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1734)at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)at java.base/java.lang.Thread.run(Unknown Source)
Caused by: java.lang.UnsatisfiedLinkError: /opt/java/openjdk/lib/libfontmanager.so: Error loading shared library libfreetype.so.6: No such file or directory (needed by /opt/java/openjdk/lib/libfontmanager.so)at java.base/jdk.internal.loader.NativeLibraries.load(Native Method)at java.base/jdk.internal.loader.NativeLibraries$NativeLibraryImpl.open(Unknown Source)at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(Unknown Source)at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(Unknown Source)at java.base/jdk.internal.loader.NativeLibraries.findFromPaths(Unknown Source)at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(Unknown Source)at java.base/java.lang.ClassLoader.loadLibrary(Unknown Source)at java.base/java.lang.Runtime.loadLibrary0(Unknown Source)at java.base/java.lang.System.loadLibrary(Unknown Source)at java.desktop/sun.font.FontManagerNativeLibrary$1.run(Unknown Source)at java.base/java.security.AccessController.doPrivileged(Unknown Source)at java.desktop/sun.font.FontManagerNativeLibrary.<clinit>(Unknown Source)at java.desktop/sun.font.SunFontManager$1.run(Unknown Source)at java.desktop/sun.font.SunFontManager$1.run(Unknown Source)at java.base/java.security.AccessController.doPrivileged(Unknown Source)at java.desktop/sun.font.SunFontManager.initStatic(Unknown Source)at java.desktop/sun.font.SunFontManager.<clinit>(Unknown Source)at java.base/java.lang.Class.forName0(Native Method)at java.base/java.lang.Class.forName(Unknown Source)at java.desktop/sun.font.FontManagerFactory$1.run(Unknown Source)at java.base/java.security.AccessController.doPrivileged(Unknown Source)at java.desktop/sun.font.FontManagerFactory.getInstance(Unknown Source)at java.desktop/java.awt.Font.getFont2D(Unknown Source)at java.desktop/java.awt.Font$FontAccessImpl.getFont2D(Unknown Source)at java.desktop/sun.font.FontUtilities.getFont2D(Unknown Source)at java.desktop/sun.java2d.SunGraphics2D.checkFontInfo(Unknown Source)at java.desktop/sun.java2d.SunGraphics2D.getFontInfo(Unknown Source)at java.desktop/sun.java2d.pipe.GlyphListPipe.drawString(Unknown Source)at java.desktop/sun.java2d.pipe.ValidatePipe.drawString(Unknown Source)at java.desktop/sun.java2d.SunGraphics2D.drawString(Unknown Source)

原因分析:

?Graphics2D類在執行文本寫入的時候,需要使用字體插件,因為當前的運行環境中沒有對應的?Error loading shared library libfreetype.so.6插件,因此就會報上述的錯誤。

經排查,博主使用的docker鏡像是精簡版本的,將一些不常用的功能代碼都去除了,因此會出現這樣那樣的問題,最終使用完全的jre17,解決了該問題,備查!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/35487.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/35487.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/35487.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java面試八股之JVM內存泄漏按照發生的方式可以分為哪幾類

JVM內存泄漏按照發生的方式可以分為哪幾類 常發性內存泄漏&#xff08;Frequent Memory Leak&#xff09; 這類內存泄漏發生的代碼會被頻繁執行&#xff0c;每次執行時都會導致一塊或多塊內存無法被回收。由于泄漏行為重復發生&#xff0c;故稱為常發性。這類泄漏通常比較容易…

下一代廣域網技術2:SRv6

2.SRv6 SR架構設計之初&#xff0c;就為SR數據平面設計了兩種實現方式&#xff1a;一種是SR-MPLS&#xff0c;其重用了MPLS數據平面&#xff0c;可以在現有IP/MPLS網絡上增量部署&#xff1b;另一種是SRv6&#xff0c;使用IPv6數據平面&#xff0c;基于IPv6路由擴展頭進行擴展…

Docker部署常見應用之Oracle數據庫

文章目錄 安裝部署參考文章 安裝部署 使用Docker安裝Oracle數據庫是一個相對簡便的過程&#xff0c;可以避免在本地環境中直接安裝Oracle數據庫的復雜性。 安裝Docker環境&#xff1a;確保你的系統上已經安裝了Docker&#xff0c;并且Docker服務正在運行。具體的安裝方法可以根…

使用North自部署圖床服務

圖床 圖床可以把圖片轉為鏈接&#xff0c;從而方便我們書寫、分享博客&#xff0c;目前圖床主要分為以下幾類: 利用 Git 倉庫存儲對象存儲&#xff08;OSS、COS、七牛云等&#xff09;免費公共圖床&#xff08;SM.MS、聚合圖床、ImgTP、Postimage等&#xff09; 但上述圖床都…

低應變復習題

1.比較臨塑荷載、臨界荷載和極限荷載的大小( ) A、臨塑荷載<臨界荷載<極限荷載 B、臨塑荷載>臨界荷載<極限荷載 C、臨塑荷載<臨界荷載>極限荷載 D、臨塑荷載>臨界荷載>極限荷載 參考答案:A 2.面關于低應變反射波法的描述,正確的是:( ) A、反射…

【雜記-淺談BGP邊界網關協議】

BGP邊界網關協議 一、BGP邊界網關協議概述二、BGP的特點及與IGP的區別三、BGP的路由屬性四、BGP協議中使用的報文 一、BGP邊界網關協議概述 1、BGP&#xff0c;Border Gateway Protocol&#xff0c;即邊界網關協議&#xff0c;是一種在自治系統&#xff08;AS&#xff09;之間…

Websocket實現方式二——注解方式

添加Websocket依賴 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dependency>根據ServerEndpoint注解注冊Websocket Configuration public class AgentWsConfig …

多項式回歸(Linear Regression)原理詳解及Python代碼示例

多項式回歸原理詳解 多項式回歸&#xff08;Polynomial Regression&#xff09;是線性回歸&#xff08;Linear Regression&#xff09;的一種擴展形式。它通過在輸入變量上添加高次項來擬合非線性關系。雖然多項式回歸本質上還是線性模型&#xff0c;但它允許模型在輸入特征的多…

if action和Switch之間該怎么選擇?

1. Switch 2. If及If Action Subsystem 3.結論 元素很多&#xff0c;用switch 元素少&#xff0c;用if或switch 如果...很多&#xff0c;用if

職業技能大賽引領下大數據專業實訓教學的改革研究

隨著信息化時代的加速發展&#xff0c;大數據專業作為新興的熱門領域&#xff0c;正日益成為高等職業教育體系中不可或缺的一部分&#xff0c;其承擔著為社會培養大批具有高素質應用技能的大數據技術人才的重任。職業技能大賽作為檢驗和提升學生技能水平的有效平臺&#xff0c;…

web學習筆記(六十九)vue2

1. vue2創建腳手架項目 &#xff08;1&#xff09;在cmd窗口輸入npm install -g vue/cli命令行&#xff0c;快速搭建腳手架。 &#xff08;2&#xff09; 創建vue2項目 &#xff08;3&#xff09; 選擇配置項目&#xff0c;最下面的選項是自己重新配置&#xff0c;第一次創建v…

使用mmdetection遇到的一些問題總結

【問題1】 No module named ‘mmcv._ext’ 應該安裝mmcv-full 而不是mmcv 【問題2】cannot import name ‘Config‘ from ‘mmcv‘ 原因是mmcv的版本太高兩種解決方案&#xff1a;1&#xff09;降低mmcv版本。2&#xff09;將 from mmcv import Config, DictAction 修改為 fro…

android 4大組件用法

在Android開發中&#xff0c;應用程序的主要組件包括Activity、Service、Broadcast Receiver和Content Provider。這些組件共同組成了Android應用的基本構架。以下是每個組件的詳細用法&#xff1a; 1. Activity Activity是Android應用的主要組成部分&#xff0c;代表一個用戶…

中電金信:向“新”而行—探索AI在保險領域的創新應用

大模型的應用已經滲透到各個領域&#xff0c;并展現出驚人的潛力。在自然語言處理方面&#xff0c;大模型用于機器翻譯、文本摘要、問答系統等&#xff1b;在計算機視覺領域&#xff0c;應用于圖像識別、目標檢測、視頻分析等&#xff1b;此外&#xff0c;大模型也應用于語音識…

使用nvm管理node版本及pnpm安裝

文章目錄 GithubWindows 環境Mac/Linux 使用腳本進行安裝或更新Mac/Linux 環境變量nvm 常用命令npm 常用命令npm 安裝 pnpmNode 歷史版本 Github https://github.com/nvm-sh/nvm Windows 環境 https://nvm.uihtm.com/nvm.html Mac/Linux 使用腳本進行安裝或更新 curl -o- …

名企架構師精講:Spring框架核心速覽

目錄 1. 課程概覽 2. 初識篇&#xff1a;Spring框架AOP&IOC案例詳解 課程內容3. 課程特色4.適用人群5. 你將收獲6. 學習建議 1. 課程概覽 本課程通過精選的兩篇深度文章和一套詳盡的視頻教程&#xff0c;全面而深入地解析并實踐了Spring框架的核心內容。 主要包含以下幾部…

VTable導出當前頁和導出所有頁數據

表格導出的是當前顯示的表格&#xff0c;如果是分頁表格想導出全部的數據話。有兩種方法可以實現 表格先顯示的全量數據&#xff0c;導出后再恢復當前頁。新建一個隱藏的表格實例顯示全量數據導出這個隱藏的表格實例。 下面是全量代碼&#xff1a; <template><div&…

快速創建條形熱力圖

Excel中的條件格式可以有效的凸顯數據特征&#xff0c;如下圖中B列所示。 現在需要使用圖表展現熱力條形圖&#xff0c;如下圖所示。由于顏色有多個過渡色&#xff0c;因此手工逐個設置數據條的顏色&#xff0c;基本上是不可能完成的任務&#xff0c;使用VBA代碼可以快速創建這…

git stash相關命令解釋

git stash 這個命令會保存你當前工作區和暫存區的所有更改到一個臨時的“stash”區域&#xff0c;然后使你的工作目錄和暫存區變得干凈&#xff08;即回到最近一次提交的狀態&#xff09;。 當你想要回到這個“stash”區域中的更改時&#xff0c;你可以使用 git stash list 來查…

SRE監控的四個黃金指標到底長啥樣?

一、監控的黃金信號 掌握系統運行狀態&#xff0c;了解組件、服務的可靠性和穩定性&#xff0c;需要借助監控系統收集指標、可視化數據&#xff0c;并在異常出現時進行操作提醒。那么監控的都要關注哪些呢&#xff1f;我們來了解一下監控的指標&#xff0c;即系統中衡量的最重…