android读取sd卡图片并进行缩放操作

在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;   
 /** Called when the activity is first created. */ 
 @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();  
 
//        imView.setImageDrawable(resizeImage(bitmap, 300, 100));  
 
        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));//2.2才加进来的新类,简单易用 
//        imView.setImageDrawable(resizeImage(bitmap, 30, 30));  
        stop=System.currentTimeMillis();  
 
         theTime+= String.format("\n2 iterative: (%d msec)",    
                stop - start);   
 
        text.setText(theTime);  
    }  
 
 //使用Bitmap加Matrix来缩放 
 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);    
 // if you want to rotate the Bitmap    
 // matrix.postRotate(45);    
        Bitmap resizedBitmap = Bitmap.createBitmap(BitmapOrg, 0, 0, width,    
                        height, matrix, true);    
 return new BitmapDrawable(resizedBitmap);    
    }  
 
 //使用BitmapFactory.Options的inSampleSize参数来缩放 
 public static Drawable resizeImage2(String path,  
 int width,int height)   
    {  
        BitmapFactory.Options options = new BitmapFactory.Options();  
        options.inJustDecodeBounds = true;//不加载bitmap到内存中 
        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源码:

/* 
 * Copyright (C) 2009 The Android Open Source Project 
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0 
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License. 
 */ 
 
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;  
 
/** 
 * Thumbnail generation routines for media provider. 
 */ 
 
public class ThumbnailUtils {  
 private static final String TAG = "ThumbnailUtils";  
 
 /* Maximum pixels size for created bitmap. */ 
 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;  
 
 /* Options used internally. */ 
 private static final int OPTIONS_NONE = 0x0;  
 private static final int OPTIONS_SCALE_UP = 0x1;  
 
 /** 
     * Constant used to indicate we should recycle the input in 
     * {@link #extractThumbnail(Bitmap, int, int, int)} unless the output is the input. 
     */ 
 public static final int OPTIONS_RECYCLE_INPUT = 0x2;  
 
 /** 
     * Constant used to indicate the dimension of mini thumbnail. 
     * @hide Only used by media framework and media provider internally. 
     */ 
 public static final int TARGET_SIZE_MINI_THUMBNAIL = 320;  
 
 /** 
     * Constant used to indicate the dimension of micro thumbnail. 
     * @hide Only used by media framework and media provider internally. 
     */ 
 public static final int TARGET_SIZE_MICRO_THUMBNAIL = 96;  
 
 /** 
     * This method first examines if the thumbnail embedded in EXIF is bigger than our target 
     * size. If not, then it'll create a thumbnail from original image. Due to efficiency 
     * consideration, we want to let MediaThumbRequest avoid calling this method twice for 
     * both kinds, so it only requests for MICRO_KIND and set saveImage to true. 
     * 
     * This method always returns a "square thumbnail" for MICRO_KIND thumbnail. 
     * 
     * @param filePath the path of image file 
     * @param kind could be MINI_KIND or MICRO_KIND 
     * @return Bitmap 
     * 
     * @hide This method is only used by media framework and media provider internally. 
     */ 
 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) {  
 // now we make it a "square thumbnail" for MICRO_KIND thumbnail 
            bitmap = extractThumbnail(bitmap,  
                    TARGET_SIZE_MICRO_THUMBNAIL,  
                    TARGET_SIZE_MICRO_THUMBNAIL, OPTIONS_RECYCLE_INPUT);  
        }  
 return bitmap;  
    }  
 
 /** 
     * Create a video thumbnail for a video. May return null if the video is 
     * corrupt or the format is not supported. 
     * 
     * @param filePath the path of video file 
     * @param kind could be MINI_KIND or MICRO_KIND 
     */ 
 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) {  
 // Assume this is a corrupt video file 
        } catch (RuntimeException ex) {  
 // Assume this is a corrupt video file. 
        } finally {  
 try {  
                retriever.release();  
            } catch (RuntimeException ex) {  
 // Ignore failures while cleaning up. 
            }  
        }  
 if (kind == Images.Thumbnails.MICRO_KIND && bitmap != null) {  
            bitmap = extractThumbnail(bitmap,  
                    TARGET_SIZE_MICRO_THUMBNAIL,  
                    TARGET_SIZE_MICRO_THUMBNAIL,  
                    OPTIONS_RECYCLE_INPUT);  
        }  
 return bitmap;  
    }  
 
 /** 
     * Creates a centered bitmap of the desired size. 
     * 
     * @param source original bitmap source 
     * @param width targeted width 
     * @param height targeted height 
     */ 
 public static Bitmap extractThumbnail(  
            Bitmap source, int width, int height) {  
 return extractThumbnail(source, width, height, OPTIONS_NONE);  
    }  
 
 /** 
     * Creates a centered bitmap of the desired size. 
     * 
     * @param source original bitmap source 
     * @param width targeted width 
     * @param height targeted height 
     * @param options options used during thumbnail extraction 
     */ 
 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;  
    }  
 
 /* 
     * Compute the sample size as a function of minSideLength 
     * and maxNumOfPixels. 
     * minSideLength is used to specify that minimal width or height of a 
     * bitmap. 
     * maxNumOfPixels is used to specify the maximal size in pixels that is 
     * tolerable in terms of memory usage. 
     * 
     * The function returns a sample size based on the constraints. 
     * Both size and minSideLength can be passed in as IImage.UNCONSTRAINED, 
     * which indicates no care of the corresponding constraint. 
     * The functions prefers returning a sample size that 
     * generates a smaller bitmap, unless minSideLength = IImage.UNCONSTRAINED. 
     * 
     * Also, the function rounds up the sample size to a power of 2 or multiple 
     * of 8 because BitmapFactory only honors sample size this way. 
     * For example, BitmapFactory downsamples an image by 2 even though the 
     * request is 3. So we round up the sample size to avoid OOM. 
     */ 
 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 the larger one when there is no overlapping zone. 
 return lowerBound;  
        }  
 
 if ((maxNumOfPixels == UNCONSTRAINED) &&  
                (minSideLength == UNCONSTRAINED)) {  
 return 1;  
        } else if (minSideLength == UNCONSTRAINED) {  
 return lowerBound;  
        } else {  
 return upperBound;  
        }  
    }  
 
 /** 
     * Make a bitmap from a given Uri, minimal side length, and maximum number of pixels. 
     * The image data will be read from specified pfd if it's not null, otherwise 
     * a new input stream will be created using specified ContentResolver. 
     * 
     * Clients are allowed to pass their own BitmapFactory.Options used for bitmap decoding. A 
     * new BitmapFactory.Options will be created if options is null. 
     */ 
 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) {  
 // do nothing 
      }  
    }  
 
 private static ParcelFileDescriptor makeInputStream(  
            Uri uri, ContentResolver cr) {  
 try {  
 return cr.openFileDescriptor(uri, "r");  
        } catch (IOException ex) {  
 return null;  
        }  
    }  
 
 /** 
     * Transform source Bitmap to targeted width and height. 
     */ 
 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)) {  
 /* 
            * In this case the bitmap is smaller, at least in one dimension, 
            * than the target.  Transform it by placing as much of the image 
            * as possible into the target and leaving the top/bottom or 
            * left/right (or both) black. 
            */ 
            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) {  
 // this is used for minithumb and crop, so we want to filter here. 
            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;  
    }  
 
 /** 
     * SizedThumbnailBitmap contains the bitmap, which is downsampled either from 
     * the thumbnail in exif or the full image. 
     * mThumbnailData, mThumbnailWidth and mThumbnailHeight are set together only if mThumbnail 
     * is not null. 
     * 
     * The width/height of the sized bitmap may be different from mThumbnailWidth/mThumbnailHeight. 
     */ 
 private static class SizedThumbnailBitmap {  
 public byte[] mThumbnailData;  
 public Bitmap mBitmap;  
 public int mThumbnailWidth;  
 public int mThumbnailHeight;  
    }  
 
 /** 
     * Creates a bitmap by either downsampling from the thumbnail in EXIF or the full image. 
     * The functions returns a SizedThumbnailBitmap, 
     * which contains a downsampled bitmap and the thumbnail data in EXIF if exists. 
     */ 
 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;  
 
 // Compute exifThumbWidth. 
 if (thumbData != null) {  
            exifOptions.inJustDecodeBounds = true;  
            BitmapFactory.decodeByteArray(thumbData, 0, thumbData.length, exifOptions);  
            exifOptions.inSampleSize = computeSampleSize(exifOptions, targetSize, maxPixels);  
            exifThumbWidth = exifOptions.outWidth / exifOptions.inSampleSize;  
        }  
 
 // Compute fullThumbWidth. 
        fullOptions.inJustDecodeBounds = true;  
        BitmapFactory.decodeFile(filePath, fullOptions);  
        fullOptions.inSampleSize = computeSampleSize(fullOptions, targetSize, maxPixels);  
        fullThumbWidth = fullOptions.outWidth / fullOptions.inSampleSize;  
 
 // Choose the larger thumbnail as the returning sizedThumbBitmap. 
 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);  
        }  
    }  
}  

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏大内老A

