You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PNG转SVG转换报错:Invalid byte 1 of 1-byte UTF-8 sequence

问题:使用Apache Batik将PNG转SVG时出现UTF-8编码错误

我尝试通过以下Java代码使用Apache Batik的PNGTranscoder将PNG图片转换为SVG:

public class ImageToSVGConverterTool {

    public static void main(String[] args) {
        String inputImagePath = "C:\\Users\\path\\facebook.png"; // 替换为你的输入图片路径
        String outputSVGPath = "C:\\Users\\path\\OUTPUT\\output_image.svg"; // 替换为目标SVG输出路径
        //FileUtils.createNewFile(outputSVGPath);
        System.out.println(FileUtils.isImageFile(outputSVGPath));
        System.out.println(new File(outputSVGPath).isFile());
        try {
            convertImageToSVG(inputImagePath, outputSVGPath);
            System.out.println("Image converted to SVG successfully.");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void convertImageToSVG(String inputImagePath, String outputSVGPath)
            throws IOException, TranscoderException {
        File inputFile = new File(inputImagePath);
        File outputFile = new File(outputSVGPath);

        ImageTranscoder transcoder = new PNGTranscoder(); // 输入为PNG时改用PNGTranscoder
        //ImageTranscoder transcoder = new JPEGTranscoder(); // 输入为PNG时改用PNGTranscoder

        // 设置输出文件
        FileOutputStream outputStream = new FileOutputStream(outputFile);
        TranscoderOutput transcoderOutput = new TranscoderOutput(outputStream);

        // 设置输入图片
        TranscoderInput transcoderInput = new TranscoderInput(inputFile.toURI().toString());

        // 执行转换
        transcoder.transcode(transcoderInput, transcoderOutput);

        // 关闭输出流
        outputStream.close();
    }
}

输入文件是从网上下载的facebook.png,输出SVG文件为空,且运行时出现如下错误:

org.apache.batik.transcoder.TranscoderException: null
Enclosed Exception:
Invalid byte 1 of 1-byte UTF-8 sequence.
    com.uml.svg.tools.ImageToSVGConverterTool.convertImageToSVG(ImageToSVGConverterTool.java:50)
    at com.uml.svg.tools.ImageToSVGConverterTool.main(ImageToSVGConverterTool.java:24)
Caused by: org.apache.batik.dom.util.SAXIOException: Invalid byte 1 of 1-byte UTF-8 sequence.
    
Caused by: org.xml.sax.SAXParseException; systemId: file:/C:/Users/ravmaddi/Desktop/facebook.png; lineNumber: 1; columnNumber: 1; Invalid byte

请问该如何解决此问题?


解决方案

1. 错误根源:转码方向完全搞反了

Apache Batik的PNGTranscoder核心功能是把SVG文件转成PNG位图,而非将PNG转成SVG。它内部会用SAX解析器读取输入的SVG(XML格式),但你传入的是PNG二进制文件,解析器试图把二进制当作UTF-8编码的XML处理,自然会抛出编码错误。

2. 正确实现方式

根据需求分两种场景处理:

场景一:将PNG嵌入SVG(最简单方案)

如果只是需要生成一个包含该PNG的SVG文件(用<image>标签引用或嵌入),可以直接手动构建SVG内容,无需使用Batik:

import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
import java.io.File;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;

public class ImageToSVGConverterTool {
    public static void main(String[] args) {
        String inputImagePath = "C:\\Users\\path\\facebook.png";
        String outputSVGPath = "C:\\Users\\path\\OUTPUT\\output_image.svg";
        try {
            embedPngIntoSvg(inputImagePath, outputSVGPath);
            System.out.println("Image embedded into SVG successfully.");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void embedPngIntoSvg(String inputImagePath, String outputSVGPath) throws IOException {
        // 读取PNG并转为Base64(嵌入SVG,无需外部文件依赖)
        byte[] imageBytes = Files.readAllBytes(Paths.get(inputImagePath));
        String base64Image = Base64.getEncoder().encodeToString(imageBytes);
        
        // 获取图片原始尺寸
        BufferedImage img = ImageIO.read(new File(inputImagePath));
        int width = img.getWidth();
        int height = img.getHeight();
        
        // 构建标准SVG内容
        String svgContent = String.format("""
                <svg xmlns="http://www.w3.org/2000/svg" width="%d" height="%d" viewBox="0 0 %d %d">
                    <image href="data:image/png;base64,%s" width="%d" height="%d"/>
                </svg>
                """, width, height, width, height, base64Image, width, height);
        
        // 写入SVG文件
        try (FileOutputStream outputStream = new FileOutputStream(outputSVGPath)) {
            outputStream.write(svgContent.getBytes("UTF-8"));
        }
    }
}

场景二:将PNG矢量化(转为矢量图形)

如果需要把PNG的像素内容转为SVG的矢量路径(比如线条、形状),Batik不支持这个功能,需要使用其他工具:

  • 开源工具:可以调用Potrace(命令行工具)或Inkscape的命令行接口来完成矢量化
  • 第三方库:比如使用Apache Commons Imaging配合自定义逻辑,或商业矢量转换库

内容的提问来源于stack exchange,提问作者Sun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 13:00:37