Android 加载高清巨图,无需剪裁压缩
来源:互联网 发布:数据切片和切块 编辑:程序博客网 时间:2024/06/05 09:41
LargeImage
Android 加载大图 可以高清显示10000*10000像素的图片
可以滑动,放大缩小具有PhotoView的效果
普通图片也可以用它展示 #Gradle
compile 'com.shizhefei:LargeImageView:1.0.9'
Download Demo apk
#效果
#使用方法
<com.shizhefei.view.largeimage.LargeImageView android:id="@+id/imageView" android:scrollbars="vertical|horizontal" android:layout_width="match_parent" android:layout_height="match_parent" />
代码
largeImageView = (LargeImageView) findViewById(R.id.imageView);//通过文件的方式加载sd卡中的大图largeImageView.setImage(new FileBitmapDecoderFactory(file));//通过流的方式加载assets文件夹里面的大图largeImageView.setImage(new InputStreamBitmapDecoderFactory(getAssets().open(ss[position])))//加载普通大小图片largeImageView.setImage(R.drawable.cat);largeImageView.setImage(drawable);largeImageView.setImage(bitmap);
支持的事件
largeImageView.setOnClickListener(onClickListener); largeImageView.setOnLongClickListener(onLongClickListener);
设置是否可以缩放
largeImageView.setEnabled(true);
Hook临界值(不设置的话会使用默认的计算缩放最小倍数和最大倍数)
/** * Hook临界值 */public interface CriticalScaleValueHook { /** * 返回最小的缩放倍数 * scale为1的话表示,显示的图片和View一样宽 * * @param largeImageView * @param imageWidth * @param imageHeight * @param suggestMinScale 默认建议的最小的缩放倍数 * @return */ float getMinScale(LargeImageView largeImageView, int imageWidth, int imageHeight, float suggestMinScale); /** * 返回最大的缩放倍数 * scale为1的话表示,显示的图片和View一样宽 * * @param largeImageView * @param imageWidth * @param imageHeight * @param suggestMaxScale 默认建议的最大的缩放倍数 * @return */ float getMaxScale(LargeImageView largeImageView, int imageWidth, int imageHeight, float suggestMaxScale);}
例如
largeImageView.setCriticalScaleValueHook(new LargeImageView.CriticalScaleValueHook() { @Override public float getMinScale(LargeImageView largeImageView, int imageWidth, int imageHeight, float suggestMinScale) { return 1; } @Override public float getMaxScale(LargeImageView largeImageView, int imageWidth, int imageHeight, float suggestMaxScale) { return 4; } });
加载网络的图片,先下载本地,再通过加载图片的文件
比如glide加载图片,具体代码查看demo
String url = "http://img.tuku.cn/file_big/201502/3d101a2e6cbd43bc8f395750052c8785.jpg"; Glide.with(this).load(url).downloadOnly(new ProgressTarget<String, File>(url, null) { @Override public void onLoadStarted(Drawable placeholder) { super.onLoadStarted(placeholder); ringProgressBar.setVisibility(View.VISIBLE); ringProgressBar.setProgress(0); } @Override public void onProgress(long bytesRead, long expectedLength) { int p = 0; if (expectedLength >= 0) { p = (int) (100 * bytesRead / expectedLength); } ringProgressBar.setProgress(p); } @Override public void onResourceReady(File resource, GlideAnimation<? super File> animation) { super.onResourceReady(resource, animation); ringProgressBar.setVisibility(View.GONE); largeImageView.setImage(new FileBitmapDecoderFactory(resource)); } @Override public void getSize(SizeReadyCallback cb) { cb.onSizeReady(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL); } });
#实现原理
只加载显示的区域的图片,切成小块拼接.
#LargeImageView 根据滚动和缩放事件 scrollTo 对应的位置,计算当前显示区域的图片绘制出来
#UpdateImageView 监听View的显示区域的变化,然后加载显示区域内应该显示的图片区域,然后绘制到View上
UpdateView负责监听显示区域的变化的View,子类通过重写onUpdateWindow(Rect visiableRect)监听显示区域,大部分代码源于SurfaceView监听代码
###BlockImageLoader负责加载显示区域的图片块。 ###
###实现细节: ### 每次LargeImageView的onDraw方法都会调用ImageManagerd的getDrawData(float imageScale, Rect imageRect)方法,imageRect为在View上图片显示的区域(需要加载的图片区域),imageScale 假设等于4的话,就是View上显示1像素,image要加载4个像素的区域(缩小4倍的图片)
getDrawData(float imageScale, Rect imageRect)实现细节:
手势移动,图片显示区域会变化。比如显示区域是800800,向右移动2像素,难道要重新加载800800的图片区域? 所以我采用了图片切块的操作,分块的优化
- 比如图片显示比例是1,那么要横向分多少份才,纵向分多少分,才合理?图片显示比例是4,横向分多少份才,纵向分多少分,才合理。
所以我采用了基准块(图片比例是1,一个图片块的宽高的合理sise) BASE_BLOCKSIZE = context.getResources().getDisplayMetrics().heightPixels / 2+1;
图片缩放比例为1的话,图片块宽高是BASE_BLOCKSIZE
图片缩放比例为4的话,图片块宽高是4*BASE_BLOCKSIZE
图片没被位移,那么屏幕上显示横向2列,纵向getDisplayMetrics().heightPixels/BASE_BLOCKSIZE行
2.因为手势放大缩小操作要加载不同清晰度的图片区域,比如之前的图片缩放是4,现在缩放是4.2,难道要重新加载?
通过public int getNearScale(float imageScale)方法计算趋于2的指数次方的值(1,2,4,8,16)
比如3.9和4.2和4比较接近,就直接加载图片显示比例为4的图片块
3.之前没加载的区域,难道要空白显示么?
为了避免加载出现白色块,我会缓存当前比例的加载的图片块,以及2倍比例的图片块(之前加载过,并且当前还属于当前显示区域的,如果不是的话也不缓存它) 所以发现没有的话去拿其他比例的图片区去显示
4.难道只加载显示区域?
当然,还会去加载旁边一部分没显示的区域的图片块
5.onDraw方法是UI线程,调用getDrawData(float imageScale, Rect imageRect)加载图片块的方法怎么不卡住
getDrawData只返回之前加载过的图片块,而没有加载的是通过LoadHandler.sendMessage去加载 LoadHandler的Loop是通过HandlerThread线程创建的Loop,也就是开个线程加载.
每加载一个图片块通过 onImageLoadListenner.onBlockImageLoadFinished();onDraw重绘
onDraw又调用getDrawData加载,直至需要显示的图片块加载完成
转自:https://github.com/LuckyJayce/LargeImage
- Android 加载高清巨图,无需剪裁压缩
- Android上传头像,图片剪裁,压缩图片
- Android上传头像,图片剪裁,压缩图片
- Android上传头像,图片剪裁,压缩图片
- Android图片处理——压缩、剪裁、圆角、保存
- Android调用系统摄像头拍照并剪裁压缩
- android 拍照并将图片剪裁、压缩并显示
- php图片压缩剪裁
- Android--自定义View加载网络图片,实现缩放,圆形剪裁
- android拍照选择图库后将照片剪裁压缩显示到imageview上
- Android 图像选取 图片剪裁 照相选图 照相裁剪 图像压缩 11 - 14更新
- Android 加载压缩的图片
- android 图片剪裁
- Android 剪裁图片
- 图片剪裁 Android
- android 系统图片剪裁
- android 剪裁图片
- android系统剪裁照片
- 系统延迟及定时机制
- 【Linux内核】学习资料
- [Oracle 11g r2(11.2.0.4.0)]Oracle Golden Gate Training-workshop3
- dns请求包
- 继承和初始化时,程序运行顺序的自己的理解。
- Android 加载高清巨图,无需剪裁压缩
- 大周总结
- 调用动态链接库*.so
- 编译接口工具类
- Java算法之直接插入排序
- linux性能监控工具-(显示系统整体资源使用情况-top命令)
- 旷视科技完成4.6亿美元C轮融资,打破商汤4.1亿美元单轮融资记录
- 解密DNA机器人“巨大的一小步”:血液循环中精准送达药物
- 3分钟学会sessionStorage用法