Android Bitmap 全面解析(一)加载大尺寸图片

http://www.eoeandroid.com/thread-331669-1-1.html

Android Bitmap 全面解析(二)加载多张图片的缓存处理
http://www.eoeandroid.com/thread-332399-1-1.html

Android Bitmap 全面解析(三)开源图片框架分析1-UIL(上)
http://www.eoeandroid.com/thread-333220-1-1.html

Android Bitmap 全面解析(三)开源图片框架分析1-UIL(下)
http://www.eoeandroid.com/thread-333229-1-1.html

 
Android Bitmap 全面解析(三)开源图片框架分析2-ImageLoader和Volley
 
Android Bitmap 全面解析(四)图片处理效果对比
 
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" > <LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<ImageView
android:id="@+id/iv1"
android:layout_width="150dp"
android:layout_height="150dp" />
<ImageView
android:id="@+id/iv2"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_marginLeft="20dp"
android:scaleType="centerCrop" />
</LinearLayout> <LinearLayout
android:layout_marginTop="50dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<ImageView
android:id="@+id/iv3"
android:layout_width="150dp"
android:layout_height="150dp" />
<ImageView
android:id="@+id/iv4"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_marginLeft="20dp"
android:scaleType="centerCrop" />
</LinearLayout> </LinearLayout>
 package com.example.bdimagescale;

 import android.app.Activity;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.Menu;
