Android 笔记 ImageView 显示大图遇到的问题 以及 无损显示大图 的解决方案
ImageView
制作一个显示图片的activity,类似相册那样的,可以移动图片,多点触控的时候放大缩小图片等功能
一般就是用BitmapFactory
来解码bitmap,然后设置imageView.setImageBitmap()
但是遇到了一个问题,就是图片过大的时候(也没多大,也就是手机摄像头拍的照片,4128x3096,13M像素),真机运行会显示空白,什么都没有
但是模拟器运行正常,就是有一点卡。
在网上搜索的时候看到有一些解释
1,因为图片太大导致的OOM(out of memory)错误
在程序中设置try-catch并没有抓到这个错误,而且debug发现,在BitmapFactory
解码图片以后,可以获取到Bitmap的信息,说明也许没有出现这个错误,图片的内存占用仍然在可取范围内
2,需要设置解码的option参数,inSampleSize
这个参数的意思是,把图像的长/宽缩小,再生成Bitmap,inSampleSize的数值是1,2,4这样的比例,然后长/宽就除以这个数值,那么总像素数就除以这个数值的平方
这样的话,内存占用就小了。实际测试的时候,4128X 3096的照片可以显示,内存占用的确小了很多。但是图像放大以后发现果然分辨率也小了。虽然放的不是很大的时候看起来没区别,但是更希望有个解决方案能显示原图的分辨率
而且,快图浏览这个app可以完美显示原分辨率的图像,说明不需要减小分辨率也可以做到正常显示。
3,又发现一个现象,就是长图也无法显示。
比如一个6000X1000的图,总像素6M,内存占用也很小,但是也无法显示。这证明我在第一条里面的推测是正确的,没有出现OOM,解码的时候正常,但是显示的时候错误。
在网上查找发现是这么一个问题,Bitmap too large to be uploaded into a texture
这个信息并不会出现在错误提示里,所以无法catch,只能在logcat里面看到一个warning
但是我用真机测试的时候还没有找到显示Log的方法(网上找到的方法都无效),而模拟器测试又正常,所以没看到这个warning。
Bitmap too large to be uploaded into a texture (5312x2988, max=4096x4096)
有一些网上的信息是这样显示的,说明最大支持的就是4096x4096。
然后我发现,手机里面有一些正好4096像素宽的图像可以正常显示,大一点的比如4128的就不行,我觉得这个解释才是我这个问题的最终解释。
也就是说,是因为图像在显示的时候,有一个最大边长像素数,我的手机的限制是4096,网上也有其他的情况比如2048等等。
解决方案
1 网上提示说可以关闭硬件加速
在manifest文件里面设置 hardwareAcceleration = “false”,就关闭了硬件加速
没错,这样是可以加载长图了,但是APP变卡了,体验非常不好。舍弃
2 用切割法
就说说,每次显示在imageView中的图不是原图的bitmap,通过一个方法
Bitmap.createBitmap(bitmap,x,y,width,height)
创建一个bitmap,长宽符合屏幕要求,这样就不会超过像素限制。实际操作以后发现,的确可以显示大图,但是效果也不好,拖动的时候帧数比较低,比上一条的那种好点,但是没有达到最好的要求(就是像快图浏览里面那样的),即便手机自带的相册app也比这个流畅一些。
3,找了半天找到一个github上的项目,运行以后发现完美达到要求
Subsampling Scale Image View
这个解决方案是这样的,其实也是切割法,但是跟上一条不同的是,需要定义一个自定义的VIEW,自己写里面的onDraw方法,绘制bitmap
当然不要一次性画出来,而是根据情况将图切分为能够绘制出来的块。比如现在很多设备的限制是4096X4096,以前貌似是2048x2048,就根据情况切分为最大这样的块,然后绘制每个块,把块拼接起来,就跟原来的图一样了。
变换的时候,在onDraw里面设置matrix canvas.concat(matrix)
,然后再drawBitmap(...)
这样,每次绘图的时候就会根据matrix来变换了。当然,也可以直接用带matrix参数的drawBitmap。
这就是基本原理。还有一个,就是前面提到的inSampleSize。在不显示大图的情况下,可以设置inSampleSize来缩小图的比例,可以节省内存提高处理速度
补充
实际操作中我发现一个问题,就是设置canvas.concat(matrix)
以后,实际变换的是整个canvas的坐标系。
也就是说,变换matrix以后,画布的中心点已经不再是屏幕中心了。这时候如果在原来的坐标画另外一个图形,会发现画在了其他位置,正好和画布的移动吻合,说明是画布移动了,而不是画布上的图像。
所以,设置全局的matrx以后会带来一点问题,就是坐标系也会移动。
找到一个解决办法 :
不要设置全局的matrix canvas.concat()
改为:
bitmapMatrix.reset();
bitmapMatrix.postTranslate(block.left,block.top);
bitmapMatrix.postConcat(mMatrix);
canvas.drawBitmap(block.bitmap,bitmapMatrix,mPaint);
其中bitmapMatrix是一个单独的matrix
在每次绘图之前,把这个matrix重置,然后添加一个偏移量,就是第二行
再添加全局的matrix,就是第三行。注意第二行和第三行顺序不能反了,实际测试中发现反了以后会显示错误。
这样的话,就不是改变全局坐标,canvas没有变动,变动的是bitmap。
Android 笔记 ImageView 显示大图遇到的问题 以及 无损显示大图 的解决方案相关推荐
- android 图片横竖判断_Android应用开发之android 判断ImageView当前显示的是哪一张图片...
本文将带你了解Android应用开发之android 判断ImageView当前显示的是哪一张图片,希望本文对大家学Android有所帮助. 判断ImageView当前显示的是哪一张图片 Java ...
- Android笔记:Dialog显示图片
下看一下效果图 点击TextView弹出Dialog 点击图片Dialog消失 先看一下MainActivity package com.cxy.demo;import android.app.Act ...
- Android在ImageView上直接显示网络图片
亲测可用,若有疑问请私信 在原生的ImageView中,没有一个方法是可以直接显示网络的图片的,当我们经常需要显示网络图片时,每次都有一大堆的操作,这会很麻烦,今天就教大家在ImageView上轻松显 ...
- android imageview 居中显示,Android中ImageView无法居中的问题
做Android UI布局,尤其是遇到比较复杂的多重LinearLayout嵌套,常常会被一些比较小的问题困扰上半天,比如今天在使用ImageView的时候,想让其居中显示,可是无论怎样设置layou ...
- Android使用ImageView显示网络图片
本案例使用ImageView 简单的实现了网络图片的调用.当中注意事项.由于用到了网络,这里採用了HttpClient方法訪问网络联接,关于怎样使用,可參照文章 Android中使用HttpClien ...
- Android 自定义ImageView加载图片
自定义imageview功能: 可以实现设置图片显示的时候,依据本身的比例进行图片的缩放 加载图片效果: 使用ImageLoader来加载 图片: 首先将ImageLoader的jar包关联到项目中 ...
- Android笔记之(图片高斯+Glide实现微信图片加载策略+仿微信进度条)
很久以前就想自己实现一下仿微信图片加载的那种策略了,先加载一张模糊的图片,然后再加载清晰大图,今天研究了一下,不过要是Glide支持进度条显示就好了,不得不说Glide很强大, 不啰嗦了,直接上代码了 ...
- Android笔记:触摸事件的分析与总结----多点触控
其他相关博文: Android笔记:触摸事件的分析与总结----MotionEvent对象 Android笔记:触摸事件的分析与总结----TouchEvent处理机制 An ...
- 镜像处理坐标 android,Android应用开发之Android重写ImageView实现图片镜像效果的代码教程...
本文将带你了解Android应用开发之Android重写ImageView实现图片镜像效果的代码教程,希望本文对大家学Android有所帮助. 前两天朋友问我一个问题,如何实现从手机系统相册加载一张图 ...
最新文章
- SpringBoot第二十三篇: 异步方法
- MySQL数据库介绍、安装(服务端软件安装、客户端软件安装(图形化界面客户端和命令行客户端))
- 写在开年:移植wolfssl4.3.0到w60x_sdk_3.04时的一点问题
- left join 和 left outer join 的区别【转】
- 雷蛇灯光配置文件_雷蛇猎魂光蛛竞技版机械键盘评测
- ubuntu linux下建立stm32开发环境: 程序烧录 openocd+openjtag
- markdown-Macdown
- Struts2中访问HttpServletRequest和HttpSession
- Linux 中/etc/profile、~/.bash_profile 环境变量配置以及区别
- 一加8系列再次开售 全渠道销售额破亿
- HTML 标签学习总结第一天
- [LevelDB] 编译和使用
- 2020 年的第一天,程序员鸭血粉丝又碰上生产事故
- 移动应用设计领域中最拔尖的15大应用
- 尚硅谷Docker---docker安装及简介
- mysql中转换日期格式,MySQL日期格式转换
- 图解HTTP笔记记录
- linux usb摄像头驱动程序,Linux系统下USB摄像头驱动开发
- IDEA 2018.3.3 有效期至 2100
- STM32自学笔记ADC多通道扫描