在Android中对大图片进行缩放真的很不尽如人意,不知道是不是我的方法不对。下面我列出3种对图片缩放的方法,并给出相应速度。请高人指教。
第一种是BitmapFactory和BitmapFactory.Options。
首先,BitmapFactory.Options有几个Fields很有用:
inJustDecodeBounds:If set to true, the decoder will return null (no bitmap), but the out...
也就是说,当inJustDecodeBounds设成true时,bitmap并不加载到内存,这样效率很高哦。而这时,你可以获得bitmap的高、宽等信息。
outHeight:The resulting height of the bitmap, set independent of the state of inJustDecodeBounds.
outWidth:The resulting width of the bitmap, set independent of the state of inJustDecodeBounds.
看到了吧,上面3个变量是相关联的哦。
inSampleSize :
If set to a value > 1, requests the decoder to subsample the original image, returning a smaller image to save memory.
这就是用来做缩放比的。这里有个技巧:
inSampleSize=(outHeight/Height+outWidth/Width)/2
实践证明,这样缩放出来的图片还是很好的。
最后用BitmapFactory.decodeFile(path, options)生成。
由于只是对bitmap加载到内存一次,所以效率比较高。解析速度快。
第二种是使用Bitmap加Matrix来缩放。
首先要获得原bitmap,再从原bitmap的基础上生成新图片。这样效率很低。
第三种是用2.2新加的类ThumbnailUtils来做。
让我们新看看这个类,从API中来看,此类就三个静态方法:createVideoThumbnail、extractThumbnail(Bitmap source, int width, int height, int options)、extractThumbnail(Bitmap source, int width, int height)。
我这里使用了第三个方法。再看看它的源码,下面会附上。是上面我们用到的BitmapFactory.Options和Matrix等经过人家一阵加工而成。
效率好像比第二种方法高一点点。
下面是我的例子:
-
<?xml version="1.0" encoding="utf-8"?>
-
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-
android:orientation="vertical"
-
android:layout_width="fill_parent"
-
android:layout_height="fill_parent"
-
>
-
-
<ImageView
-
android:id="@+id/imageShow"
-
android:layout_width="wrap_content"
-
android:layout_height="wrap_content"
-
/>
-
<ImageView
-
android:id="@+id/image2"
-
android:layout_width="wrap_content"
-
android:layout_height="wrap_content"
-
/>
-
<TextView
-
android:id="@+id/text"
-
android:layout_width="fill_parent"
-
android:layout_height="wrap_content"
-
android:text="@string/hello"
-
/>
-
</LinearLayout>
-
package com.linc.ResolvePicture;
-
-
import java.io.File;
-
import java.io.FileNotFoundException;
-
import java.io.FileOutputStream;
-
import java.io.IOException;
-
-
import android.app.Activity;
-
import android.graphics.Bitmap;
-
import android.graphics.BitmapFactory;
-
import android.graphics.Matrix;
-
import android.graphics.drawable.BitmapDrawable;
-
import android.graphics.drawable.Drawable;
-
import android.media.ThumbnailUtils;
-
import android.os.Bundle;
-
import android.util.Log;
-
import android.widget.ImageView;
-
import android.widget.TextView;
-
-
public class ResolvePicture extends Activity {
-
private static String tag="ResolvePicture";
-
Drawable bmImg;
-
ImageView imView;
-
ImageView imView2;
-
TextView text;
-
String theTime;
-
long start, stop;
-
-
@Override
-
public void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
setContentView(R.layout.main);
-
-
text=(TextView)findViewById(R.id.text);
-
-
imView=(ImageView) findViewById(R.id.imageShow);
-
imView2=(ImageView) findViewById(R.id.image2);
-
-
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
-
R.drawable.pic);
-
-
start=System.currentTimeMillis();
-
-
-
-
imView2.setImageDrawable(resizeImage2("/sdcard/2.jpeg", 200, 100));
-
-
stop=System.currentTimeMillis();
-
-
String theTime= String.format("\n1 iterative: (%d msec)",
-
stop - start);
-
-
start=System.currentTimeMillis();
-
imView.setImageBitmap(ThumbnailUtils.extractThumbnail(bitmap,200,100));
-
-
stop=System.currentTimeMillis();
-
-
theTime+= String.format("\n2 iterative: (%d msec)",
-
stop - start);
-
-
text.setText(theTime);
-
}
-
-
-
public static Drawable resizeImage(Bitmap bitmap, int w, int h)
-
{
-
Bitmap BitmapOrg = bitmap;
-
int width = BitmapOrg.getWidth();
-
int height = BitmapOrg.getHeight();
-
int newWidth = w;
-
int newHeight = h;
-
-
float scaleWidth = ((float) newWidth) / width;
-
float scaleHeight = ((float) newHeight) / height;
-
-
Matrix matrix = new Matrix();
-
matrix.postScale(scaleWidth, scaleHeight);
-
-
-
Bitmap resizedBitmap = Bitmap.createBitmap(BitmapOrg, 0, 0, width,
-
height, matrix, true);
-
return new BitmapDrawable(resizedBitmap);
-
}
-
-
-
public static Drawable resizeImage2(String path,
-
int width,int height)
-
{
-
BitmapFactory.Options options = new BitmapFactory.Options();
-
options.inJustDecodeBounds = true;
-
BitmapFactory.decodeFile(path,options);
-
int outWidth = options.outWidth;
-
int outHeight = options.outHeight;
-
options.inDither = false;
-
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
-
options.inSampleSize = 1;
-
-
if (outWidth != 0 && outHeight != 0 && width != 0 && height != 0)
-
{
-
int sampleSize=(outWidth/width+outHeight/height)/2;
-
Log.d(tag, "sampleSize = " + sampleSize);
-
options.inSampleSize = sampleSize;
-
}
-
-
options.inJustDecodeBounds = false;
-
return new BitmapDrawable(BitmapFactory.decodeFile(path, options));
-
}
-
-
-
private void saveThePicture(Bitmap bitmap)
-
{
-
File file=new File("/sdcard/2.jpeg");
-
try
-
{
-
FileOutputStream fos=new FileOutputStream(file);
-
if(bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos))
-
{
-
fos.flush();
-
fos.close();
-
}
-
}
-
catch(FileNotFoundException e1)
-
{
-
e1.printStackTrace();
-
}
-
catch(IOException e2)
-
{
-
e2.printStackTrace();
-
}
-
}
-
}
ThumbnailUtils源码:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
package android.media;
-
-
import android.content.ContentResolver;
-
import android.content.ContentUris;
-
import android.content.ContentValues;
-
import android.database.Cursor;
-
import android.graphics.Bitmap;
-
import android.graphics.BitmapFactory;
-
import android.graphics.Canvas;
-
import android.graphics.Matrix;
-
import android.graphics.Rect;
-
import android.media.MediaMetadataRetriever;
-
import android.media.MediaFile.MediaFileType;
-
import android.net.Uri;
-
import android.os.ParcelFileDescriptor;
-
import android.provider.BaseColumns;
-
import android.provider.MediaStore.Images;
-
import android.provider.MediaStore.Images.Thumbnails;
-
import android.util.Log;
-
-
import java.io.FileInputStream;
-
import java.io.FileDescriptor;
-
import java.io.IOException;
-
import java.io.OutputStream;
-
-
-
-
-
-
public class ThumbnailUtils {
-
private static final String TAG = "ThumbnailUtils";
-
-
-
private static final int MAX_NUM_PIXELS_THUMBNAIL = 512 * 384;
-
private static final int MAX_NUM_PIXELS_MICRO_THUMBNAIL = 128 * 128;
-
private static final int UNCONSTRAINED = -1;
-
-
-
private static final int OPTIONS_NONE = 0x0;
-
private static final int OPTIONS_SCALE_UP = 0x1;
-
-
-
-
-
-
public static final int OPTIONS_RECYCLE_INPUT = 0x2;
-
-
-
-
-
-
public static final int TARGET_SIZE_MINI_THUMBNAIL = 320;
-
-
-
-
-
-
public static final int TARGET_SIZE_MICRO_THUMBNAIL = 96;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
public static Bitmap createImageThumbnail(String filePath, int kind) {
-
boolean wantMini = (kind == Images.Thumbnails.MINI_KIND);
-
int targetSize = wantMini
-
? TARGET_SIZE_MINI_THUMBNAIL
-
: TARGET_SIZE_MICRO_THUMBNAIL;
-
int maxPixels = wantMini
-
? MAX_NUM_PIXELS_THUMBNAIL
-
: MAX_NUM_PIXELS_MICRO_THUMBNAIL;
-
SizedThumbnailBitmap sizedThumbnailBitmap = new SizedThumbnailBitmap();
-
Bitmap bitmap = null;
-
MediaFileType fileType = MediaFile.getFileType(filePath);
-
if (fileType != null && fileType.fileType == MediaFile.FILE_TYPE_JPEG) {
-
createThumbnailFromEXIF(filePath, targetSize, maxPixels, sizedThumbnailBitmap);
-
bitmap = sizedThumbnailBitmap.mBitmap;
-
}
-
-
if (bitmap == null) {
-
try {
-
FileDescriptor fd = new FileInputStream(filePath).getFD();
-
BitmapFactory.Options options = new BitmapFactory.Options();
-
options.inSampleSize = 1;
-
options.inJustDecodeBounds = true;
-
BitmapFactory.decodeFileDescriptor(fd, null, options);
-
if (options.mCancel || options.outWidth == -1
-
|| options.outHeight == -1) {
-
return null;
-
}
-
options.inSampleSize = computeSampleSize(
-
options, targetSize, maxPixels);
-
options.inJustDecodeBounds = false;
-
-
options.inDither = false;
-
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
-
bitmap = BitmapFactory.decodeFileDescriptor(fd, null, options);
-
} catch (IOException ex) {
-
Log.e(TAG, "", ex);
-
}
-
}
-
-
if (kind == Images.Thumbnails.MICRO_KIND) {
-
-
bitmap = extractThumbnail(bitmap,
-
TARGET_SIZE_MICRO_THUMBNAIL,
-
TARGET_SIZE_MICRO_THUMBNAIL, OPTIONS_RECYCLE_INPUT);
-
}
-
return bitmap;
-
}
-
-
-
-
-
-
-
-
-
public static Bitmap createVideoThumbnail(String filePath, int kind) {
-
Bitmap bitmap = null;
-
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
-
try {
-
retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY);
-
retriever.setDataSource(filePath);
-
bitmap = retriever.captureFrame();
-
} catch (IllegalArgumentException ex) {
-
-
} catch (RuntimeException ex) {
-
-
} finally {
-
try {
-
retriever.release();
-
} catch (RuntimeException ex) {
-
-
}
-
}
-
if (kind == Images.Thumbnails.MICRO_KIND && bitmap != null) {
-
bitmap = extractThumbnail(bitmap,
-
TARGET_SIZE_MICRO_THUMBNAIL,
-
TARGET_SIZE_MICRO_THUMBNAIL,
-
OPTIONS_RECYCLE_INPUT);
-
}
-
return bitmap;
-
}
-
-
-
-
-
-
-
-
-
public static Bitmap extractThumbnail(
-
Bitmap source, int width, int height) {
-
return extractThumbnail(source, width, height, OPTIONS_NONE);
-
}
-
-
-
-
-
-
-
-
-
-
public static Bitmap extractThumbnail(
-
Bitmap source, int width, int height, int options) {
-
if (source == null) {
-
return null;
-
}
-
-
float scale;
-
if (source.getWidth() < source.getHeight()) {
-
scale = width / (float) source.getWidth();
-
} else {
-
scale = height / (float) source.getHeight();
-
}
-
Matrix matrix = new Matrix();
-
matrix.setScale(scale, scale);
-
Bitmap thumbnail = transform(matrix, source, width, height,
-
OPTIONS_SCALE_UP | options);
-
return thumbnail;
-
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
private static int computeSampleSize(BitmapFactory.Options options,
-
int minSideLength, int maxNumOfPixels) {
-
int initialSize = computeInitialSampleSize(options, minSideLength,
-
maxNumOfPixels);
-
-
int roundedSize;
-
if (initialSize <= 8 ) {
-
roundedSize = 1;
-
while (roundedSize < initialSize) {
-
roundedSize <<= 1;
-
}
-
} else {
-
roundedSize = (initialSize + 7) / 8 * 8;
-
}
-
-
return roundedSize;
-
}
-
-
private static int computeInitialSampleSize(BitmapFactory.Options options,
-
int minSideLength, int maxNumOfPixels) {
-
double w = options.outWidth;
-
double h = options.outHeight;
-
-
int lowerBound = (maxNumOfPixels == UNCONSTRAINED) ? 1 :
-
(int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));
-
int upperBound = (minSideLength == UNCONSTRAINED) ? 128 :
-
(int) Math.min(Math.floor(w / minSideLength),
-
Math.floor(h / minSideLength));
-
-
if (upperBound < lowerBound) {
-
-
return lowerBound;
-
}
-
-
if ((maxNumOfPixels == UNCONSTRAINED) &&
-
(minSideLength == UNCONSTRAINED)) {
-
return 1;
-
} else if (minSideLength == UNCONSTRAINED) {
-
return lowerBound;
-
} else {
-
return upperBound;
-
}
-
}
-
-
-
-
-
-
-
-
-
-
private static Bitmap makeBitmap(int minSideLength, int maxNumOfPixels,
-
Uri uri, ContentResolver cr, ParcelFileDescriptor pfd,
-
BitmapFactory.Options options) {
-
Bitmap b = null;
-
try {
-
if (pfd == null) pfd = makeInputStream(uri, cr);
-
if (pfd == null) return null;
-
if (options == null) options = new BitmapFactory.Options();
-
-
FileDescriptor fd = pfd.getFileDescriptor();
-
options.inSampleSize = 1;
-
options.inJustDecodeBounds = true;
-
BitmapFactory.decodeFileDescriptor(fd, null, options);
-
if (options.mCancel || options.outWidth == -1
-
|| options.outHeight == -1) {
-
return null;
-
}
-
options.inSampleSize = computeSampleSize(
-
options, minSideLength, maxNumOfPixels);
-
options.inJustDecodeBounds = false;
-
-
options.inDither = false;
-
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
-
b = BitmapFactory.decodeFileDescriptor(fd, null, options);
-
} catch (OutOfMemoryError ex) {
-
Log.e(TAG, "Got oom exception ", ex);
-
return null;
-
} finally {
-
closeSilently(pfd);
-
}
-
return b;
-
}
-
-
private static void closeSilently(ParcelFileDescriptor c) {
-
if (c == null) return;
-
try {
-
c.close();
-
} catch (Throwable t) {
-
-
}
-
}
-
-
private static ParcelFileDescriptor makeInputStream(
-
Uri uri, ContentResolver cr) {
-
try {
-
return cr.openFileDescriptor(uri, "r");
-
} catch (IOException ex) {
-
return null;
-
}
-
}
-
-
-
-
-
private static Bitmap transform(Matrix scaler,
-
Bitmap source,
-
int targetWidth,
-
int targetHeight,
-
int options) {
-
boolean scaleUp = (options & OPTIONS_SCALE_UP) != 0;
-
boolean recycle = (options & OPTIONS_RECYCLE_INPUT) != 0;
-
-
int deltaX = source.getWidth() - targetWidth;
-
int deltaY = source.getHeight() - targetHeight;
-
if (!scaleUp && (deltaX < 0 || deltaY < 0)) {
-
-
-
-
-
-
-
Bitmap b2 = Bitmap.createBitmap(targetWidth, targetHeight,
-
Bitmap.Config.ARGB_8888);
-
Canvas c = new Canvas(b2);
-
-
int deltaXHalf = Math.max(0, deltaX / 2);
-
int deltaYHalf = Math.max(0, deltaY / 2);
-
Rect src = new Rect(
-
deltaXHalf,
-
deltaYHalf,
-
deltaXHalf + Math.min(targetWidth, source.getWidth()),
-
deltaYHalf + Math.min(targetHeight, source.getHeight()));
-
int dstX = (targetWidth - src.width()) / 2;
-
int dstY = (targetHeight - src.height()) / 2;
-
Rect dst = new Rect(
-
dstX,
-
dstY,
-
targetWidth - dstX,
-
targetHeight - dstY);
-
c.drawBitmap(source, src, dst, null);
-
if (recycle) {
-
source.recycle();
-
}
-
return b2;
-
}
-
float bitmapWidthF = source.getWidth();
-
float bitmapHeightF = source.getHeight();
-
-
float bitmapAspect = bitmapWidthF / bitmapHeightF;
-
float viewAspect = (float) targetWidth / targetHeight;
-
-
if (bitmapAspect > viewAspect) {
-
float scale = targetHeight / bitmapHeightF;
-
if (scale < .9F || scale > 1F) {
-
scaler.setScale(scale, scale);
-
} else {
-
scaler = null;
-
}
-
} else {
-
float scale = targetWidth / bitmapWidthF;
-
if (scale < .9F || scale > 1F) {
-
scaler.setScale(scale, scale);
-
} else {
-
scaler = null;
-
}
-
}
-
-
Bitmap b1;
-
if (scaler != null) {
-
-
b1 = Bitmap.createBitmap(source, 0, 0,
-
source.getWidth(), source.getHeight(), scaler, true);
-
} else {
-
b1 = source;
-
}
-
-
if (recycle && b1 != source) {
-
source.recycle();
-
}
-
-
int dx1 = Math.max(0, b1.getWidth() - targetWidth);
-
int dy1 = Math.max(0, b1.getHeight() - targetHeight);
-
-
Bitmap b2 = Bitmap.createBitmap(
-
b1,
-
dx1 / 2,
-
dy1 / 2,
-
targetWidth,
-
targetHeight);
-
-
if (b2 != b1) {
-
if (recycle || b1 != source) {
-
b1.recycle();
-
}
-
}
-
-
return b2;
-
}
-
-
-
-
-
-
-
-
-
-
private static class SizedThumbnailBitmap {
-
public byte[] mThumbnailData;
-
public Bitmap mBitmap;
-
public int mThumbnailWidth;
-
public int mThumbnailHeight;
-
}
-
-
-
-
-
-
-
private static void createThumbnailFromEXIF(String filePath, int targetSize,
-
int maxPixels, SizedThumbnailBitmap sizedThumbBitmap) {
-
if (filePath == null) return;
-
-
ExifInterface exif = null;
-
byte [] thumbData = null;
-
try {
-
exif = new ExifInterface(filePath);
-
if (exif != null) {
-
thumbData = exif.getThumbnail();
-
}
-
} catch (IOException ex) {
-
Log.w(TAG, ex);
-
}
-
-
BitmapFactory.Options fullOptions = new BitmapFactory.Options();
-
BitmapFactory.Options exifOptions = new BitmapFactory.Options();
-
int exifThumbWidth = 0;
-
int fullThumbWidth = 0;
-
-
-
if (thumbData != null) {
-
exifOptions.inJustDecodeBounds = true;
-
BitmapFactory.decodeByteArray(thumbData, 0, thumbData.length, exifOptions);
-
exifOptions.inSampleSize = computeSampleSize(exifOptions, targetSize, maxPixels);
-
exifThumbWidth = exifOptions.outWidth / exifOptions.inSampleSize;
-
}
-
-
-
fullOptions.inJustDecodeBounds = true;
-
BitmapFactory.decodeFile(filePath, fullOptions);
-
fullOptions.inSampleSize = computeSampleSize(fullOptions, targetSize, maxPixels);
-
fullThumbWidth = fullOptions.outWidth / fullOptions.inSampleSize;
-
-
-
if (thumbData != null && exifThumbWidth >= fullThumbWidth) {
-
int width = exifOptions.outWidth;
-
int height = exifOptions.outHeight;
-
exifOptions.inJustDecodeBounds = false;
-
sizedThumbBitmap.mBitmap = BitmapFactory.decodeByteArray(thumbData, 0,
-
thumbData.length, exifOptions);
-
if (sizedThumbBitmap.mBitmap != null) {
-
sizedThumbBitmap.mThumbnailData = thumbData;
-
sizedThumbBitmap.mThumbnailWidth = width;
-
sizedThumbBitmap.mThumbnailHeight = height;
-
}
-
} else {
-
fullOptions.inJustDecodeBounds = false;
-
sizedThumbBitmap.mBitmap = BitmapFactory.decodeFile(filePath, fullOptions);
-
}
-
}
-
}
Android--生成缩略图------方法总结
原文:http://blog.csdn.net/copy_yuan/article/details/51371664