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. hdu1116

    http://acm.hdu.edu.cn/showproblem.php?pid=1116 #include<stdio.h> #include<math.h> #inclu ...

  2. python对json的相关操作

    什么是json: JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.易于人阅读和编写.同时也易于机器解析和生成.它基于JavaScript Programm ...

  3. kmeans理解

    最近看到Andrew Ng的一篇论文,文中用到了Kmeans和DL结合的思想,突然发现自己对ML最基本的聚类算法都不清楚,于是着重的看了下Kmeans,并在网上找了程序跑了下. kmeans是unsu ...

  4. *[topcoder]LongWordsDiv2

    http://community.topcoder.com/stat?c=problem_statement&pm=13147 此题关键在于发现ABAB的组合最多有26*26种,可以穷举,然后 ...

  5. ActiveMQ使用教程

    ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线.ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,尽管JMS规范出台已经是很久 ...

  6. import java.util.Scanner;

    一.扫描控制台输入     当通过new Scanner(System.in)创建一个Scanner,控制台会一直等待输入,,,,,,,直到敲回车键结束,把所输入的内容传给Scanner,作为扫描对象 ...

  7. C++:类模板与模板类

    6.3 类模板和模板类 所谓类模板,实际上是建立一个通用类,其数据成员.成员函数的返回值类型和形参类型不具体指定,用一个虚拟的类型来代表.使用类模板定义对象时,系统会实参的类型来取代类模板中虚拟类型从 ...

  8. 1401 - Remember the Word

    注意到单词的长度最长100,其实最糟糕复杂度应该能到O(300005*100),需要注意的是在字典树上匹配单词时,一旦不匹配,则后面的就不会匹配,需要break出来(这个害我TLE查了半天,日!),还 ...

  9. ios高版本SDK在低版本真机调试

    将build settings的ios deployment target改为对应真机系统版本即可

  10. MySql开启跟踪

    使用 show variables like '%log%'; 查看general_log.log_output.general_log_file 更新为 set global general_log ...