一、svg文件

1.1 svg介绍

SVG 意为可缩放矢量图形(Scalable Vector Graphics), 使用 XML 格式定义图像。因此对svg文件的操作,可以看做对xml文件的解析。svg基础知识可以参考svg教程,在此不做过多赘述。

1.2 svg文件操作

1.2.1 获取svg文件源码

读取svg文件并转换为字符串类型,可得到源码

public String svgOriginFile(MultipartFile file) throws IOException {
        if (file != null) {
            InputStream fileInput = file.getInputStream();
            byte[] inputByte = new byte[fileInput.available()];
            fileInput.read(inputByte);
            String originFile = new String(inputByte, "UTF-8");
            log.info("Get svg originFile [{}]", originFile);
            fileInput.close();
            return originFile;
        }
        return null;
    }

1.2.2 获取svg文件宽高

读取svg的xml文件,获取svg文件的width、height属性

public Float svgSize(String originFile, String lengthName) throws IOException {
        if (originFile != null && lengthName != null) {
            Document doc = svgDocument(originFile);
            Element element = doc.getDocumentElement();
            String length = lengthReg(element.getAttribute(lengthName));
            if (length == "" || length == null) {
                int num = lengthName.equals("width") ? 2 : 3;
                String viewBox = element.getAttribute("viewBox");
                length = viewBox.split(" ")[num];
            }
            log.info("Svg {} size is {}", lengthName, length);
            return Float.parseFloat(length);
        }
        return null;
    }


public Document svgDocument(String originFile) throws IOException {
        byte[] bytes = originFile.getBytes("utf-8");
        ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
        String parser = XMLResourceDescriptor.getXMLParserClassName();
        SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parser);
        Document doc = f.createDocument(null, inputStream);
        return doc;
    }

public String lengthReg(String str) {
        //用正则表达式
        String reg = "[^0-9]";
        //Pattern类的作用在于编译正则表达式后创建一个匹配模式.
        Pattern p = Pattern.compile(reg);
        //Matcher类使用Pattern实例提供的模式信息对正则表达式进行匹配
        Matcher m = p.matcher(str);
        return m.replaceAll("").trim();
    }

1.2.3 获取svg文件颜色

读取svg的xml文件,获取svg文件的fill属性

public String selectColorByOriginFile(String originFile) throws IOException {
        if (originFile != null) {
            Document doc = svgDocument(originFile);
            Element element = doc.getDocumentElement();
            NodeList list = element.getElementsByTagName("path");
            Element colorElement = (Element) list.item(0);
            String color = colorElement.getAttribute("fill");
            log.info("Get svg color [{}]", color);
            return color;
        }
        return null;
    }

1.2.4 svg文件着色

读取svg的xml文件,更改svg文件的fill属性,写入xml文件

public String svgColoration(String originFile, String color) throws  TransformerException, IOException {
        if (originFile != null && color != null) {
            Document doc = svgDocument(originFile);
            Element element = doc.getDocumentElement();
            NodeList list = element.getElementsByTagName("path");
            for (int i = 0; i < list.getLength(); i++) {
                Element colorElement = (Element) list.item(i);
                colorElement.setAttribute("fill", color);
            }
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            StringWriter buffer = new StringWriter();
            transformer.setOutputProperty(OutputKeys.STANDALONE, "no");
            transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, doc.getDoctype().getPublicId());
            transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, doc.getDoctype().getSystemId());
            transformer.transform(new DOMSource(element), new StreamResult(buffer));
            log.info("Get colorized  svg file [{}]", buffer.toString());
            return buffer.toString();
        }
        return  null;
    }

二、svg转png

2.1 Batik介绍

Batik是为想使用svg格式图片来实现各种功能的应用程序和Applet提供的一个基于java的工具包。工程创建的目的是为开发者提供一系列可以结合或单独使用来支持特殊的svg解决方案的核心模块。模块主要SVGParser、SVGGernerator、SVGDOM。Batik工程的其他目的是使它具有高度的扩展性,举个例子,Batik允许开发者使用自定义的SVG元素。即使工程的目标是提供一系列核心模块,但是还是提供了一个完整的SVG浏览器,以便证实各个模块的有效性和交互性。

简单来说:Batik其实就是将对svg的操作分为了一个个核心模块,这主要包括SVGParser(解释器),SVGGernerator(生成器),SVGDOM(DOM元素)。SVGParser解释器主要是对SVG的xml文件节点的解析,SVGGernerator(生成器)可以通过生成一个svg文件,SVGDOM能够建立SVGDOM节点,并在每一个Element上添加不同的属性。

官方地址:https://xmlgraphics.apache.org/batik/