MVVM(Knockout.js)的新尝试:多个Page,一个ViewModel

对于面向数据的Web应用来说,MVVM模式是一项不错的选择,它借助JS框架提供的“绑定”机制是我们无需过多关注UI(HTML)的细节,只需要操作绑定的数据源。M...

39190
来自专栏jianhuicode

Android注解学习(2)

    最近考试周没什么时间写,回归正题。前面的一次简单的讲了关于注解的的基础部分,这一次分析xutils注解封装的源码(奉上github源码)。     补充...

21150
来自专栏jianhuicode

Android注解学习(2)

    最近考试周没什么时间写,回归正题。前面的一次简单的讲了关于注解的的基础部分,这一次分析xutils注解封装的源码(奉上github源码)。     补充...

22190
来自专栏ASP.NET MVC5 后台权限管理系统

.Net 转战 Android 4.4 日常笔记(1)--工具及环境搭建

闲来没事做,还是想再学习一门新的技术,无论何时Android开发比Web的开发工资应该高40%,我也建议大家面对移动开发,我比较喜欢学习最新版本的,我有java...

19860
来自专栏ASP.NET MVC5 后台权限管理系统

.Net 转战 Android 4.4 日常笔记(2)--HelloWorld入门程序

我不知道人们为什么那么喜欢用HelloWorld来做为自己的第一个程序入门,为什么不是hello **其他的东西或者hi。 一、打开ADT 的Eclipse开发...

