java将svg转为base64png图片,去除透明区域

实现思路

ps:最终输出的为 base64 内容,访问的话字符串拼接开头内容:“data:image/png;base64,” + 结果

  1. svg 转 png
  2. 像素点判断 png 非透明区域位置
  3. png 转为 base64 字符串
    ps:由于我懒得清临时文件,上述所有 png 均为 BufferedImage

1. 导包

	<dependency>
	    <groupId>org.apache.xmlgraphics</groupId>
	    <artifactId>batik-transcoder</artifactId>
	    <version>1.16</version>
	</dependency>
	<dependency>
	    <groupId>org.apache.xmlgraphics</groupId>
	    <artifactId>batik-codec</artifactId>
	    <version>1.16</version>
	</dependency>

2. 业务代码

import java.awt.image.BufferedImage;
import java.awt.Graphics2D;
import java.io.*;
import java.util.Base64;
import javax.imageio.ImageIO;

import com.cdel.CommonConstant;
import lombok.extern.slf4j.Slf4j;
import org.apache.batik.transcoder.*;
import org.apache.batik.transcoder.image.PNGTranscoder;

@Slf4j
public class SVGToImageConverter {
    public static void main(String[] args) {
        String svgData = """
        这里是svg标签内容:<svg>xxxxxx</svg>
        """;

        String png = svg2Base64Png(svgData);
        System.out.println(png);
    }
    public static String svg2Base64Png(String svgData) {
        try {
            // 1. SVG 转 BufferImage
            BufferedImage image = svg2BufferImage(svgData);
            // 2. 裁剪照片
            image = handleImage(image);
            // 3. 返回base64图片
            return image2Base64(image);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private static BufferedImage handleImage(BufferedImage image) {
        int minX = image.getWidth(), minY = image.getHeight(), maxX = 0, maxY = 0;
        boolean hasNonTransparentPixel = false;

        for (int y = 0; y < image.getHeight(); y++) {
            for (int x = 0; x < image.getWidth(); x++) {
                // a r g b
                int pixel = image.getRGB(x, y);
                int alpha = (pixel >> 24) & 0xff;
                if (alpha != 0) {
                    hasNonTransparentPixel = true;
                    if (x < minX) {
                        minX = x;
                    }
                    if (y < minY) {
                        minY = y;
                    }
                    if (x > maxX) {
                        maxX = x;
                    }
                    if (y > maxY) {
                        maxY = y;
                    }
                }
            }
        }

        if (hasNonTransparentPixel && maxX >= minX && maxY >= minY) {
            int width = maxX - minX + 1;
            int height = maxY - minY + 1;
            BufferedImage cropped = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g = cropped.createGraphics();
            g.drawImage(image, 0, 0, width, height, minX, minY, maxX + 1, maxY + 1, null);
            g.dispose();
            log.info("图像裁剪完成,裁剪区域:({}, {}), 宽度:{}, 高度:{}", minX, minY, width, height);
            return cropped;
        } else {
            log.warn("未找到透明区域");
            return image;
        }
    }

    private static BufferedImage svg2BufferImage(String svgData) throws TranscoderException, IOException {
        // PNG转码器
        PNGTranscoder transcoder = new PNGTranscoder();
        // SVG输入
        TranscoderInput input = new TranscoderInput(new StringReader(svgData));
        ByteArrayOutputStream pngOutputStream = new ByteArrayOutputStream();
        TranscoderOutput output = new TranscoderOutput(pngOutputStream);
        transcoder.transcode(input, output);
        pngOutputStream.flush();

        ByteArrayInputStream pngInputStream = new ByteArrayInputStream(pngOutputStream.toByteArray());
        BufferedImage image = ImageIO.read(pngInputStream);

        pngOutputStream.close();
        pngInputStream.close();
        log.info("SVG 转 BufferedImage 成功");
        return image;
    }

    private static String image2Base64(BufferedImage image) throws IOException {
    	// 创建白色背景图
        BufferedImage backgroundImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB);
        Graphics2D g = backgroundImage.createGraphics();
        g.setColor(java.awt.Color.WHITE);
        g.fillRect(0, 0, backgroundImage.getWidth(), backgroundImage.getHeight());
        g.drawImage(image, 0, 0, null);
        g.dispose();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(backgroundImage , "png", baos);
        baos.flush();
        byte[] imageBytes = baos.toByteArray();
        baos.close();
        return Base64.getEncoder().encodeToString(imageBytes);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值