2.2 引入java batik依赖

    
		<properties>
       		 <batik.version>1.11</batik.version>
    	</properties>  
      

		<dependency>
            <groupId>org.apache.xmlgraphics</groupId>
            <artifactId>batik-svggen</artifactId>
            <version>${batik.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.xmlgraphics</groupId>
            <artifactId>batik-transcoder</artifactId>
            <version>${batik.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.xmlgraphics</groupId>
            <artifactId>batik-codec</artifactId>
            <version>${batik.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.xmlgraphics</groupId>
            <artifactId>xmlgraphics-commons</artifactId>
            <version>2.3</version>
        </dependency>

2.3 svg转png

入参为svg源文件码

 public  InputStream svgToPng(String originFile, Float multiple) throws IOException, TranscoderException {
        if (originFile != null && multiple != null) {
            long st = System.currentTimeMillis();
            ByteArrayOutputStream pngStream = new ByteArrayOutputStream();
            InputStream pngInput;
                byte[] bytes = originFile.getBytes("utf-8");
                TranscoderInput input = new TranscoderInput(new ByteArrayInputStream(bytes));
                PNGTranscoder t = new PNGTranscoder();
          //获取宽高,动态放大
                Float width = svgSize(originFile, "width");
                Float height = svgSize(originFile, "height");
                t.addTranscodingHint(PNGTranscoder.KEY_WIDTH, width * multiple);
                t.addTranscodingHint(PNGTranscoder.KEY_HEIGHT, height * multiple);
          //格式转换
                t.transcode(input, new TranscoderOutput(pngStream));
                byte[] outByte = pngStream.toByteArray();
                pngInput = new ByteArrayInputStream(outByte);
                long cost = System.currentTimeMillis() - st;
                log.info("SvgToPng success, cost time {} ms", cost);
                    pngStream.close();
            return pngInput;
        } else {
            return null;
        }
    }

入参为svg文件

    public static void convertToPngByFile(String filePath, String pngFilePath,Map<String, String> map)
            throws IOException, TranscoderException {
        File file = new File(pngFilePath);
        FileOutputStream outputStream = null;
        try {
            file.createNewFile();
            outputStream = new FileOutputStream(file);
            convertToPngByFile(filePath, outputStream,map);
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
     
    public static void convertToPngByFile(String path, OutputStream outputStream,Map<String, String> map)
            throws TranscoderException, IOException {
        try {
            File file = new File(path);
            String parser = XMLResourceDescriptor.getXMLParserClassName();
            SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parser);
            Document doc = f.createDocument(file.toURI().toString());
            for (int i = 1; i <=map.size()/3; i++) {
                Element e = doc.getElementById(map.get("id"+i));
                System.out.println(map.get("name"+i));
                e.setAttribute(map.get("name"+i), map.get("value"+i));
            }
            PNGTranscoder t = new PNGTranscoder();
            TranscoderInput input = new TranscoderInput(doc);
            TranscoderOutput output = new TranscoderOutput(outputStream);
            t.transcode(input, output);
            outputStream.flush();
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

三、png转jpg

3.1 命令行转换

cwebp [options] input_file -o output_file.webp

参考:

java服务器端图片转换webp以及批量转换webp脚本

cwebp 命令大全

官方文档

3.2 第三方jar包转换

webp-imageio

3.2.1 导入maven依赖

由于公司私服有该依赖,故无需手动下载引入依赖,手动导入方式可参考文末链接

				<dependency>
            <groupId>com.github.nintha</groupId>
            <artifactId>webp-imageio-core</artifactId>
            <version>0.1.3</version>
        </dependency>

3.2.2 调用接口

public void pngToWebp(InputStream pngInput, String outputWebpPath) throws IOException {
        if (pngInput == null && outputWebpPath == null) {
            return;
        }
        long st = System.currentTimeMillis();
        BufferedImage image = ImageIO.read(pngInput);
        ImageWriter writer = ImageIO.getImageWritersByMIMEType("image/webp").next();
        WebPWriteParam writeParam = new WebPWriteParam(writer.getLocale());
        writeParam.setCompressionMode(writeParam.MODE_EXPLICIT);
        writeParam.setCompressionType("Lossless");
        writer.setOutput(new FileImageOutputStream(new File(outputWebpPath)));
        writer.write(null, new IIOImage(image, null, null), writeParam);
        long cost = System.currentTimeMillis() - st;
        log.info("PngToWebp success, cost time {} ms", cost);
    }

参考:

官方文档

https://blog.csdn.net/xu_san_duo/article/details/79085718

https://www.jb51.net/article/147135.htm

https://segmentfault.com/a/1190000016324137

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