36、Android Bitmap 全面解析
Android Bitmap 全面解析(一)加载大尺寸图片
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
<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 全面解析的更多相关文章
- Android Bitmap 全面解析(四)图片处理效果对比 ...
对比对象: UIL Volley 官方教程中的方法(此系列教程一里介绍的,ImageLoader的处理方法和官方的差不多) -------------------------------------- ...
- Android Bitmap 全面解析(一)加载大尺寸图片
压缩原因:1.imageview大小如果是200*300那么加载个2000*3000的图片到内存中显然是浪费可耻滴行为;2.最重要的是图片过大时直接加载原图会造成OOM异常(out of memory ...
- Android Bitmap 全面解析(二)加载多张图片的缓存处理
一般少量图片是很少出现OOM异常的,除非单张图片过~大~ 那么就可以用教程一里面的方法了通常应用场景是listview列表加载多张图片,为了提高效率一般要缓存一部分图片,这样方便再次查看时能快速显示~ ...
- Android Bitmap变迁与原理解析(4.x-8.x)
App开发不可避免的要和图片打交道,由于其占用内存非常大,管理不当很容易导致内存不足,最后OOM,图片的背后其实是Bitmap,它是Android中最能吃内存的对象之一,也是很多OOM的元凶,不过,在 ...
- Android OkHttp完全解析 --zz
参考文章 https://github.com/square/okhttp http://square.github.io/okhttp/ 泡网OkHttp使用教程 Android OkHttp完全解 ...
- Android OkHttp完全解析 是时候来了解OkHttp了
Android OkHttp完全解析 是时候来了解OkHttp了 标签: AndroidOkHttp 2015-08-24 15:36 316254人阅读 评论(306) 收藏 举报 分类: [an ...
- Android IntentService完全解析 当Service遇到Handler
一 概述 大家都清楚,在Android的开发中,凡是遇到耗时的操作尽可能的会交给Service去做,比如我们上传多张图,上传的过程用户可能将应用置于后台,然后干别的去了,我们的Activity就很可能 ...
- Android Volley完全解析
1. Volley简介 我们平时在开发Android应用的时候不可避免地都需要用到网络技术,而多数情况下应用程序都会使用HTTP协议来发送和接收网络数据.Android系统中主要提供了两种方式来进行H ...
- android源码解析(十七)-->Activity布局加载流程
版权声明:本文为博主原创文章,未经博主允许不得转载. 好吧,终于要开始讲讲Activity的布局加载流程了,大家都知道在Android体系中Activity扮演了一个界面展示的角色,这也是它与andr ...
随机推荐
- Jmeter 快速入门教程(三-1) --添加响应断言(即loadrunner中所指的检查点)
[版权所有: whoistester.com & jmeter.cf] 上一节课,我们创建了一个测试场景,并进行了少量vuser的负载测试. 有时候我们执行了测试,但是发现并不是所有事务都执行 ...
- 李洪强iOS开发之OC语言构造方法
OC语言构造方法 一.构造方法 (一)构造方法的调用 完整的创建一个可用的对象:Person *p=[Person new]; New方法的内部会分别调用两个方法来完成2件事情,1)使用alloc方法 ...
- HTML5入门1---Canvas画布
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- python 利用imap接收邮件,并保存附件
def SaveAttachImap():# login the imap server ,retrive the new mails ,and download the attachments. ...
- 你真的了解try{ return }finally{}中的return?
你真的了解try{ return }finally{}中的return? 今天去逛论坛 时发现了一个很有趣的问题: 谁能给我我解释一下这段程序的结果为什么是:2.而不是:3 代码如下: class ...
- 基于SMB协议的共享文件读写 博客分类: Java
基于SMB协议的共享文件读写 博客分类: Java 一.SMB协议 SMB协议是基于TCP-NETBIOS下的,一般端口使用为139,445. 服务器信息块(SMB)协议是一种IBM协议,用于在计 ...
- 转AOP 介绍
来自:http://blog.csdn.net/a906998248/article/details/7514969 这篇也不错,详细介绍了CGLIP http://blog.jobbole.com/ ...
- hadoop拾遗(三)---- 多种输入
虽然一个MapReduce作业的输入可能包含多个输入文件(由文件glob.过滤器和路径组成),但所有文件都由同一个InputFormat和同一个Mapper来解释.然而,数据格式往往会随时间而演变,所 ...
- trim合理和谐
今天早上,到公司,噩耗传来.上周的上线的功能出现问题,后台mis中有数据不能保存了. 经过紧张的查找,还是我的问题.有一个查重操作,在查重前,会比对新旧值,新值顺手trim了.旧值直接保存了. 在比较 ...
- input默认提示取消
input 输入框有提示功能,当你之前输入过一些内容,你下次打入相关字符的时候,默认会有之前输入的一些相关的字符的提示,这个提示一般来说还是很好的,但是,有时候,我们想自己输入,不想要提示. 如果不需 ...