实现思路
ps:最终输出的为 base64 内容,访问的话字符串拼接开头内容
:“data:image/png;base64,” + 结果
- svg 转 png
- 像素点判断 png 非透明区域位置
- 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);
}
}