如何在Android上显示wmf的文件

菜鸟进场,方圆十里,寸草不生

最近定制化一个app,需要显示wmf的文件,但是Android上无法对这种文件的直接显示,所以就需要对文件进行一个转换,网上对这方面的需求很少,所以简单的记录一下,就讲讲这里面的坑。

1、思路
首先,wmf是一种矢量图,而Android上说到矢量图想到什么呢?当然是svg图了,所以基本的思路就是将wmf转换为svg,然后再在Android上显示。

2、流程
(1)先通过jar包将wmf的图转化为svg,使用jar包:wmf2svg-0.9.6.jar
https://download.csdn.net/download/version1_0/10765431
使用代码:

  /**
 * @param file   wmf文件的位置
 * @param dest   转换出来的svg文件的保存位置
 */
  private void convert(String file, String dest) throws Exception {
        InputStream in = new FileInputStream(file);
        WmfParser parser = new WmfParser();
        final SvgGdi gdi = new SvgGdi(false);
        parser.parse(in, gdi);
        Document doc = gdi.getDocument();
        OutputStream out = new FileOutputStream(dest);
        if (dest.endsWith(".svgz")) {
            out = new GZIPOutputStream(out);
        }
        output(doc, out);
    }


    private void output(Document doc, OutputStream out) throws Exception {
        TransformerFactory factory = TransformerFactory.newInstance();
        Transformer transformer = factory.newTransformer();
        transformer.setOutputProperty(OutputKeys.METHOD, "xml");
        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, "-//W3C//DTD SVG 1.0//EN");
        transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd");
        transformer.transform(new DOMSource(doc), new StreamResult(out));
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        transformer.transform(new DOMSource(doc), new StreamResult(bos));
        out.flush();
        out.close();
    }

备注:这里转换出来的文件在浏览器上已经可以访问了,但是在Android上不能访问。通过网上查询得知,这个转换出来的文件格式其实是svgz,这个svgz格式其实是svg的zip压缩包,但是这个压缩方式并不是普通的压缩方式,而是gzip方式压缩,需要解压。

(2)解压缩(这里附一个gzip格式压缩包的工具类)

public class GzipUtils {
    public static final int BUFFER = 1024;
    public static final String EXT = ".gz";

    /**
     * 数据压缩
     */
    public static byte[] compress(byte[] data) throws Exception {
        ByteArrayInputStream bais = new ByteArrayInputStream(data);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        // 压缩
        compress(bais, baos);
        byte[] output = baos.toByteArray();
        baos.flush();
        baos.close();
        bais.close();
        return output;
    }

    /**
     * 文件压缩
     */
    public static void compress(File file) throws Exception {
        compress(file, true);
    }

    /**
     * 文件压缩
     */
    public static void compress(File file, boolean delete) throws Exception {
        FileInputStream fis = new FileInputStream(file);
        FileOutputStream fos = new FileOutputStream(file.getPath() + EXT);
        compress(fis, fos);
        fis.close();
        fos.flush();
        fos.close();
        if (delete) {
            file.delete();
        }
    }

    /**
     * 数据压缩
     */
    public static void compress(InputStream is, OutputStream os) throws Exception {
        GZIPOutputStream gos = new GZIPOutputStream(os);
        int count;
        byte data[] = new byte[BUFFER];
        while ((count = is.read(data, 0, BUFFER)) != -1) {
            gos.write(data, 0, count);
        }
        gos.finish();
        gos.flush();
        gos.close();
    }

    /**
     * 文件压缩
     */
    public static void compress(String path) throws Exception {
        compress(path, true);
    }

    /**
     * 文件压缩
     */
    public static void compress(String path, boolean delete) throws Exception {
        File file = new File(path);
        compress(file, delete);
    }

    /**
     * 文件压缩
     */
    public static void compress(String inputFileName, String outputFileName) throws Exception {
        FileInputStream inputFile = new FileInputStream(inputFileName);
        FileOutputStream outputFile = new FileOutputStream(outputFileName);
        compress(inputFile, outputFile);
        inputFile.close();
        outputFile.flush();
        outputFile.close();
    }

    /**
     * 数据解压缩
     */
    public static byte[] decompress(byte[] data) throws Exception {
        ByteArrayInputStream bais = new ByteArrayInputStream(data);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        // 解压缩
        decompress(bais, baos);
        data = baos.toByteArray();
        baos.flush();
        baos.close();
        bais.close();
        return data;
    }

    /**
     * 文件解压缩
     */
    public static void decompress(File file) throws Exception {
        decompress(file, true, null);
    }

