最近项目优化的时候发现app上选择的部分图片上传到服务器后无法显示或者直接上传失败,经过跟踪发现问题出现在webp图片格式上,说到webp格式的图片,这是google自己发明的一种图片格式,在网络上使用可以比jpg和png更小,图像的清晰度还不损失,是个很好的图片格式。无奈,目前除了google的产品,android和chorme等支持外,其他地方支持的都不太如人意。有两个可以解决该问题的方法,一种是在服务器端,图片上传后,通过php转码为jpg或者png再使用;一种是在安卓端选择了webp格式的图片,本地转换为jpg或者png再上传。
服务器转码需要php5.4版本以上,但是公司的核心系统偏偏跑在php5.4以下,而且升级php很不现实,核心系统的稳定是第一位的,所以该方法被pass掉了,接下来就该我们苦逼的android程序员揪头发了,先是在百度和google上各种搜索,基本没发现可用的解决方法,不过也提供了一点线索,有些大牛用ndk的方式解决了,仔细阅读这些文章,找到了解决路径,使用libwebp库,将webp格式图片转成bitmap,bitmap再转png或者jpg就无压力了,这就是解决办法了,不扯淡,上代码:
准备工作:在csdn上找libwebp.so 放在armeabi 和armeabi-v7a各一份,将libwebp.jar放在依赖库里;
核心代码,从webp到bitmap转换;
static { System.loadLibrary("webp"); } private byte[] loadFileAsByteArray(String filePath) { File file = new File(filePath); byte[] data = new byte[(int)file.length()]; try { FileInputStream inputStream; inputStream = new FileInputStream(file); inputStream.read(data); inputStream.close(); } catch (Exception e) { e.printStackTrace(); } return data; } private Bitmap webpToBitmap(byte[] encoded) { int[] width = new int[] { 0 }; int[] height = new int[] { 0 }; byte[] decoded = libwebp.WebPDecodeARGB(encoded,encoded.length,width,height); //byte[] decoded = libwebp.WebPDecodeARGB(encoded, encoded.length, width, height); int[] pixels = new int[decoded.length / 4]; ByteBuffer.wrap(decoded).asIntBuffer().get(pixels); return Bitmap.createBitmap(pixels, width[0], height[0], Bitmap.Config.ARGB_8888); }图片格式判断代码:
BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(file.getAbsolutePath(), options); String type = options.outMimeType; Util.printLog("image type -> ", type); if(type.equals("image/webp")){Bitmap转png代码:
Bitmap bp = webpToBitmap(loadFileAsByteArray(file.getAbsolutePath())); String c = file.getParent(); newFile = new File(c + File.separator + System.currentTimeMillis() + ".png"); Util.printLog("webp test",file.getAbsolutePath());// Util.printLog("webp test",newFile.getAbsolutePath());// if(newFile.exists()){ newFile.delete(); } FileOutputStream out; try{ out = new FileOutputStream(newFile); if(bp.compress(Bitmap.CompressFormat.PNG, 90, out)) { out.flush(); out.close(); } } catch (FileNotFoundException e) { e.printStackTrace(); }catch (IOException e) { e.printStackTrace(); }
注意事项:webp格式图片如果经过剪裁的话,虽然扩展名是.webp,但是实际格式一般是png或者jpg,请使用上面的图片格式判断代码判断实际图片格式后,再决定是否需要转换。libwebp.so 和libwebp.jar我会在我的资源里传一份 http://download.csdn.net/detail/dsb2008dsb/9813264 ,其他人共享的也有。