zl程序教程

您现在的位置是:首页 >  移动开发

当前栏目

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

Android 操作 进行 图片 读取 缩放 SD
2023-09-14 08:58:19 时间
在Android中对大图片进行缩放真的很不尽如人意,不知道是不是我的方法不对。下面我列出3种对图片缩放的方法,并给出相应速度。请高人指教。 br br 第一种是BitmapFactory和BitmapFactory.Options。 br 首先,BitmapFactory.Options有几个Fields很有用: br inJustDecodeBounds:If set to
在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   
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();           }       }  
 * 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 itll 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 its 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);           }       }   }