    /**
     * 文件解压缩
     */
    public static void decompress(File file, boolean delete, String outPath) throws Exception {
        FileInputStream fis = new FileInputStream(file);
        FileOutputStream fos = null;
        if (outPath == null || outPath == "") {
            fos = new FileOutputStream(file.getPath().replace(EXT, ""));
        } else {
            File files = new File(outPath);
            //判断文件是否存在,不存在,则创建
            if(!files.exists()){
                files.mkdirs();
            }
            //文件输出流参数中,需要指定文件解压后的文件名,这里,用文件的原名称
            fos = new FileOutputStream(outPath + File.separator + file.getName().replace(EXT, ""));
        }
        decompress(fis, fos);
        fis.close();
        fos.flush();
        fos.close();
        if (delete) {
            file.delete();
        }
    }

    /**
     * 文件解压缩
     */
    public static void decompress(String inputFileName, String outputFileName) throws Exception {
        FileInputStream inputFile = new FileInputStream(inputFileName);
        FileOutputStream outputFile = new FileOutputStream(outputFileName);
        decompress(inputFile, outputFile);
        inputFile.close();
        outputFile.flush();
        outputFile.close();
    }

    /**
     * 数据解压缩
     */
    public static void decompress(InputStream is, OutputStream os) throws Exception {
        GZIPInputStream gis = new GZIPInputStream(is);
        int count;
        byte data[] = new byte[BUFFER];
        while ((count = gis.read(data, 0, BUFFER)) != -1) {
            os.write(data, 0, count);
        }
        gis.close();
    }

    /**
     * 文件解压缩
     */
    public static void decompress(String path) throws Exception {
        decompress(path, true, null);
    }

    /**
     * 文件解压缩(解压单个文件)
     */
    public static void decompress(String path, boolean delete, String outPath) throws Exception {
        File file = new File(path);
        decompress(file, delete, outPath);
    }
}

(3)、将svg图显示到Android上,目前网络上有直接显示svg图片的框架,而不需要通过Android studio自带的插件进行转换,这个框架就是:

	//直接展示svg格式的图片
    implementation 'com.pixplicity.sharp:library:1.1.0'

使用方式:

				//展示到photoview
                Sharp.loadFile(new File(file3) + ".1.svg").into(ivMap);

备注:到目前为止,可能有些svg图已经能够显示了,但是还有一些无法进行显示,原因是svg图里面可能带有style属性,而这个框架无法识别这个属性,就需要将这个属性里面的东西都设置到svg的文件中。(如果不理解的可以通过txt将svg打开,就知道什么原因了)
我这里写了一个,可能不是很规范,但能用吧,就先用着。

/**
 * 将style文件放到
 */
private void setStyle(File file) {
    if (!file.exists() && file.isDirectory()) {
        return;
    }

    BufferedWriter bw = null;
    BufferedReader br = null;
    try {
        br = new BufferedReader(new FileReader(file));
        File outFile = new File(file.getAbsolutePath() + ".1.svg");
        bw = new BufferedWriter(new FileWriter(outFile));
        //字符数组循环读取
        String style = "";
        boolean flag = false;
        String str = null;
        while ((str = br.readLine()) != null) {
            bw.write(str + "\n");
            if (str.indexOf("style") != -1) {
                flag = !flag;
            }
            if (flag) {
                style += str;
            }
            if (!flag && !TextUtils.isEmpty(style)) {
                break;
            }
        }

        Map<String, String> map = new HashMap();
        //去除里面的空格和换行
        style = style.replaceAll("\n", "");
        style = style.replaceAll(" ", "");
        if (!TextUtils.isEmpty(style)) {
            //切出所有的属性
            String[] styles = style.split(">");
            if (!TextUtils.isEmpty(styles[1])) {
                String[] styles1 = styles[1].split("<");
                if (!TextUtils.isEmpty(styles1[0])) {
                    //按.将所有的属性隔开
                    String[] styles2 = styles1[0].split("\\.");
                    for (int i = 0; i < styles2.length; i++) {
                        String data = styles2[i];
                        if (!TextUtils.isEmpty(data)) {
                            //按大括号切出属性值
                            String[] data1 = data.split("\\{");
                            String[] data2 = data1[1].split("\\}");
                            //转换属性的文件样式
                            String value = data2[0].replaceAll(":", "=\"");
                            value = value.replaceAll(";", "\" ");
                            map.put(data1[0], value);
                        }
                    }
                }
            }
        }

        //写出到磁盘
        str = null;
        while ((str = br.readLine()) != null) {
            if (str.indexOf("class") != -1) {
                //去掉以前的class属性标识
                String[] str1 = str.split("\"");
                String[] type = str1[1].split(" ");
                str = str.replaceAll("class=\"", "");

                for (int i = 0; i < type.length; i++) {
                    String style1 = map.get(type[i]);
                    if (!TextUtils.isEmpty(style1)) {
                        str = str.replaceAll(type[i] + "\"", style1);
                        str = str.replaceAll(type[i], style1);
                    }
                }
            }
            bw.write(str + "\n");
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            if (bw != null) {
                bw.close();
            }
            if (br != null) {
                br.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

以上,wmf的文件就可以在Android上展示了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值