如何在Android上显示wmf的文件
16lz
2021-12-04
菜鸟进场,方圆十里,寸草不生
最近定制化一个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 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上展示了。
更多相关文章
- 做自己的Android(安卓)ROM,屏蔽对framework中的系统APK的签名检查
- 阿里Android开发规范:资源文件命名与使用规范
- 【Rayeager PX2】andoid开机logo分析及PX上的实现
- 解读Android(安卓)LOG机制的实现
- Facebook推出强大Android图片库Fresco 自动释放内存 图片缓存 内
- android中一些view处理(拖动,定位,显示,图层)
- WebView之js调用Android类的方法传递数据 - 依凡王子
- 解读Android(安卓)LOG机制的实现
- 用ndk环境编译android可用的so库