import android.widget.ImageView; public class MainActivity extends Activity { private static final int FIT_INSIDE = 1;
private static final int CROP = 2; private ImageView iv1;// 默认缩放类型,即FIT_INSIDE
private ImageView iv2;// centerCrop缩放类型,即CROP
private ImageView iv3;// 默认缩放类型,即FIT_INSIDE
private ImageView iv4;// centerCrop缩放类型,即CROP @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); // // 10000以内随机宽高
// for(int i=0; i<20; i++) {
// int width = (int)(Math.random()*9000+1000);
// int height = (int)(Math.random()*9000+1000);
// test(width, height, 400, 200, 200, 200);
// // compareInSampleSize(width, height, 400, 200);
// } iv1 = (ImageView) findViewById(R.id.iv1);
iv2 = (ImageView) findViewById(R.id.iv2);
iv3 = (ImageView) findViewById(R.id.iv3);
iv4 = (ImageView) findViewById(R.id.iv4);
testLongImage();
// testNormalImage();
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
} // 数据对比
public void test(int width, int height, int limitWidth,
int limitHeight,int viewWidth, int viewHeight) {
System.out.println("原图宽高=" + width + ":" + height);
System.out.println("限定宽高=" + limitWidth + ":" + limitHeight);
System.out.println("控件大小=" + viewWidth + ":" + viewHeight);
float densityOfINSIDE0 = calculateImagePxDensityOfINSIDE(
limitWidth,limitHeight, viewWidth, viewHeight);
System.out.println("默认即INDESE情况下目标像素密度为="
+ densityOfINSIDE0);
float densityOfCROP0 = calculateImagePxDensityOfCROP(limitWidth,
limitHeight, viewWidth, viewHeight);
System.out.println("CROP情况下目标像素密度为=" + densityOfCROP0);
System.out.println("---------------------"); int inSampleSize1 = calculateInSampleSize(
width, height, limitWidth,limitHeight);
int imageWidth = width / inSampleSize1;
int imageHeight = height / inSampleSize1;
System.out.println("官方:对应缩放后图片大小="
+ imageWidth + ":" + imageHeight);
float densityOfINSIDE = calculateImagePxDensityOfINSIDE(
imageWidth,imageHeight, viewWidth, viewHeight);
System.out.println("默认即INDESE情况下像素密度为="
+ densityOfINSIDE);
float densityOfCROP = calculateImagePxDensityOfCROP(imageWidth,
imageHeight, viewWidth, viewHeight);
System.out.println("CROP情况下像素密度为=" + densityOfCROP);
System.out.println("---------------------"); int reWidth = getResizedDimension(limitWidth, limitHeight,
width,height);
int reHeight = getResizedDimension(limitHeight, limitWidth,
height,width);
// System.out.println("处理后限定宽高="+reWidth+":"+reHeight);
int inSampleSize2 = findBestSampleSize(width, height, reWidth,
reHeight);
int imageWidth2 = width / inSampleSize2;
int imageHeight2 = height / inSampleSize2;
System.out.println("Volley:对应缩放后图片大小=" + imageWidth2 + ":"
+ imageHeight2);
float densityOfINSIDE2 = calculateImagePxDensityOfINSIDE(
imageWidth2,imageHeight2, viewWidth, viewHeight);
System.out.println("默认即INDESE情况下像素密度为="
+ densityOfINSIDE2);
float densityOfCROP2 = calculateImagePxDensityOfCROP(imageWidth2,
imageHeight2, viewWidth, viewHeight);
System.out.println("CROP情况下像素密度为=" + densityOfCROP2);
System.out.println("---------------------"); int inSampleSize3OfINSIDE = computeImageSampleSize(width, height,
limitWidth, limitHeight, FIT_INSIDE, true);
int imageWidthOfINSIDE = width / inSampleSize3OfINSIDE;
int imageHeightOfINSIDE = height / inSampleSize3OfINSIDE;
System.out.println("UIL FIT_INSIDE:对应缩放后图片大小=" + imageWidthOfINSIDE
+ ":" + imageHeightOfINSIDE);
float densityOfINSIDE3 = calculateImagePxDensityOfINSIDE(
imageWidthOfINSIDE, imageHeightOfINSIDE, viewWidth, viewHeight);
System.out.println("默认即INDESE情况下像素密度为=" + densityOfINSIDE3);
int inSampleSize3OfCROP = computeImageSampleSize(width, height,
limitWidth, limitHeight, CROP, true);
int imageWidthOfCROP = width / inSampleSize3OfCROP;
int imageHeightOfCROP = height / inSampleSize3OfCROP;
System.out.println("UIL CROP:对应缩放后图片大小=" + imageWidthOfCROP + ":"
+ imageHeightOfCROP);
float densityOfCROP3 = calculateImagePxDensityOfCROP(imageWidthOfCROP,
imageHeightOfCROP, viewWidth, viewHeight);
System.out.println("CROP情况下像素密度为=" + densityOfCROP3);
System.out.println("---------------------"); System.out.println();
} // inSampleSize对比
public void compareInSampleSize(int imageWidth, int imageHeight,
int reqWidth, int reqHeight) {
System.out.println("原图片 " + imageWidth + ":" + imageHeight);
System.out.print("官方 "
+ calculateInSampleSize(imageWidth, imageHeight, reqWidth,
reqHeight));
System.out.print(" ... ");
System.out.print("UIL "
+ computeImageSampleSize(imageWidth, imageHeight, reqWidth,
reqHeight, CROP, true));
System.out.print(" ... ");
System.out.print("Volley "
+ findBestSampleSize(imageWidth, imageHeight, reqWidth,
reqHeight));
System.out.println();
System.out.println();
} public void testLongImage() {
Bitmap vbitmap = decodeByVolley(getResources(), R.drawable.longimage,
300, 300);
// UIL框架中会自行判断处理viewScaleType,这里为了简单临时手写了
Bitmap ubitmap_inside = decodeByUIL(getResources(),
R.drawable.longimage, 300, 300, FIT_INSIDE);
Bitmap ubitmap_crop = decodeByUIL(getResources(), R.drawable.longimage,
300, 300, CROP); iv1.setImageBitmap(vbitmap);
iv2.setImageBitmap(vbitmap); iv3.setImageBitmap(ubitmap_inside);
iv4.setImageBitmap(ubitmap_crop);
} public void testNormalImage() {
Bitmap vbitmap = decodeByVolley(getResources(), R.drawable.normalimage,
300, 300);
// UIL框架中会自行判断处理viewScaleType,这里为了简单临时手写了
Bitmap ubitmap_inside = decodeByUIL(getResources(),
R.drawable.normalimage, 300, 300, FIT_INSIDE);
Bitmap ubitmap_crop = decodeByUIL(getResources(),
R.drawable.normalimage, 300, 300, CROP); iv1.setImageBitmap(vbitmap);
iv2.setImageBitmap(vbitmap); iv3.setImageBitmap(ubitmap_inside);
iv4.setImageBitmap(ubitmap_crop);
} public Bitmap decodeByVolley(Resources res, int resId, int limitWidth,
int limitHeight) { // 首先不加载图片,仅获取图片尺寸
final BitmapFactory.Options options = new BitmapFactory.Options();
// 当inJustDecodeBounds设为true时,不会加载图片仅获取图片尺寸信息
options.inJustDecodeBounds = true;
// 此时仅会将图片信息会保存至options对象内,decode方法不会返回bitmap对象
BitmapFactory.decodeResource(res, resId, options); int reWidth = getResizedDimension(limitWidth, limitHeight,
options.outWidth, options.outHeight);
int reHeight = getResizedDimension(limitHeight, limitWidth,
options.outHeight, options.outWidth); // 计算压缩比例,如inSampleSize=4时,图片会压缩成原图的1/4
options.inSampleSize = findBestSampleSize(options.outWidth,
options.outHeight, reWidth, reHeight); // 当inJustDecodeBounds设为false时,BitmapFactory.decode...就会返回图片对象了
options.inJustDecodeBounds = false;
// 利用计算的比例值获取压缩后的图片对象
return BitmapFactory.decodeResource(res, resId, options);
} public Bitmap decodeByUIL(Resources res, int resId, int limitWidth,
int limitHeight, int scaleType) { // 首先不加载图片,仅获取图片尺寸
final BitmapFactory.Options options = new BitmapFactory.Options();
// 当inJustDecodeBounds设为true时,不会加载图片仅获取图片尺寸信息
options.inJustDecodeBounds = true;
// 此时仅会将图片信息会保存至options对象内,decode方法不会返回bitmap对象
BitmapFactory.decodeResource(res, resId, options); // 计算压缩比例,如inSampleSize=4时,图片会压缩成原图的1/4
options.inSampleSize = computeImageSampleSize(options.outWidth,
options.outWidth, limitWidth, limitHeight, scaleType, true); // 当inJustDecodeBounds设为false时,BitmapFactory.decode...就会返回图片对象了
options.inJustDecodeBounds = false;
// 利用计算的比例值获取压缩后的图片对象
return BitmapFactory.decodeResource(res, resId, options);
} // 计算FIT_INSIDE时像素密度
static float calculateImagePxDensityOfINSIDE(int imageWidth,
int imageHeight, int viewWidth, int viewHeight) {
float density = -1;
if (imageWidth >= imageHeight) {
density = (float) imageWidth / (float) viewWidth;
} else {
density = (float) imageHeight / (float) viewHeight;
}
return density * density;
} // 计算CROP时像素密度
static float calculateImagePxDensityOfCROP(int imageWidth, int imageHeight,
int viewWidth, int viewHeight) {
float density = -1;
if (imageWidth >= imageHeight) {
density = (float) imageHeight / (float) viewHeight;
} else {
density = (float) imageWidth / (float) viewWidth;
}
return density * density;
} // ////////////////// 官方 ////////////////////////////////
int calculateInSampleSize(int width, int height, int reqWidth, int reqHeight) {
// 初始化压缩比例为1
int inSampleSize = 1; // 当图片宽高值任何一个大于所需压缩图片宽高值时,进入循环计算系统
if (height > reqHeight || width > reqWidth) { final int halfHeight = height / 2;
final int halfWidth = width / 2; // 压缩比例值每次循环两倍增加,
// 直到原图宽高值的一半除以压缩值后都~大于所需宽高值为止(将>改成了>=)
while ((halfHeight / inSampleSize) >= reqHeight
&& (halfWidth / inSampleSize) >= reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
} // ////////////////// UIL ////////////////////////////////
int computeImageSampleSize(int width, int height, int limitWidth,
int limitHeight, int viewScaleType, boolean powerOf2Scale) { int scale = 1; int widthScale = width / limitWidth;
int heightScale = height / limitHeight; switch (viewScaleType) {
case FIT_INSIDE:
if (powerOf2Scale) {
while (width / 2 >= limitWidth || height / 2 >= limitHeight) { // ||
width /= 2;
height /= 2;
scale *= 2;
}
} else {
scale = Math.max(widthScale, heightScale); // max
}
break;
case CROP:
if (powerOf2Scale) {
while (width / 2 >= limitWidth && height / 2 >= limitHeight) { // &&
width /= 2;
height /= 2;
scale *= 2;
}
} else {
scale = Math.min(widthScale, heightScale); // min
}
break;
} if (scale < 1) {
scale = 1;
} return scale;
} // ////////////////// Volley ////////////////////////////////
int findBestSampleSize(int actualWidth, int actualHeight, int desiredWidth,
int desiredHeight) {
double wr = (double) actualWidth / desiredWidth;
double hr = (double) actualHeight / desiredHeight;
double ratio = Math.min(wr, hr);
float n = 1.0f;
while ((n * 2) <= ratio) {
n *= 2;
} return (int) n;
} int getResizedDimension(int maxPrimary, int maxSecondary,
int actualPrimary, int actualSecondary) {
// If no dominant value at all, just return the actual.
if (maxPrimary == 0 && maxSecondary == 0) {
return actualPrimary;
} // If primary is unspecified, scale primary to match secondary's scaling
// ratio.
if (maxPrimary == 0) {
double ratio = (double) maxSecondary / (double) actualSecondary;
return (int) (actualPrimary * ratio);
} if (maxSecondary == 0) {
return maxPrimary;
} double ratio = (double) actualSecondary / (double) actualPrimary;
int resized = maxPrimary;
if (resized * ratio > maxSecondary) {
resized = (int) (maxSecondary / ratio);
}
return resized;
} }

36、Android Bitmap 全面解析的更多相关文章

  1. Android Bitmap 全面解析(四)图片处理效果对比 ...

    对比对象: UIL Volley 官方教程中的方法(此系列教程一里介绍的,ImageLoader的处理方法和官方的差不多) -------------------------------------- ...

  2. Android Bitmap 全面解析(一)加载大尺寸图片

    压缩原因:1.imageview大小如果是200*300那么加载个2000*3000的图片到内存中显然是浪费可耻滴行为;2.最重要的是图片过大时直接加载原图会造成OOM异常(out of memory ...

  3. Android Bitmap 全面解析(二)加载多张图片的缓存处理

    一般少量图片是很少出现OOM异常的,除非单张图片过~大~ 那么就可以用教程一里面的方法了通常应用场景是listview列表加载多张图片,为了提高效率一般要缓存一部分图片,这样方便再次查看时能快速显示~ ...

  4. Android Bitmap变迁与原理解析(4.x-8.x)

    App开发不可避免的要和图片打交道,由于其占用内存非常大,管理不当很容易导致内存不足,最后OOM,图片的背后其实是Bitmap,它是Android中最能吃内存的对象之一,也是很多OOM的元凶,不过,在 ...

  5. Android OkHttp完全解析 --zz

    参考文章 https://github.com/square/okhttp http://square.github.io/okhttp/ 泡网OkHttp使用教程 Android OkHttp完全解 ...

  6. Android OkHttp完全解析 是时候来了解OkHttp了

    Android OkHttp完全解析 是时候来了解OkHttp了 标签: AndroidOkHttp 2015-08-24 15:36 316254人阅读 评论(306) 收藏 举报  分类: [an ...

  7. Android IntentService完全解析 当Service遇到Handler

    一 概述 大家都清楚,在Android的开发中,凡是遇到耗时的操作尽可能的会交给Service去做,比如我们上传多张图,上传的过程用户可能将应用置于后台,然后干别的去了,我们的Activity就很可能 ...

  8. Android Volley完全解析

    1. Volley简介 我们平时在开发Android应用的时候不可避免地都需要用到网络技术,而多数情况下应用程序都会使用HTTP协议来发送和接收网络数据.Android系统中主要提供了两种方式来进行H ...

  9. android源码解析(十七)-->Activity布局加载流程

    版权声明:本文为博主原创文章,未经博主允许不得转载. 好吧,终于要开始讲讲Activity的布局加载流程了,大家都知道在Android体系中Activity扮演了一个界面展示的角色,这也是它与andr ...

随机推荐

  1. hdu 4704 Sum

    思路:对于给定的n,s(i)即将n分解为i个数的组合数,也就是在n-1个位置插入i-1个板即C(n-1,i-1); ∑S=2^(n-1); phi(1000000007)=1000000006; 对于 ...

  2. JS事件(事件冒泡和事件捕获)

    事件流:描述的是在页面中接收事件的顺序 事件冒泡:由最具体的元素接收,然后逐级向上传播至最不具体的元素的节点(文档) 事件捕获:最不具体的节点先接收事件,而最具体的节点应该是最后接收事件 DOM中:用 ...

  3. 使用CXF暴露您的REST服务

    使用CXF暴露您的REST服务 REST应用服务器SpringBeanServlet  1.  前言 现在互联网Open API流行,将您的Web应用也可以开放Open API给其他第三方使用.达到一 ...

  4. JavaMail如何保证邮件发送成功

    使用过JavaMail的api发送邮件的人可能会有这样一个疑惑:我如何知道我调用该api发送的邮件是否成功呢?一般的开放的api给我们调用都会有个返回值或者状态码,来告诉我们执行成功与否.但是Java ...

  5. Ubuntu 安装mod_python配置Apache2

    在Ubuntu上搭建Python运行环境,mod_python是不可少的(据说mod_swgi也是可以的,没有亲测).使用命令安装mod_python. 安装: apt-get install lib ...

  6. $.post()

    定义和用法 post() 方法通过 HTTP POST 请求从服务器载入数据. jQuery.post(url,data,success(data, textStatus, jqXHR),dataTy ...

  7. Android仿iPhone晃动撤销输入功能(微信摇一摇功能)

    重力传感器微信摇一摇SensorMannager自定义alertdialogSensorEventListener 很多程序中我们可能会输入长文本内容,比如短信,写便笺等,如果想一次性撤销所有的键入内 ...

  8. Python3 学习第二弹: 字符串String

    字符串表示问题 常见用法 '' 与 "" 就不提了 一些特殊用法 三引号:接收多行字符串的输入 >>>print('''Oh my God!''') Oh my ...

  9. Java与正则表达式

    Java与正则表达式 标签: Java基础 正则 正如正则的名字所显示的是描述了一个规则, 通过这个规则去匹配字符串. 学习正则就是学习正则表达式的语法规则 正则语法 普通字符 字母, 数字, 汉字, ...

  10. c#里面的namespace基础(一)

    我现在感到学好C#就是就是要知道,C#的基本语法,C#的新的特点,C#能干什么! 其中我感到不管如何,NAMESPACE都是很关键的,可以说不是只对C#而言,而是整个.NET都是由NAMESPACE组 ...