目录介绍

  • 0.思考问题及解决方案
  • 1.加载图片的压缩处理技术
  • 2.网络url图片转换Bitmap保存到本地

    • 2.1 直接通过http请求网络图片通过流转化成Bitmap
    • 2.2 使用第三方库glide将网络图片转化为Bitmap
  • 3.保存bitmap图片到本地文件夹
  • 4.实现带有圆角的图片

    • 4.1 使用glide处理图片圆角的逻辑
    • 4.2 自定义带有圆角的ImageView
  • 5.毫无满仓轮播图背景做高斯模糊

    • 5.1 高斯模糊实现原理
    • 5.2 高斯模糊实现的代码
    • 5.3 高斯模糊可能会造成的崩溃
    • 5.4 高斯模糊参考案例

关于链接

  • 1.技术博客汇总
  • 2.开源项目汇总
  • 3.生活博客汇总
  • 4.喜马拉雅音频汇总
  • 5.程序员聊天笔记汇总
  • 5.其他汇总

0.思考问题及解决方案

  • 0.1.0 图片压缩的技术是什么,原理如何理解?
  • 0.1.1 为什么保存图片,切割图片圆角需要将图片转化成bitmap?
  • 0.1.2 对于从网络下载图片,可以采用什么方式?为什么glide相比从网络直接请求更加高效?
  • 0.1.3 图片背景滑动高斯模糊的原理是什么,是否影响性能?
  • 0.1.4 bitmap如何避免被回收?如果回收了,怎么避免出现使用bitmap崩溃
  • 0.1.5 为什么设置高斯模糊需要放在子线程中处理,不这样做会有什么影响?

1.加载图片的压缩处理技术

1.1 压缩技术步骤

  • 1.1.1 科学计算图片所需的采样比例
  • 1.1.2 设置图片加载的渲染模式为Config.RGB_565,能降低一半内存
  • 1.1.3 对bitmap进行质量压缩

1.2 代码如下所示

/*** 根据路径获得突破并压缩返回bitmap用于显示* @return          Bitmap*/
public static Bitmap getSmallBitmap(String filePath, int newWidth, int newHeight) {final BitmapFactory.Options options = new BitmapFactory.Options();//设置只解析图片的边界参数,即宽高options.inJustDecodeBounds = true;//options.inSampleSize = 2;BitmapFactory.decodeFile(filePath, options);// Calculate inSampleSize//科学计算图片所需的采样比例options.inSampleSize = calculateInSampleSize(options, newWidth, newHeight);//设置图片加载的渲染模式为Config.RGB_565,能降低一半内存,但是会影响图片质量options.inPreferredConfig = Bitmap.Config.RGB_565;// Decode bitmap with inSampleSize set//关闭标记,解析真实的图片options.inJustDecodeBounds = false;Bitmap bitmap = BitmapFactory.decodeFile(filePath, options);//质量压缩Bitmap newBitmap = compressImage(bitmap, 500);if (bitmap != null){bitmap.recycle();}return newBitmap;
}/*** 计算图片的缩放值*/
private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {// Raw height and width of imagefinal int height = options.outHeight;final int width = options.outWidth;int inSampleSize = 1;if (height > reqHeight || width > reqWidth) {// Calculate ratios of height and width to requested height and// widthfinal int heightRatio = Math.round((float) height / (float) reqHeight);final int widthRatio = Math.round((float) width / (float) reqWidth);// Choose the smallest ratio as inSampleSize value, this will// guarantee// a final image with both dimensions larger than or equal to the// requested height and width.inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;}return inSampleSize;
}/*** 质量压缩* @param image* @param maxSize*/
private static Bitmap compressImage(Bitmap image, int maxSize){ByteArrayOutputStream os = new ByteArrayOutputStream();// scaleint options = 80;// Store the bitmap into output stream(no compress)image.compress(Bitmap.CompressFormat.JPEG, options, os);// Compress by loopwhile ( os.toByteArray().length / 1024 > maxSize) {// Clean up osos.reset();// interval 10options -= 10;image.compress(Bitmap.CompressFormat.JPEG, options, os);}Bitmap bitmap = null;byte[] b = os.toByteArray();if (b.length != 0) {bitmap = BitmapFactory.decodeByteArray(b, 0, b.length);}return bitmap;
}

