Java使用Graphics2D繪制SVG和PNG的方法
前言
emmm… 有個(gè)需求,需要根據(jù)信息生成svg,因?yàn)榭紤]到樣式一致性的問題最終決定有服務(wù)端來生成svg。
Java提供了許多圖形處理類和方法,如Graphics2D、AffineTransform、Stroke等,這些都可以用于繪制SVG圖像。
Graphics2D介紹
Graphics2D是Java中用于繪制2D圖形的類,它是Graphics類的子類,提供了更多的圖形繪制方法和屬性。在Java中,可以使用Graphics2D來創(chuàng)建各種類型的2D圖形,例如直線、矩形、圓形、弧形等。
Graphics2D類中一些常用的方法包括:
drawLine(int x1, int y1, int x2, int y2):繪制一條直線。
drawRect(int x, int y, int width, int height):繪制一個(gè)矩形。
fillRect(int x, int y, int width, int height):填充一個(gè)矩形。
drawOval(int x, int y, int width, int height):繪制一個(gè)橢圓或圓形。
fillOval(int x, int y, int width, int height):填充一個(gè)橢圓或圓形。
drawArc(int x, int y, int width, int height, int startAngle, int arcAngle):繪制一個(gè)弧形。
fillArc(int x, int y, int width, int height, int startAngle, int arcAngle):填充一個(gè)弧形。
drawString(String str, int x, int y):繪制一個(gè)字符串。
setPaint(Paint paint):設(shè)置繪制顏色。
setStroke(Stroke s):設(shè)置線條樣式(粗細(xì)、虛線等)。
rotate(double theta):旋轉(zhuǎn)坐標(biāo)系。
translate(double tx, double ty):平移坐標(biāo)系。
入門使用
maven引入依賴:
<dependency> <groupId>org.jfree</groupId> <artifactId>jfreesvg</artifactId> <version>3.4</version> </dependency>
使用Graphics2D類需要先獲取Graphics2D對(duì)象,可以通過將Graphics對(duì)象向下轉(zhuǎn)型為Graphics2D對(duì)象或通過創(chuàng)建BufferedImage對(duì)象來獲取。例如:
@SneakyThrows @Test public void t2() { int width = 700; int height = 500; SVGGraphics2D g2 = new SVGGraphics2D(width, height); // 設(shè)置字體和顏色 Font font = new Font("SFProText", Font.BOLD, 96); g2.setColor(Color.BLACK); g2.setFont(font); // 畫一條直線,起點(diǎn)坐標(biāo)為(100,100),終點(diǎn)坐標(biāo)為(10,20) g2.drawLine(100, 100, 10, 20); // 繪制一個(gè)矩形,左上角坐標(biāo)為(15,10),寬為10,高為20 g2.drawRect(15, 10, 10, 20); // 繪制一個(gè)圓形,圓心坐標(biāo)為(30,25),半徑為55 g2.drawOval(30, 25, 55, 55); // 繪制一個(gè)圓弧,圓心坐標(biāo)為(90,25),半徑為50,起始角度為0,終止角度為90度 g2.drawArc(90, 25, 50, 50, 0, 90); // 填充一個(gè)矩形,左上角坐標(biāo)為(150,100),寬為10,高為20 g2.fillRect(150, 100, 10, 20); // 保存svg到本地文件 InputStream inputStream = new ByteArrayInputStream(g2.getSVGDocument().getBytes()); try (FileOutputStream outputStream = new FileOutputStream(new File("C:\Users\Administrator\Downloads\1test.svg"))) { byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } } }
生成的svg如下圖所示:
進(jìn)階
現(xiàn)在我們?cè)囍O(shè)計(jì)一張名片,其中包含logo,姓名和聯(lián)系方式等信息,居中顯示。在寫入字符串的時(shí)候,如果字符串要居中,都需要根據(jù)字體和字符串去獲取字符串寬度,然后計(jì)算x,y點(diǎn)的位置。
文字的原點(diǎn)坐標(biāo)不同于一般圖形在右上角,如果需要將文字準(zhǔn)確的繪制到指定位置,需要了解文字的原點(diǎn)坐標(biāo)位置。如下圖所示,文本框的原點(diǎn)x坐標(biāo)位于文本框最左側(cè),y坐標(biāo)則位于基線上?;€以上為asent,基線以下為decent。為什么會(huì)有基線這個(gè)概念,可能會(huì)讓人產(chǎn)生疑惑,實(shí)際上是有原因的。實(shí)際上基線相同的文字,即使字體大小不一樣,繪制出來的結(jié)果是文本底部對(duì)齊的。 因?yàn)槲淖值撞窟€有一部分留白,因此文字底部對(duì)齊不是基于底部坐標(biāo)對(duì)齊,而是進(jìn)行基線對(duì)齊。
實(shí)現(xiàn)代碼如下:
@SneakyThrows @Test public void t2() { int width = 400; int height = 600; SVGGraphics2D g2 = new SVGGraphics2D(width, height); g2.setColor(new Color(168, 252, 229)); // 填充一個(gè)矩形,左上角坐標(biāo)為(150,100),寬為10,高為20 g2.fillRect(0, 0, width, height); Font font = new Font("SFProText", Font.BOLD, 40); g2.setColor(Color.BLACK); g2.setFont(font); String companyLogo = "https://xxx.jpg"; URL companyLogoUrl = new URL(companyLogo); BufferedImage image = ImageIO.read(companyLogoUrl); g2.drawImage(image, 100, 64, 200, 120, null); FontDesignMetrics metrics = FontDesignMetrics.getMetrics(font); String name = "張三三三三"; // 計(jì)算位置 int startX = (width - metrics.stringWidth(name)) / 2; int startY = 300 + metrics.getAscent(); g2.drawString(name, startX, startY); String phone = "55555555555"; startX = (width - metrics.stringWidth(phone)) / 2; startY = 400 + metrics.getAscent(); g2.drawString(phone, startX, startY); g2.dispose(); InputStream inputStream = new ByteArrayInputStream(g2.getSVGDocument().getBytes()); try (FileOutputStream outputStream = new FileOutputStream(new File("C:\Users\Administrator\Downloads\1test.svg"))) { byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } } }
SVG轉(zhuǎn)JPG
pom.xml增加依賴:
<!--svg2png--> <dependency> <groupId>org.apache.xmlgraphics</groupId> <artifactId>batik-all</artifactId> <version>1.14</version> </dependency> <dependency> <groupId>org.apache.xmlgraphics</groupId> <artifactId>fop</artifactId> <version>2.7</version> </dependency>
轉(zhuǎn)換代碼:
// svg2jpg ImageTranscoder transcoder = new JPEGTranscoder(); TranscoderInput input = new TranscoderInput(inputStream); OutputStream out = Files.newOutputStream(new File("C:\Users\Administrator\Downloads\557.jpg").toPath()); TranscoderOutput output = new TranscoderOutput(out); //轉(zhuǎn)換 transcoder.transcode(input, output);
繪制PNG
可以直接選擇繪制PNG圖片,節(jié)省轉(zhuǎn)換過程中的各種問題,方法都是一樣的,只是操作的對(duì)象有點(diǎn)不同,
通過BufferedImage去創(chuàng)建繪圖對(duì)象:
int width = 400; int height = 600; BufferedImage tarImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D g2 = tarImage.createGraphics();
完整實(shí)現(xiàn)代碼:
@SneakyThrows @Test public void t3() { int width = 400; int height = 600; BufferedImage tarImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); val g2 = tarImage.createGraphics(); g2.setColor(new Color(168, 252, 229)); // 填充一個(gè)矩形,左上角坐標(biāo)為(150,100),寬為10,高為20 g2.fillRect(0, 0, width, height); Font font = new Font("SFProText", Font.BOLD, 40); g2.setColor(Color.BLACK); g2.setFont(font); String companyLogo = "https://xxx.jpg"; URL companyLogoUrl = new URL(companyLogo); BufferedImage image = ImageIO.read(companyLogoUrl); g2.drawImage(image, 100, 64, 200, 120, null); FontDesignMetrics metrics = FontDesignMetrics.getMetrics(font); String name = "張三三三三"; int startX = (width - metrics.stringWidth(name)) / 2; int startY = 300 + metrics.getAscent(); g2.drawString(name, startX, startY); String phone = "55555555555"; startX = (width - metrics.stringWidth(phone)) / 2; startY = 400 + metrics.getAscent(); g2.drawString(phone, startX, startY); // 繪制圖片 g2.dispose(); // tarImage轉(zhuǎn)inputStream String IMAGE_TYPE = "png"; ByteArrayOutputStream os = new ByteArrayOutputStream(); ImageIO.write(tarImage, IMAGE_TYPE, os); InputStream inputStream = new ByteArrayInputStream(os.toByteArray()); try (FileOutputStream outputStream = new FileOutputStream(new File("C:\Users\Administrator\Downloads\2test.png"))) { byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } } }
繪制圖片效果如下:
我們可以看到圖片和文本信息鋸齒狀比較明顯,可以通過增加圖片質(zhì)量參數(shù)來改善質(zhì)量。
/** * 設(shè)置圖片質(zhì)量(抗鋸齒等) * @param */ public void setImagQuality(Graphics2D g2) { RenderingHints qualityHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); qualityHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); qualityHints.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); qualityHints.put(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); qualityHints.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE); g2.setRenderingHints(qualityHints); }
左邊未設(shè)置圖片質(zhì)量,右邊設(shè)置了圖片質(zhì)量,對(duì)比效果如下所示:
以上就是Java使用Graphics2D繪制SVG和PNG的方法的詳細(xì)內(nèi)容,更多關(guān)于Java 繪制SVG和PNG的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java調(diào)用阿里身份證實(shí)現(xiàn)驗(yàn)證接口
這篇文章主要為大家詳細(xì)介紹了Java如何調(diào)用阿里身份證實(shí)現(xiàn)驗(yàn)證接口,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以了解一下2023-06-06解決在啟動(dòng)eclipse的tomcat進(jìn)行訪問時(shí)出現(xiàn)404問題的方法
這篇文章主要介紹了解決在啟動(dòng)eclipse的tomcat進(jìn)行訪問時(shí)出現(xiàn)404問題的方法,感興趣的小伙伴們可以參考一下2016-04-04MybatisX-Generator自動(dòng)代碼生成插件教程
這篇文章主要介紹了MybatisX-Generator自動(dòng)代碼生成插件教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04詳細(xì)聊一聊java語言中的package和import機(jī)制
這篇文章主要給大家介紹了關(guān)于java語言中package和import機(jī)制的相關(guān)資料,Java中的package是指將相關(guān)的類組織在一起的一種機(jī)制,它可以用來避免命名沖突,也可以方便地管理和維護(hù)代碼,需要的朋友可以參考下2024-01-01解決使用@Value(${×××))從properties文件取值的坑
這篇文章主要介紹了解決使用@Value(${×××))從properties文件取值的坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07文件路徑正確,報(bào)java.io.FileNotFoundException異常的原因及解決辦法
這篇文章主要介紹了文件路徑正確,報(bào)java.io.FileNotFoundException異常的原因及解決辦法的相關(guān)資料,需要的朋友可以參考下2016-04-04SpringBoot?Web開發(fā)之請(qǐng)求響應(yīng)、分層解耦問題記錄
在?Spring?Boot?的?Web?請(qǐng)求響應(yīng)處理中,Servlet?起著關(guān)鍵的作用,Servlet?是?Java?Web?開發(fā)中的基本組件,主要負(fù)責(zé)處理客戶端的請(qǐng)求并生成響應(yīng),這篇文章主要介紹了SpringBoot?Web開發(fā)之請(qǐng)求響應(yīng),分層解耦,需要的朋友可以參考下2024-08-08