欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java使用Graphics2D繪制SVG和PNG的方法

 更新時(shí)間:2023年06月01日 10:44:19   作者:iiopsd  
Java提供了許多圖形處理類和方法,如Graphics2D、AffineTransform、Stroke等,這些都可以用于繪制SVG圖像,Graphics2D是Java中用于繪制2D圖形的類,本文給大家介紹如何使用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)文章

最新評(píng)論