2.网络url图片转换Bitmap保存到本地

2.1 直接通过http请求网络图片通过流转化成Bitmap

  • 2.1.1 直接通过网络请求将网络图片转化成bitmap

    • 经过测试,请求8张图片,耗时毫秒值174
    • 如果是服务器响应速度一般,耗时需要2秒【正式接口】
/*** 请求网络图片转化成bitmap* @param url                       url* @return                          将url图片转化成bitmap对象*/
private static long time = 0;
public static Bitmap returnBitMap(String url) {long l1 = System.currentTimeMillis();URL myFileUrl = null;Bitmap bitmap = null;HttpURLConnection conn = null;InputStream is = null;try {myFileUrl = new URL(url);} catch (MalformedURLException e) {e.printStackTrace();}try {conn = (HttpURLConnection) myFileUrl.openConnection();conn.setConnectTimeout(10000);conn.setReadTimeout(5000);conn.setDoInput(true);conn.connect();is = conn.getInputStream();bitmap = BitmapFactory.decodeStream(is);} catch (IOException e) {e.printStackTrace();} finally {try {if (is != null) {is.close();conn.disconnect();}} catch (IOException e) {e.printStackTrace();}long l2 = System.currentTimeMillis();time = (l2-l1) + time;LogUtils.e("毫秒值"+time);//保存}return bitmap;
}

2.2 使用第三方库glide将网络图片转化为Bitmap

/*** 请求网络图片转化成bitmap*/
private static long times = 0;
public static void glideBitmap(Context context,String url){final long l1 = System.currentTimeMillis();Glide.with(context).load(url).asBitmap()//设置缓存.diskCacheStrategy(DiskCacheStrategy.ALL).into(new SimpleTarget<Bitmap>() {@Overridepublic void onResourceReady(Bitmap resource,GlideAnimation<? super Bitmap> glideAnimation) {long l2 = System.currentTimeMillis();times = (l2-l1) + times;LogUtils.e("毫秒值"+times);//请求8张图片,耗时毫秒值98}});
}

3.保存bitmap图片到本地文件夹

/*** 保存图片至自定义路径,刷新相册*/
public static void saveImageToFile(Context context, Bitmap bmp) {// 首先保存图片,这个路径可以自定义File appDir = new File(Environment.getExternalStorageDirectory(), "yc");// 测试由此抽象路径名表示的文件或目录是否存在if (!appDir.exists()) {//如果不存在,则创建由此抽象路径名命名的目录//noinspection ResultOfMethodCallIgnoredappDir.mkdir();}// 然后自定义图片的文件名称String fileName = System.currentTimeMillis() + ".jpg";// 创建file对象File file = new File(appDir, fileName);try {FileOutputStream fos = new FileOutputStream(file);bmp.compress(Bitmap.CompressFormat.JPEG, 100, fos);fos.flush();fos.close();} catch (IOException e) {e.printStackTrace();}// 其次把文件插入到系统图库try {MediaStore.Images.Media.insertImage(context.getContentResolver(),file.getAbsolutePath(), fileName, null);} catch (FileNotFoundException e) {e.printStackTrace();}// 最后通知图库更新Intent intent = new Intent();intent.setAction(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);intent.setData(Uri.parse("file://" + file.getAbsoluteFile()));context.sendBroadcast(intent);
}

4.实现带有圆角的图片

4.1 使用glide处理图片圆角的逻辑

/*** 加载带有圆角的矩形图片  用glide处理** @param path   路径* @param round  圆角半径* @param resId  加载失败时的图片* @param target 控件*/
public static void loadImgByPicassoWithRound(final Context activity, String path,final int round, int resId, final ImageView target) {if (path != null && path.length() > 0) {Glide.with(activity).load(path).asBitmap().placeholder(resId).error(resId)//设置缓存.diskCacheStrategy(DiskCacheStrategy.ALL).into(new BitmapImageViewTarget(target) {@Overrideprotected void setResource(Bitmap resource) {super.setResource(resource);RoundedBitmapDrawable circularBitmapDrawable = RoundedBitmapDrawableFactory.create(activity.getResources(), resource);//设置绘制位图时要应用的角半径circularBitmapDrawable.setCornerRadius(round);target.setImageDrawable(circularBitmapDrawable);}});}
}

4.2 自定义带有圆角的ImageView

  • 使用BitmapShader实现圆形、圆角图片
  • 具体看:https://github.com/yangchong2... 中的libimage自定义imageView

5.毫无满仓轮播图背景做高斯模糊

5.1 高斯模糊实现原理

  • 前沿【摘自网络】:在Android平台上进行模糊渲染是一个相当耗CPU也相当耗时的操作,一旦处理不好,卡顿是在所难免的。考虑到效率,渲染一张图片最好的方法是使用OpenGL,其次是使用C++/C,使用Java代码是最慢的。但是Android推出RenderScript之后,我们就有了新的选择,测试表明,使用RenderScript的渲染效率和使用C/C++不相上下,但是使用RenderScript却比使用JNI简单地多!
  • 原理步骤如下所示:

    • a.压缩图片,可以质量压缩,也可以宽高压缩
    • b.创建RenderScript内核对象
    • c.创建一个模糊效果的RenderScript的工具对象
    • d.设置相关参数,具体看代码……
  • 实现思路:先将图片进行最大程度的模糊处理,再将原图放置在模糊后的图片上面,通过不断改变原图的透明度(Alpha值)来实现动态模糊效果。

5.2 高斯模糊实现的代码

  • 5.2.1 设置高斯模糊代码
/*** 设置模糊背景*/
private void setBlurBackground(int pos) {//获取轮播图索引pos处的图片Integer integer = pagerAdapter.getBitmapHashMap().get(pos);Resources res = this.getResources();Bitmap bitmap= BitmapFactory.decodeResource(res, integer);//压缩图片final Bitmap image = BitmapUtils.compressImage(bitmap);if (bitmap != null) {if (mBlurRunnable != null) {mIvBlurBackground.removeCallbacks(mBlurRunnable);}mBlurRunnable = new Runnable() {@Overridepublic void run() {//压缩图片,宽高缩放Bitmap blurBitmap = BlurBitmapUtils.getBlurBitmap(mIvBlurBackground.getContext(), image, 15);ViewSwitchUtils.startSwitchBackgroundAnim(mIvBlurBackground, blurBitmap);}};mIvBlurBackground.postDelayed(mBlurRunnable, 100);}
}
  • 5.2.2 RenderScript图片高斯模糊
/*** RenderScript图片高斯模糊*/
public class BlurBitmapUtils {/*** 建议模糊度(在0.0到25.0之间)*/private static final int SCALED_WIDTH = 100;private static final int SCALED_HEIGHT = 100;/*** 得到模糊后的bitmap* @param context                   上下文* @param bitmap                    bitmap* @param radius                    半径* @return*/public static Bitmap getBlurBitmap(Context context, Bitmap bitmap, int radius) {// 将缩小后的图片做为预渲染的图片。Bitmap inputBitmap = Bitmap.createScaledBitmap(bitmap, SCALED_WIDTH, SCALED_HEIGHT, false);// 创建一张渲染后的输出图片。Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap);// 创建RenderScript内核对象RenderScript rs = RenderScript.create(context);// 创建一个模糊效果的RenderScript的工具对象ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));// 由于RenderScript并没有使用VM来分配内存,所以需要使用Allocation类来创建和分配内存空间。// 创建Allocation对象的时候其实内存是空的,需要使用copyTo()将数据填充进去。Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap);Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap);// 设置渲染的模糊程度, 25f是最大模糊度blurScript.setRadius(radius);// 设置blurScript对象的输入内存blurScript.setInput(tmpIn);// 将输出数据保存到输出内存中blurScript.forEach(tmpOut);// 将数据填充到Allocation中tmpOut.copyTo(outputBitmap);return outputBitmap;}}
  • 5.2.3 设置高斯模糊背景View动画过渡效果
/*** 图片背景切换动画帮助类,设置View动画*/
public class ViewSwitchUtils {static void startSwitchBackgroundAnim(ImageView view, Bitmap bitmap) {Drawable oldDrawable = view.getDrawable();Drawable oldBitmapDrawable ;TransitionDrawable oldTransitionDrawable = null;if (oldDrawable instanceof TransitionDrawable) {oldTransitionDrawable = (TransitionDrawable) oldDrawable;oldBitmapDrawable = oldTransitionDrawable.findDrawableByLayerId(oldTransitionDrawable.getId(1));} else if (oldDrawable instanceof BitmapDrawable) {oldBitmapDrawable = oldDrawable;} else {oldBitmapDrawable = new ColorDrawable(0xffc2c2c2);}if (oldTransitionDrawable == null) {oldTransitionDrawable = new TransitionDrawable(new Drawable[]{oldBitmapDrawable, new BitmapDrawable(bitmap)});oldTransitionDrawable.setId(0, 0);oldTransitionDrawable.setId(1, 1);oldTransitionDrawable.setCrossFadeEnabled(true);view.setImageDrawable(oldTransitionDrawable);} else {oldTransitionDrawable.setDrawableByLayerId(oldTransitionDrawable.getId(0), oldBitmapDrawable);oldTransitionDrawable.setDrawableByLayerId(oldTransitionDrawable.getId(1), new BitmapDrawable(bitmap));}oldTransitionDrawable.startTransition(1000);}
}

5.3 高斯模糊可能会造成的崩溃

  • 5.3.1 崩溃日志

    • 开发回收bitmap引发Canvas: trying to use a recycled bitmap错误处理
  • 5.3.2 抛该异常的原因分析

    • 如果代码已经不再需要使用Bitmap对象了,就可以释放了。释放内存以后,就不能再使用该Bitmap对象了,如果再次使用,就会抛出异常。所以一定要保证不再使用的时候释放。
  • 5.3.3 解决该问题的办法

    • 使用缓存

5.4 高斯模糊参考案例

  • Android 图片高斯模糊解决方案:https://www.jianshu.com/p/02d...
关于我的博客
  • 我的个人站点:www.yczbj.org,www.ycbjie.cn
  • github:https://github.com/yangchong211
  • 知乎:https://www.zhihu.com/people/...
  • 简书:http://www.jianshu.com/u/b7b2...
  • csdn:http://my.csdn.net/m0_37700275
  • 喜马拉雅听书:http://www.ximalaya.com/zhubo...
  • 开源中国:https://my.oschina.net/zbj161...
  • 泡在网上的日子:http://www.jcodecraeer.com/me...
  • 邮箱:yangchong211@163.com
  • 阿里云博客:https://yq.aliyun.com/users/a... 239.headeruserinfo.3.dT4bcV
  • segmentfault头条:https://segmentfault.com/u/xi...

Android 图片相关整理相关推荐

  1. android 最全 图片相关知识整理

    android 最全 图片相关知识整理 图片基础知识梳理 图片基础知识梳理(1) - ImageView 的 ScaleType 属性解析 图片基础知识梳理(2) - Bitmap 占用内存分析 图片 ...

  2. Android 图片文件操作、屏幕相关、.9图片的理解

     一:Android图片操作 1.存储bitmap到本地文件系统 public static void bitmapToFile(Bitmap bitmap, String uri) {if(!ext ...

  3. 【Android】RecycleView简单仿漫画APP图片相关样式

    真的真的想不到起什么标题好了,这次的内容真的是太简单了,没有什么挑战性,一天以内就完成了.最近在学kotlin,也会有一份kotlin的代码,鉴于很多人都是从java开始进行android开发的,ko ...

  4. android开发相关资料整理【2011-10-29】

    外文译本--andbook Android开发基础书籍 Android CheckBox的isChecked属性 方法的反射 Android BluetoothClass.Device Android ...

  5. Android图片系列-2.Android App图片压缩、裁剪分析整理

    移动端常用的图片格式有PNG和JPEG,目前ios手机和大部分安卓手机拍照生成的图片默认格式都是JPEG.我们开发APP的时候通常使用的是PNG,这可能是考虑到图片质量效果.PNG图片是无损压缩格式, ...

  6. android 常用框架整理

    文章目录 UI 框架 WebView 框架 具体内容 UI 卫星菜单 节选器 下拉刷新 模糊效果 HUD与Toast 进度条 UI其他 动画 网络相关 网络连接 网络测试 图像获取 响应式编程 地图 ...

  7. GitHub 优秀的 Android 开源项目 淘宝技术牛p博客整理开发中最常用的GitHub上 优秀的 Android 开源项目整理(精品)...

    原文地址为http://www.trinea.cn/android/android-open-source-projects-view/,作者Trinea 主要介绍那些不错个性化的View,包括Lis ...

  8. Android 开源项目整理

    这是一个基本把github上所有优秀安卓的开源代码整理了,下面是都是转自https://github.com/Trinea/Android-open-project,都是一些牛人,很有开源精神的达人做 ...

  9. Android技术面试整理

    colife Android技术面试整理 前19题为常考题目!!  1.Android的四大组件是哪些,它们的作用? 2.请介绍下Android中常用的五种布局. 3.android中的动画有哪几类, ...

最新文章

  1. Android-如何开发一个功能强大的图片选择器
  2. C# 8.0的三个令人兴奋的新特性
  3. 如何通过SpringMVC框架响应JSON数据
  4. 输入参数的数目不足_机器学习算法—KMEANS算法原理及阿里云PAI平台算法模块参数说明...
  5. 天津理工大学c语言上机报告3,天津理工大学-c语言上机报告4.pdf
  6. 你所不知道的setTimeout
  7. 2018 区块链技术及应用峰会(BTA)·中国全日程公布!
  8. 理解crossentropy loss
  9. php mysql 获取排名,Mysql排序获取排名的实例代码
  10. python子类调用父类构造函数_Java 子类调用父类的构造函数
  11. Java、对字符串中的字符排序
  12. github系列(一) Windows环境下载与安装
  13. 狗民网:狗与爱的世界
  14. 将中文字符串转为拼音
  15. Bootstrap-用ICheck插件给CheckBox换新装
  16. 如何混淆JavaWeb代码
  17. 操作系统资源分配管理
  18. 【Unity小游戏】 横版2D射击小游戏 效果展示+完整项目源码【超级简单,自己也可以做游戏玩了】
  19. 记录调整CentOS的分区大小
  20. 甲骨文助ISV 通过SOA与Oracle软件集成

热门文章

  1. mysql安装、配置、连接
  2. 通用easyui查询页面组件
  3. bowtie1和bowtie2的比较
  4. 《Cracking the Coding Interview》——第10章:可扩展性和存储空间限制——题目1
  5. 大家一起讨论一下朋友网的人脉关系算法是怎么实现的
  6. 测试基础-05-bug的定义生命周期
  7. html toast 插件,基于Bootstrap4的Toast提示插件
  8. webassembly类型_几张图让你看懂WebAssembly
  9. mongodb默认的用户名密码_Windows下MongoDB设置用户、密码
  10. cad插入块_CAD中的quot;块quot;能否修改?能!一个命令可快速解决