22070
来自专栏大内老A

WCF后续之旅(11): 关于并发、回调的线程关联性(Thread Affinity)

对于一般的多线程操作,比如异步地进行基于文件系统的IO操作;异步地调用Web Service;或者是异步地进行数据库访问等等,是和具体的线程无关的。也就是说,对...

21970
来自专栏软件

Appium Desktop 使用

Appium Desktop 元素定位 与Android的uiautomatorviewer一样,可进行元素定位,某些app 在 uiautomatorview...

39880
来自专栏ASP.NET MVC5 后台权限管理系统

.Net 转战 Android 4.4 日常笔记(3)--目录结构分析

看了创建项目后,出现的文件夹很多确实有点晕,不过经过简单的了解还是跟我们asp.net的目录有点相识滴。 ? 下面这张图,概括了主要的文件用途。其实也只需要了解...

20060
来自专栏编程

RxJava系列一

前言 提升开发效率,降低维护成本一直是开发团队永恒不变的宗旨。近一年来国内的技术圈子中越来越多的开始提及Rx,经过一段时间的学习和探索之后我也深深的感受到了Rx...

268100
来自专栏大内老A

WCF后续之旅(11): 关于并发、回调的线程关联性(Thread Affinity)

对于一般的多线程操作,比如异步地进行基于文件系统的IO操作;异步地调用Web Service;或者是异步地进行数据库访问等等,是和具体的线程无关的。也就是说,对...

262100

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励