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. Ubuntu环境下手动配置ant

    配置ant 1. 下载ant(http://ant.apache.org/bindownload.cgi) 例如我下载的是:apache-ant-1.9.4-bin.tar.gz 解压ant,将文件夹 ...

  2. 在PowerDesigner中设计物理模型3——视图、存储过程和函数

    原文:在PowerDesigner中设计物理模型3--视图.存储过程和函数 视图 在SQL Server中视图定义了一个SQL查询,一个查询中可以查询一个表也可以查询多个表,在PD中定义视图与在SQL ...

  3. IntelliJ IDEA 15开发Java Maven项目

    1.安装好之后开始创建项目

  4. 58. Length of Last Word

    题目: Given a string s consists of upper/lower-case alphabets and empty space characters ' ', return t ...

  5. iOS:自定义工具栏、导航栏、标签栏

    工具栏为UIToolBar,导航栏UINavigationBar,标签栏UITabBar.它们的样式基本上时差不多的,唯一的一点区别就是,工具栏一般需要自己去创建,然后添加到视图中,而导航栏和标签栏不 ...

  6. 爬虫Larbin解析(一)——Larbin配置与使用

    介绍 功能:网络爬虫 开发语言:c++ 开发者:Sébastien Ailleret(法国) 特点:只抓取网页,高效(一个简单的larbin的爬虫可以每天获取500万的网页) 安装 安装平台:Ubun ...

  7. Eclipse groovy in action

    Eclipse :Version: Juno Service Release 2GrEclipse plugins:http://dist.springsource.org/release/GRECL ...

  8. SqlServer 如何以脚本形式导出数据

    你是否遇到这样的情况,在公司导出一个数据库,回到家里导入自己的电脑里,然后发现数据库版本不匹配,这真是一个悲剧. 那么以下这个方法就可以避免这个悲剧,将数据以脚本的形式导出,这样灵活性更好. 1.选择 ...

  9. 内存分配方法 kmalloc()、vmalloc()、__get_free_pages()

    Copyright: 该文章版权由潘云登所有.可在非商业目的下任意传播和复制. 对于商业目的下对本文的任何行为需经作者同意. kmalloc #include <linux/slab.h> ...

  10. hibernate--关联映射(多对一,一对一)

    多对一 关联映射 --- many-to-one 场景:用户和组:从用户角度来,多个用户属于一个组(多对一 关联) 使用hibernate开发的思路:先建立对象模型(领域模型),把实体抽取出来. 目前 ...