在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等经过人家一阵加工而成。
效率好像比第二种方法高一点点。
下面是我的例子:
1. <?xml version="1.0" encoding="utf-8"?>
2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3. android:orientation="vertical"
4. android:layout_;fill_parent"
5. android:layout_height="fill_parent"
6. >
7.
8. <ImageView
9. android:id="@+id/imageShow"
10. android:layout_;wrap_content"
11. android:layout_height="wrap_content"
12. />
13. <ImageView
14. android:id="@+id/image2"
15. android:layout_;wrap_content"
16. android:layout_height="wrap_content"
17. />
18. <TextView
19. android:id="@+id/text"
20. android:layout_;fill_parent"
21. android:layout_height="wrap_content"
22. android:text="@string/hello"
23. />
24. </LinearLayout>
1. package com.linc.ResolvePicture;
2.
3. import java.io.File;
4. import java.io.FileNotFoundException;
5. import java.io.FileOutputStream;
6. import java.io.IOException;
7.
8. import android.app.Activity;
9. import android.graphics.Bitmap;
10. import android.graphics.BitmapFactory;
11. import android.graphics.Matrix;
12. import android.graphics.drawable.BitmapDrawable;
13. import android.graphics.drawable.Drawable;
14. import android.media.ThumbnailUtils;
15. import android.os.Bundle;
16. import android.util.Log;
17. import android.widget.ImageView;
18. import android.widget.TextView;
19.
20. public class ResolvePicture extends Activity {
21. private static String tag="ResolvePicture";
22. Drawable bmImg;
23. ImageView imView;
24. ImageView imView2;
25. TextView text;
26. String theTime;
27. long start, stop;
28. /** Called when the activity is first created. */
29. @Override
30. public void onCreate(Bundle savedInstanceState) {
31. super.onCreate(savedInstanceState);
32. setContentView(R.layout.main);
33.
34. text=(TextView)findViewById(R.id.text);
35.
36. imView=(ImageView) findViewById(R.id.imageShow);
37. imView2=(ImageView) findViewById(R.id.image2);
38.
39. Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
40. R.drawable.pic);
41.
42. start=System.currentTimeMillis();
43.
44. // imView.setImageDrawable(resizeImage(bitmap, 300, 100));
45.
46. imView2.setImageDrawable(resizeImage2("/sdcard/2.jpeg", 200, 100));
47.
48. stop=System.currentTimeMillis();
49.
50. String theTime= String.format("\n1 iterative: (%d msec)",
51. stop - start);
52.
53. start=System.currentTimeMillis();
54. imView.setImageBitmap(ThumbnailUtils.extractThumbnail(bitmap,200,100));//2.2才加进来的新类,简单易用
55. // imView.setImageDrawable(resizeImage(bitmap, 30, 30));
56. stop=System.currentTimeMillis();
57.
58. theTime+= String.format("\n2 iterative: (%d msec)",
59. stop - start);
60.
61. text.setText(theTime);
62. }
63.
64. //使用Bitmap加Matrix来缩放
65. public static Drawable resizeImage(Bitmap bitmap, int w, int h)
66. {
67. Bitmap BitmapOrg = bitmap;
68. int width = BitmapOrg.getWidth();
69. int height = BitmapOrg.getHeight();
70. int newWidth = w;
71. int newHeight = h;
72.
73. float scaleWidth = ((float) newWidth) / width;
74. float scaleHeight = ((float) newHeight) / height;
75.
76. Matrix matrix = new Matrix();
77. matrix.postScale(scaleWidth, scaleHeight);
78. // if you want to rotate the Bitmap
79. // matrix.postRotate(45);
80. Bitmap resizedBitmap = Bitmap.createBitmap(BitmapOrg, 0, 0, width,
81. height, matrix, true);
82. return new BitmapDrawable(resizedBitmap);
83. }
84.
85. //使用BitmapFactory.Options的inSampleSize参数来缩放
86. public static Drawable resizeImage2(String path,
87. int width,int height)
88. {
89. BitmapFactory.Options options = new BitmapFactory.Options();
90. options.inJustDecodeBounds = true;//不加载bitmap到内存中
91. BitmapFactory.decodeFile(path,options);
92. int outWidth = options.outWidth;
93. int outHeight = options.outHeight;
94. options.inDither = false;
95. options.inPreferredConfig = Bitmap.Config.ARGB_8888;
96. options.inSampleSize = 1;
97.
98. if (outWidth != 0 && outHeight != 0 && width != 0 && height != 0)
99. {
100. int sampleSize=(outWidth/width+outHeight/height)/2;
101. Log.d(tag, "sampleSize = " + sampleSize);
102. options.inSampleSize = sampleSize;
103. }
104.
105. options.inJustDecodeBounds = false;
106. return new BitmapDrawable(BitmapFactory.decodeFile(path, options));
107. }
108.
109. //图片保存
110. private void saveThePicture(Bitmap bitmap)
111. {
112. File file=new File("/sdcard/2.jpeg");
113. try
114. {
115. FileOutputStream fos=new FileOutputStream(file);
116. if(bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos))
117. {
118. fos.flush();
119. fos.close();
120. }
121. }
122. catch(FileNotFoundException e1)
123. {
124. e1.printStackTrace();
125. }
126. catch(IOException e2)
127. {
128. e2.printStackTrace();
129. }
130. }
131. }
ThumbnailUtils源码:
1. /*
2. * Copyright (C) 2009 The Android Open Source Project
3. *
4. * Licensed under the Apache License, Version 2.0 (the "License");
5. * you may not use this file except in compliance with the License.
6. * You may obtain a copy of the License at
7. *
8. * http://www.apache.org/licenses/LICENSE-2.0
9. *
10. * Unless required by applicable law or agreed to in writing, software
11. * distributed under the License is distributed on an "AS IS" BASIS,
12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13. * See the License for the specific language governing permissions and
14. * limitations under the License.
15. */
16.
17. package android.media;
18.
19. import android.content.ContentResolver;
20. import android.content.ContentUris;
21. import android.content.ContentValues;
22. import android.database.Cursor;
23. import android.graphics.Bitmap;
24. import android.graphics.BitmapFactory;
25. import android.graphics.Canvas;
26. import android.graphics.Matrix;
27. import android.graphics.Rect;
28. import android.media.MediaMetadataRetriever;
29. import android.media.MediaFile.MediaFileType;
30. import android.net.Uri;
31. import android.os.ParcelFileDescriptor;
32. import android.provider.BaseColumns;
33. import android.provider.MediaStore.Images;
34. import android.provider.MediaStore.Images.Thumbnails;
35. import android.util.Log;
36.
37. import java.io.FileInputStream;
38. import java.io.FileDescriptor;
39. import java.io.IOException;
40. import java.io.OutputStream;
41.
42. /**
43. * Thumbnail generation routines for media provider.
44. */
45.
46. public class ThumbnailUtils {
47. private static final String TAG = "ThumbnailUtils";
48.
49. /* Maximum pixels size for created bitmap. */
50. private static final int MAX_NUM_PIXELS_THUMBNAIL = 512 * 384;
51. private static final int MAX_NUM_PIXELS_MICRO_THUMBNAIL = 128 * 128;
52. private static final int UNCONSTRAINED = -1;
53.
54. /* Options used internally. */
55. private static final int OPTIONS_NONE = 0x0;
56. private static final int OPTIONS_SCALE_UP = 0x1;
57.
58. /**
59. * Constant used to indicate we should recycle the input in
60. * {@link #extractThumbnail(Bitmap, int, int, int)} unless the output is the input.
61. */
62. public static final int OPTIONS_RECYCLE_INPUT = 0x2;
63.
64. /**
65. * Constant used to indicate the dimension of mini thumbnail.
66. * @hide Only used by media framework and media provider internally.
67. */
68. public static final int TARGET_SIZE_MINI_THUMBNAIL = 320;
69.
70. /**
71. * Constant used to indicate the dimension of micro thumbnail.
72. * @hide Only used by media framework and media provider internally.
73. */
74. public static final int TARGET_SIZE_MICRO_THUMBNAIL = 96;
75.
76. /**
77. * This method first examines if the thumbnail embedded in EXIF is bigger than our target
78. * size. If not, then it'll create a thumbnail from original image. Due to efficiency
79. * consideration, we want to let MediaThumbRequest avoid calling this method twice for
80. * both kinds, so it only requests for MICRO_KIND and set saveImage to true.
81. *
82. * This method always returns a "square thumbnail" for MICRO_KIND thumbnail.
83. *
84. * @param filePath the path of image file
85. * @param kind could be MINI_KIND or MICRO_KIND
86. * @return Bitmap
87. *
88. * @hide This method is only used by media framework and media provider internally.
89. */
90. public static Bitmap createImageThumbnail(String filePath, int kind) {
91. boolean wantMini = (kind == Images.Thumbnails.MINI_KIND);
92. int targetSize = wantMini
93. ? TARGET_SIZE_MINI_THUMBNAIL
94. : TARGET_SIZE_MICRO_THUMBNAIL;
95. int maxPixels = wantMini
96. ? MAX_NUM_PIXELS_THUMBNAIL
97. : MAX_NUM_PIXELS_MICRO_THUMBNAIL;
98. SizedThumbnailBitmap sizedThumbnailBitmap = new SizedThumbnailBitmap();
99. Bitmap bitmap = null;
100. MediaFileType fileType = MediaFile.getFileType(filePath);
101. if (fileType != null && fileType.fileType == MediaFile.FILE_TYPE_JPEG) {
102. createThumbnailFromEXIF(filePath, targetSize, maxPixels, sizedThumbnailBitmap);
103. bitmap = sizedThumbnailBitmap.mBitmap;
104. }
105.
106. if (bitmap == null) {
107. try {
108. FileDescriptor fd = new FileInputStream(filePath).getFD();
109. BitmapFactory.Options options = new BitmapFactory.Options();
110. options.inSampleSize = 1;
111. options.inJustDecodeBounds = true;
112. BitmapFactory.decodeFileDescriptor(fd, null, options);
113. if (options.mCancel || options.outWidth == -1
114. || options.outHeight == -1) {
115. return null;
116. }
117. options.inSampleSize = computeSampleSize(
118. options, targetSize, maxPixels);
119. options.inJustDecodeBounds = false;
120.
121. options.inDither = false;
122. options.inPreferredConfig = Bitmap.Config.ARGB_8888;
123. bitmap = BitmapFactory.decodeFileDescriptor(fd, null, options);
124. } catch (IOException ex) {
125. Log.e(TAG, "", ex);
126. }
127. }
128.
129. if (kind == Images.Thumbnails.MICRO_KIND) {
130. // now we make it a "square thumbnail" for MICRO_KIND thumbnail
131. bitmap = extractThumbnail(bitmap,
132. TARGET_SIZE_MICRO_THUMBNAIL,
133. TARGET_SIZE_MICRO_THUMBNAIL, OPTIONS_RECYCLE_INPUT);
134. }
135. return bitmap;
136. }
137.
138. /**
139. * Create a video thumbnail for a video. May return null if the video is
140. * corrupt or the format is not supported.
141. *
142. * @param filePath the path of video file
143. * @param kind could be MINI_KIND or MICRO_KIND
144. */
145. public static Bitmap createVideoThumbnail(String filePath, int kind) {
146. Bitmap bitmap = null;
147. MediaMetadataRetriever retriever = new MediaMetadataRetriever();
148. try {
149. retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY);
150. retriever.setDataSource(filePath);
151. bitmap = retriever.captureFrame();
152. } catch (IllegalArgumentException ex) {
153. // Assume this is a corrupt video file
154. } catch (RuntimeException ex) {
155. // Assume this is a corrupt video file.
156. } finally {
157. try {
158. retriever.release();
159. } catch (RuntimeException ex) {
160. // Ignore failures while cleaning up.
161. }
162. }
163. if (kind == Images.Thumbnails.MICRO_KIND && bitmap != null) {
164. bitmap = extractThumbnail(bitmap,
165. TARGET_SIZE_MICRO_THUMBNAIL,
166. TARGET_SIZE_MICRO_THUMBNAIL,
167. OPTIONS_RECYCLE_INPUT);
168. }
169. return bitmap;
170. }
171.
172. /**
173. * Creates a centered bitmap of the desired size.
174. *
175. * @param source original bitmap source
176. * @param width targeted width
177. * @param height targeted height
178. */
179. public static Bitmap extractThumbnail(
180. Bitmap source, int width, int height) {
181. return extractThumbnail(source, width, height, OPTIONS_NONE);
182. }
183.
184. /**
185. * Creates a centered bitmap of the desired size.
186. *
187. * @param source original bitmap source
188. * @param width targeted width
189. * @param height targeted height
190. * @param options options used during thumbnail extraction
191. */
192. public static Bitmap extractThumbnail(
193. Bitmap source, int width, int height, int options) {
194. if (source == null) {
195. return null;
196. }
197.
198. float scale;
199. if (source.getWidth() < source.getHeight()) {
200. scale = width / (float) source.getWidth();
201. } else {
202. scale = height / (float) source.getHeight();
203. }
204. Matrix matrix = new Matrix();
205. matrix.setScale(scale, scale);
206. Bitmap thumbnail = transform(matrix, source, width, height,
207. OPTIONS_SCALE_UP | options);
208. return thumbnail;
209. }
210.
211. /*
212. * Compute the sample size as a function of minSideLength
213. * and maxNumOfPixels.
214. * minSideLength is used to specify that minimal width or height of a
215. * bitmap.
216. * maxNumOfPixels is used to specify the maximal size in pixels that is
217. * tolerable in terms of memory usage.
218. *
219. * The function returns a sample size based on the constraints.
220. * Both size and minSideLength can be passed in as IImage.UNCONSTRAINED,
221. * which indicates no care of the corresponding constraint.
222. * The functions prefers returning a sample size that
223. * generates a smaller bitmap, unless minSideLength = IImage.UNCONSTRAINED.
224. *
225. * Also, the function rounds up the sample size to a power of 2 or multiple
226. * of 8 because BitmapFactory only honors sample size this way.
227. * For example, BitmapFactory downsamples an image by 2 even though the
228. * request is 3. So we round up the sample size to avoid OOM.
229. */
230. private static int computeSampleSize(BitmapFactory.Options options,
231. int minSideLength, int maxNumOfPixels) {
232. int initialSize = computeInitialSampleSize(options, minSideLength,
233. maxNumOfPixels);
234.
235. int roundedSize;
236. if (initialSize <= 8 ) {
237. roundedSize = 1;
238. while (roundedSize < initialSize) {
239. roundedSize <<= 1;
240. }
241. } else {
242. roundedSize = (initialSize + 7) / 8 * 8;
243. }
244.
245. return roundedSize;
246. }
247.
248. private static int computeInitialSampleSize(BitmapFactory.Options options,
249. int minSideLength, int maxNumOfPixels) {
250. double w = options.outWidth;
251. double h = options.outHeight;
252.
253. int lowerBound = (maxNumOfPixels == UNCONSTRAINED) ? 1 :
254. (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));
255. int upperBound = (minSideLength == UNCONSTRAINED) ? 128 :
256. (int) Math.min(Math.floor(w / minSideLength),
257. Math.floor(h / minSideLength));
258.
259. if (upperBound < lowerBound) {
260. // return the larger one when there is no overlapping zone.
261. return lowerBound;
262. }
263.
264. if ((maxNumOfPixels == UNCONSTRAINED) &&
265. (minSideLength == UNCONSTRAINED)) {
266. return 1;
267. } else if (minSideLength == UNCONSTRAINED) {
268. return lowerBound;
269. } else {
270. return upperBound;
271. }
272. }
273.
274. /**
275. * Make a bitmap from a given Uri, minimal side length, and maximum number of pixels.
276. * The image data will be read from specified pfd if it's not null, otherwise
277. * a new input stream will be created using specified ContentResolver.
278. *
279. * Clients are allowed to pass their own BitmapFactory.Options used for bitmap decoding. A
280. * new BitmapFactory.Options will be created if options is null.
281. */
282. private static Bitmap makeBitmap(int minSideLength, int maxNumOfPixels,
283. Uri uri, ContentResolver cr, ParcelFileDescriptor pfd,
284. BitmapFactory.Options options) {
285. Bitmap b = null;
286. try {
287. if (pfd == null) pfd = makeInputStream(uri, cr);
288. if (pfd == null) return null;
289. if (options == null) options = new BitmapFactory.Options();
290.
291. FileDescriptor fd = pfd.getFileDescriptor();
292. options.inSampleSize = 1;
293. options.inJustDecodeBounds = true;
294. BitmapFactory.decodeFileDescriptor(fd, null, options);
295. if (options.mCancel || options.outWidth == -1
296. || options.outHeight == -1) {
297. return null;
298. }
299. options.inSampleSize = computeSampleSize(
300. options, minSideLength, maxNumOfPixels);
301. options.inJustDecodeBounds = false;
302.
303. options.inDither = false;
304. options.inPreferredConfig = Bitmap.Config.ARGB_8888;
305. b = BitmapFactory.decodeFileDescriptor(fd, null, options);
306. } catch (OutOfMemoryError ex) {
307. Log.e(TAG, "Got oom exception ", ex);
308. return null;
309. } finally {
310. closeSilently(pfd);
311. }
312. return b;
313. }
314.
315. private static void closeSilently(ParcelFileDescriptor c) {
316. if (c == null) return;
317. try {
318. c.close();
319. } catch (Throwable t) {
320. // do nothing
321. }
322. }
323.
324. private static ParcelFileDescriptor makeInputStream(
325. Uri uri, ContentResolver cr) {
326. try {
327. return cr.openFileDescriptor(uri, "r");
328. } catch (IOException ex) {
329. return null;
330. }
331. }
332.
333. /**
334. * Transform source Bitmap to targeted width and height.
335. */
336. private static Bitmap transform(Matrix scaler,
337. Bitmap source,
338. int targetWidth,
339. int targetHeight,
340. int options) {
341. boolean scaleUp = (options & OPTIONS_SCALE_UP) != 0;
342. boolean recycle = (options & OPTIONS_RECYCLE_INPUT) != 0;
343.
344. int deltaX = source.getWidth() - targetWidth;
345. int deltaY = source.getHeight() - targetHeight;
346. if (!scaleUp && (deltaX < 0 || deltaY < 0)) {
347. /*
348. * In this case the bitmap is smaller, at least in one dimension,
349. * than the target. Transform it by placing as much of the image
350. * as possible into the target and leaving the top/bottom or
351. * left/right (or both) black.
352. */
353. Bitmap b2 = Bitmap.createBitmap(targetWidth, targetHeight,
354. Bitmap.Config.ARGB_8888);
355. Canvas c = new Canvas(b2);
356.
357. int deltaXHalf = Math.max(0, deltaX / 2);
358. int deltaYHalf = Math.max(0, deltaY / 2);
359. Rect src = new Rect(
360. deltaXHalf,
361. deltaYHalf,
362. deltaXHalf + Math.min(targetWidth, source.getWidth()),
363. deltaYHalf + Math.min(targetHeight, source.getHeight()));
364. int dstX = (targetWidth - src.width()) / 2;
365. int dstY = (targetHeight - src.height()) / 2;
366. Rect dst = new Rect(
367. dstX,
368. dstY,
369. targetWidth - dstX,
370. targetHeight - dstY);
371. c.drawBitmap(source, src, dst, null);
372. if (recycle) {
373. source.recycle();
374. }
375. return b2;
376. }
377. float bitmapWidthF = source.getWidth();
378. float bitmapHeightF = source.getHeight();
379.
380. float bitmapAspect = bitmapWidthF / bitmapHeightF;
381. float viewAspect = (float) targetWidth / targetHeight;
382.
383. if (bitmapAspect > viewAspect) {
384. float scale = targetHeight / bitmapHeightF;
385. if (scale < .9F || scale > 1F) {
386. scaler.setScale(scale, scale);
387. } else {
388. scaler = null;
389. }
390. } else {
391. float scale = targetWidth / bitmapWidthF;
392. if (scale < .9F || scale > 1F) {
393. scaler.setScale(scale, scale);
394. } else {
395. scaler = null;
396. }
397. }
398.
399. Bitmap b1;
400. if (scaler != null) {
401. // this is used for minithumb and crop, so we want to filter here.
402. b1 = Bitmap.createBitmap(source, 0, 0,
403. source.getWidth(), source.getHeight(), scaler, true);
404. } else {
405. b1 = source;
406. }
407.
408. if (recycle && b1 != source) {
409. source.recycle();
410. }
411.
412. int dx1 = Math.max(0, b1.getWidth() - targetWidth);
413. int dy1 = Math.max(0, b1.getHeight() - targetHeight);
414.
415. Bitmap b2 = Bitmap.createBitmap(
416. b1,
417. dx1 / 2,
418. dy1 / 2,
419. targetWidth,
420. targetHeight);
421.
422. if (b2 != b1) {
423. if (recycle || b1 != source) {
424. b1.recycle();
425. }
426. }
427.
428. return b2;
429. }
430.
431. /**
432. * SizedThumbnailBitmap contains the bitmap, which is downsampled either from
433. * the thumbnail in exif or the full image.
434. * mThumbnailData, mThumbnailWidth and mThumbnailHeight are set together only if mThumbnail
435. * is not null.
436. *
437. * The width/height of the sized bitmap may be different from mThumbnailWidth/mThumbnailHeight.
438. */
439. private static class SizedThumbnailBitmap {
440. public byte[] mThumbnailData;
441. public Bitmap mBitmap;
442. public int mThumbnailWidth;
443. public int mThumbnailHeight;
444. }
445.
446. /**
447. * Creates a bitmap by either downsampling from the thumbnail in EXIF or the full image.
448. * The functions returns a SizedThumbnailBitmap,
449. * which contains a downsampled bitmap and the thumbnail data in EXIF if exists.
450. */
451. private static void createThumbnailFromEXIF(String filePath, int targetSize,
452. int maxPixels, SizedThumbnailBitmap sizedThumbBitmap) {
453. if (filePath == null) return;
454.
455. ExifInterface exif = null;
456. byte [] thumbData = null;
457. try {
458. exif = new ExifInterface(filePath);
459. if (exif != null) {
460. thumbData = exif.getThumbnail();
461. }
462. } catch (IOException ex) {
463. Log.w(TAG, ex);
464. }
465.
466. BitmapFactory.Options fullOptions = new BitmapFactory.Options();
467. BitmapFactory.Options exifOptions = new BitmapFactory.Options();
468. int exifThumbWidth = 0;
469. int fullThumbWidth = 0;
470.
471. // Compute exifThumbWidth.
472. if (thumbData != null) {
473. exifOptions.inJustDecodeBounds = true;
474. BitmapFactory.decodeByteArray(thumbData, 0, thumbData.length, exifOptions);
475. exifOptions.inSampleSize = computeSampleSize(exifOptions, targetSize, maxPixels);
476. exifThumbWidth = exifOptions.outWidth / exifOptions.inSampleSize;
477. }
478.
479. // Compute fullThumbWidth.
480. fullOptions.inJustDecodeBounds = true;
481. BitmapFactory.decodeFile(filePath, fullOptions);
482. fullOptions.inSampleSize = computeSampleSize(fullOptions, targetSize, maxPixels);
483. fullThumbWidth = fullOptions.outWidth / fullOptions.inSampleSize;
484.
485. // Choose the larger thumbnail as the returning sizedThumbBitmap.
486. if (thumbData != null && exifThumbWidth >= fullThumbWidth) {
487. int width = exifOptions.outWidth;
488. int height = exifOptions.outHeight;
489. exifOptions.inJustDecodeBounds = false;
490. sizedThumbBitmap.mBitmap = BitmapFactory.decodeByteArray(thumbData, 0,
491. thumbData.length, exifOptions);
492. if (sizedThumbBitmap.mBitmap != null) {
493. sizedThumbBitmap.mThumbnailData = thumbData;
494. sizedThumbBitmap.mThumbnailWidth = width;
495. sizedThumbBitmap.mThumbnailHeight = height;
496. }
497. } else {
498. fullOptions.inJustDecodeBounds = false;
499. sizedThumbBitmap.mBitmap = BitmapFactory.decodeFile(filePath, fullOptions);
500. }
501. }
502. }