博客源址Android图片缩放总结及比较

博客时间2011-08-01 17:42

在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.OptionsMatrix等经过人家一阵加工而成。
效率好像比第二种方法高一点点。

下面是我的例子:

[html] view plain copy

  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
  3. android:orientation="vertical"
  4. android:layout_width="fill_parent"
  5. android:layout_height="fill_parent"
  6. >
  7. <ImageView
  8. android:id="@+id/imageShow"
  9. android:layout_width="wrap_content"
  10. android:layout_height="wrap_content"
  11. />
  12. <ImageView
  13. android:id="@+id/image2"
  14. android:layout_width="wrap_content"
  15. android:layout_height="wrap_content"
  16. />
  17. <TextView
  18. android:id="@+id/text"
  19. android:layout_width="fill_parent"
  20. android:layout_height="wrap_content"
  21. android:text="@string/hello"
  22. />
  23. </LinearLayout>
[java] view plain copy

  1. packagecom.linc.ResolvePicture;
  2. importjava.io.File;
  3. importjava.io.FileNotFoundException;
  4. importjava.io.FileOutputStream;
  5. importjava.io.IOException;
  6. importandroid.app.Activity;
  7. importandroid.graphics.Bitmap;
  8. importandroid.graphics.BitmapFactory;
  9. importandroid.graphics.Matrix;
  10. importandroid.graphics.drawable.BitmapDrawable;
  11. importandroid.graphics.drawable.Drawable;
  12. importandroid.media.ThumbnailUtils;
  13. importandroid.os.Bundle;
  14. importandroid.util.Log;
  15. importandroid.widget.ImageView;
  16. importandroid.widget.TextView;
  17. publicclassResolvePictureextendsActivity {
  18. privatestaticString tag="ResolvePicture";
  19. Drawable bmImg;
  20. ImageView imView;
  21. ImageView imView2;
  22. TextView text;
  23. String theTime;
  24. longstart, stop;
  25. /** Called when the activity is first created. */
  26. @Override
  27. publicvoidonCreate(Bundle savedInstanceState) {
  28. super.onCreate(savedInstanceState);
  29. setContentView(R.layout.main);
  30. text=(TextView)findViewById(R.id.text);
  31. imView=(ImageView) findViewById(R.id.imageShow);
  32. imView2=(ImageView) findViewById(R.id.image2);
  33. /**pic大时(2M+)直接OOM,后面还裁剪个屁啊*/
  34. Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
  35. R.drawable.pic);
  36. start=System.currentTimeMillis();
  37. //        imView.setImageDrawable(resizeImage(bitmap, 300, 100));
  38. imView2.setImageDrawable(resizeImage2("/sdcard/2.jpeg",200,100));
  39. stop=System.currentTimeMillis();
  40. String theTime= String.format("\n1 iterative: (%d msec)",
  41. stop - start);
  42. start=System.currentTimeMillis();
  43. imView.setImageBitmap(ThumbnailUtils.extractThumbnail(bitmap,200,100));//2.2才加进来的新类,简单易用
  44. //        imView.setImageDrawable(resizeImage(bitmap, 30, 30));
  45. stop=System.currentTimeMillis();
  46. theTime+= String.format("\n2 iterative: (%d msec)",
  47. stop - start);
  48. text.setText(theTime);
  49. }
  50. //使用Bitmap加Matrix来缩放
  51. publicstaticDrawable resizeImage(Bitmap bitmap,intw,inth)
  52. {
  53. Bitmap BitmapOrg = bitmap;
  54. intwidth = BitmapOrg.getWidth();
  55. intheight = BitmapOrg.getHeight();
  56. intnewWidth = w;
  57. intnewHeight = h;
  58. floatscaleWidth = ((float) newWidth) / width;
  59. floatscaleHeight = ((float) newHeight) / height;
  60. Matrix matrix = newMatrix();
  61. matrix.postScale(scaleWidth, scaleHeight);
  62. // if you want to rotate the Bitmap
  63. // matrix.postRotate(45);
  64. Bitmap resizedBitmap = Bitmap.createBitmap(BitmapOrg, 0,0, width,
  65. height, matrix, true);
  66. returnnewBitmapDrawable(resizedBitmap);
  67. }
  68. //使用BitmapFactory.Options的inSampleSize参数来缩放
  69. publicstaticDrawable resizeImage2(String path,
  70. intwidth,intheight)
  71. {
  72. BitmapFactory.Options options = newBitmapFactory.Options();
  73. options.inJustDecodeBounds = true;//不加载bitmap到内存中
  74. BitmapFactory.decodeFile(path,options);
  75. intoutWidth = options.outWidth;
  76. intoutHeight = options.outHeight;
  77. options.inDither = false;
  78. options.inPreferredConfig = Bitmap.Config.ARGB_8888;
  79. options.inSampleSize = 1;
  80. if(outWidth !=0&& outHeight !=0&& width !=0&& height !=0)
  81. {
  82. intsampleSize=(outWidth/width+outHeight/height)/2;
  83. Log.d(tag, "sampleSize = "+ sampleSize);
  84. options.inSampleSize = sampleSize;
  85. }
  86. options.inJustDecodeBounds = false;
  87. returnnewBitmapDrawable(BitmapFactory.decodeFile(path, options));
  88. }
  89. //图片保存
  90. privatevoidsaveThePicture(Bitmap bitmap)
  91. {
  92. File file=newFile("/sdcard/2.jpeg");
  93. try
  94. {
  95. FileOutputStream fos=newFileOutputStream(file);
  96. if(bitmap.compress(Bitmap.CompressFormat.JPEG,100, fos))
  97. {
  98. fos.flush();
  99. fos.close();
  100. }
  101. }
  102. catch(FileNotFoundException e1)
  103. {
  104. e1.printStackTrace();
  105. }
  106. catch(IOException e2)
  107. {
  108. e2.printStackTrace();
  109. }
  110. }
  111. }
ThumbnailUtils源码:
[java] view plain copy

  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. packageandroid.media;
  17. importandroid.content.ContentResolver;
  18. importandroid.content.ContentUris;
  19. importandroid.content.ContentValues;
  20. importandroid.database.Cursor;
  21. importandroid.graphics.Bitmap;
  22. importandroid.graphics.BitmapFactory;
  23. importandroid.graphics.Canvas;
  24. importandroid.graphics.Matrix;
  25. importandroid.graphics.Rect;
  26. importandroid.media.MediaMetadataRetriever;
  27. importandroid.media.MediaFile.MediaFileType;
  28. importandroid.net.Uri;
  29. importandroid.os.ParcelFileDescriptor;
  30. importandroid.provider.BaseColumns;
  31. importandroid.provider.MediaStore.Images;
  32. importandroid.provider.MediaStore.Images.Thumbnails;
  33. importandroid.util.Log;
  34. importjava.io.FileInputStream;
  35. importjava.io.FileDescriptor;
  36. importjava.io.IOException;
  37. importjava.io.OutputStream;
  38. /**
  39. * Thumbnail generation routines for media provider.
  40. */
  41. publicclassThumbnailUtils {
  42. privatestaticfinalString TAG ="ThumbnailUtils";
  43. /* Maximum pixels size for created bitmap. */
  44. privatestaticfinalintMAX_NUM_PIXELS_THUMBNAIL =512*384;
  45. privatestaticfinalintMAX_NUM_PIXELS_MICRO_THUMBNAIL =128*128;
  46. privatestaticfinalintUNCONSTRAINED = -1;
  47. /* Options used internally. */
  48. privatestaticfinalintOPTIONS_NONE =0x0;
  49. privatestaticfinalintOPTIONS_SCALE_UP =0x1;
  50. /**
  51. * Constant used to indicate we should recycle the input in
  52. * {@link #extractThumbnail(Bitmap, int, int, int)} unless the output is the input.
  53. */
  54. publicstaticfinalintOPTIONS_RECYCLE_INPUT =0x2;
  55. /**
  56. * Constant used to indicate the dimension of mini thumbnail.
  57. * @hide Only used by media framework and media provider internally.
  58. */
  59. publicstaticfinalintTARGET_SIZE_MINI_THUMBNAIL =320;
  60. /**
  61. * Constant used to indicate the dimension of micro thumbnail.
  62. * @hide Only used by media framework and media provider internally.
  63. */
  64. publicstaticfinalintTARGET_SIZE_MICRO_THUMBNAIL =96;
  65. /**
  66. * This method first examines if the thumbnail embedded in EXIF is bigger than our target
  67. * size. If not, then it'll create a thumbnail from original image. Due to efficiency
  68. * consideration, we want to let MediaThumbRequest avoid calling this method twice for
  69. * both kinds, so it only requests for MICRO_KIND and set saveImage to true.
  70. *
  71. * This method always returns a "square thumbnail" for MICRO_KIND thumbnail.
  72. *
  73. * @param filePath the path of image file
  74. * @param kind could be MINI_KIND or MICRO_KIND
  75. * @return Bitmap
  76. *
  77. * @hide This method is only used by media framework and media provider internally.
  78. */
  79. publicstaticBitmap createImageThumbnail(String filePath,intkind) {
  80. booleanwantMini = (kind == Images.Thumbnails.MINI_KIND);
  81. inttargetSize = wantMini
  82. ? TARGET_SIZE_MINI_THUMBNAIL
  83. : TARGET_SIZE_MICRO_THUMBNAIL;
  84. intmaxPixels = wantMini
  85. ? MAX_NUM_PIXELS_THUMBNAIL
  86. : MAX_NUM_PIXELS_MICRO_THUMBNAIL;
  87. SizedThumbnailBitmap sizedThumbnailBitmap = newSizedThumbnailBitmap();
  88. Bitmap bitmap = null;
  89. MediaFileType fileType = MediaFile.getFileType(filePath);
  90. if(fileType !=null&& fileType.fileType == MediaFile.FILE_TYPE_JPEG) {
  91. createThumbnailFromEXIF(filePath, targetSize, maxPixels, sizedThumbnailBitmap);
  92. bitmap = sizedThumbnailBitmap.mBitmap;
  93. }
  94. if(bitmap ==null) {
  95. try{
  96. FileDescriptor fd = newFileInputStream(filePath).getFD();
  97. BitmapFactory.Options options = newBitmapFactory.Options();
  98. options.inSampleSize = 1;
  99. options.inJustDecodeBounds = true;
  100. BitmapFactory.decodeFileDescriptor(fd, null, options);
  101. if(options.mCancel || options.outWidth == -1
  102. || options.outHeight == -1) {
  103. returnnull;
  104. }
  105. options.inSampleSize = computeSampleSize(
  106. options, targetSize, maxPixels);
  107. options.inJustDecodeBounds = false;
  108. options.inDither = false;
  109. options.inPreferredConfig = Bitmap.Config.ARGB_8888;
  110. bitmap = BitmapFactory.decodeFileDescriptor(fd, null, options);
  111. catch(IOException ex) {
  112. Log.e(TAG, "", ex);
  113. }
  114. }
  115. if(kind == Images.Thumbnails.MICRO_KIND) {
  116. // now we make it a "square thumbnail" for MICRO_KIND thumbnail
  117. bitmap = extractThumbnail(bitmap,
  118. TARGET_SIZE_MICRO_THUMBNAIL,
  119. TARGET_SIZE_MICRO_THUMBNAIL, OPTIONS_RECYCLE_INPUT);
  120. }
  121. returnbitmap;
  122. }
  123. /**
  124. * Create a video thumbnail for a video. May return null if the video is
  125. * corrupt or the format is not supported.
  126. *
  127. * @param filePath the path of video file
  128. * @param kind could be MINI_KIND or MICRO_KIND
  129. */
  130. publicstaticBitmap createVideoThumbnail(String filePath,intkind) {
  131. Bitmap bitmap = null;
  132. MediaMetadataRetriever retriever = newMediaMetadataRetriever();
  133. try{
  134. retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY);
  135. retriever.setDataSource(filePath);
  136. bitmap = retriever.captureFrame();
  137. catch(IllegalArgumentException ex) {
  138. // Assume this is a corrupt video file
  139. catch(RuntimeException ex) {
  140. // Assume this is a corrupt video file.
  141. finally{
  142. try{
  143. retriever.release();
  144. catch(RuntimeException ex) {
  145. // Ignore failures while cleaning up.
  146. }
  147. }
  148. if(kind == Images.Thumbnails.MICRO_KIND && bitmap !=null) {
  149. bitmap = extractThumbnail(bitmap,
  150. TARGET_SIZE_MICRO_THUMBNAIL,
  151. TARGET_SIZE_MICRO_THUMBNAIL,
  152. OPTIONS_RECYCLE_INPUT);
  153. }
  154. returnbitmap;
  155. }
  156. /**
  157. * Creates a centered bitmap of the desired size.
  158. *
  159. * @param source original bitmap source
  160. * @param width targeted width
  161. * @param height targeted height
  162. */
  163. publicstaticBitmap extractThumbnail(
  164. Bitmap source, intwidth,intheight) {
  165. returnextractThumbnail(source, width, height, OPTIONS_NONE);
  166. }
  167. /**
  168. * Creates a centered bitmap of the desired size.
  169. *
  170. * @param source original bitmap source
  171. * @param width targeted width
  172. * @param height targeted height
  173. * @param options options used during thumbnail extraction
  174. */
  175. publicstaticBitmap extractThumbnail(
  176. Bitmap source, intwidth,intheight,intoptions) {
  177. if(source ==null) {
  178. returnnull;
  179. }
  180. floatscale;
  181. if(source.getWidth() < source.getHeight()) {
  182. scale = width / (float) source.getWidth();
  183. else{
  184. scale = height / (float) source.getHeight();
  185. }
  186. Matrix matrix = newMatrix();
  187. matrix.setScale(scale, scale);
  188. Bitmap thumbnail = transform(matrix, source, width, height,
  189. OPTIONS_SCALE_UP | options);
  190. returnthumbnail;
  191. }
  192. /*
  193. * Compute the sample size as a function of minSideLength
  194. * and maxNumOfPixels.
  195. * minSideLength is used to specify that minimal width or height of a
  196. * bitmap.
  197. * maxNumOfPixels is used to specify the maximal size in pixels that is
  198. * tolerable in terms of memory usage.
  199. *
  200. * The function returns a sample size based on the constraints.
  201. * Both size and minSideLength can be passed in as IImage.UNCONSTRAINED,
  202. * which indicates no care of the corresponding constraint.
  203. * The functions prefers returning a sample size that
  204. * generates a smaller bitmap, unless minSideLength = IImage.UNCONSTRAINED.
  205. *
  206. * Also, the function rounds up the sample size to a power of 2 or multiple
  207. * of 8 because BitmapFactory only honors sample size this way.
  208. * For example, BitmapFactory downsamples an image by 2 even though the
  209. * request is 3. So we round up the sample size to avoid OOM.
  210. */
  211. privatestaticintcomputeSampleSize(BitmapFactory.Options options,
  212. intminSideLength,intmaxNumOfPixels) {
  213. intinitialSize = computeInitialSampleSize(options, minSideLength,
  214. maxNumOfPixels);
  215. introundedSize;
  216. if(initialSize <=8) {
  217. roundedSize = 1;
  218. while(roundedSize < initialSize) {
  219. roundedSize <<= 1;
  220. }
  221. else{
  222. roundedSize = (initialSize + 7) /8*8;
  223. }
  224. returnroundedSize;
  225. }
  226. privatestaticintcomputeInitialSampleSize(BitmapFactory.Options options,
  227. intminSideLength,intmaxNumOfPixels) {
  228. doublew = options.outWidth;
  229. doubleh = options.outHeight;
  230. intlowerBound = (maxNumOfPixels == UNCONSTRAINED) ?1:
  231. (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));
  232. intupperBound = (minSideLength == UNCONSTRAINED) ?128:
  233. (int) Math.min(Math.floor(w / minSideLength),
  234. Math.floor(h / minSideLength));
  235. if(upperBound < lowerBound) {
  236. // return the larger one when there is no overlapping zone.
  237. returnlowerBound;
  238. }
  239. if((maxNumOfPixels == UNCONSTRAINED) &&
  240. (minSideLength == UNCONSTRAINED)) {
  241. return1;
  242. elseif(minSideLength == UNCONSTRAINED) {
  243. returnlowerBound;
  244. else{
  245. returnupperBound;
  246. }
  247. }
  248. /**
  249. * Make a bitmap from a given Uri, minimal side length, and maximum number of pixels.
  250. * The image data will be read from specified pfd if it's not null, otherwise
  251. * a new input stream will be created using specified ContentResolver.
  252. *
  253. * Clients are allowed to pass their own BitmapFactory.Options used for bitmap decoding. A
  254. * new BitmapFactory.Options will be created if options is null.
  255. */
  256. privatestaticBitmap makeBitmap(intminSideLength,intmaxNumOfPixels,
  257. Uri uri, ContentResolver cr, ParcelFileDescriptor pfd,
  258. BitmapFactory.Options options) {
  259. Bitmap b = null;
  260. try{
  261. if(pfd ==null) pfd = makeInputStream(uri, cr);
  262. if(pfd ==null)returnnull;
  263. if(options ==null) options =newBitmapFactory.Options();
  264. FileDescriptor fd = pfd.getFileDescriptor();
  265. options.inSampleSize = 1;
  266. options.inJustDecodeBounds = true;
  267. BitmapFactory.decodeFileDescriptor(fd, null, options);
  268. if(options.mCancel || options.outWidth == -1
  269. || options.outHeight == -1) {
  270. returnnull;
  271. }
  272. options.inSampleSize = computeSampleSize(
  273. options, minSideLength, maxNumOfPixels);
  274. options.inJustDecodeBounds = false;
  275. options.inDither = false;
  276. options.inPreferredConfig = Bitmap.Config.ARGB_8888;
  277. b = BitmapFactory.decodeFileDescriptor(fd, null, options);
  278. catch(OutOfMemoryError ex) {
  279. Log.e(TAG, "Got oom exception ", ex);
  280. returnnull;
  281. finally{
  282. closeSilently(pfd);
  283. }
  284. returnb;
  285. }
  286. privatestaticvoidcloseSilently(ParcelFileDescriptor c) {
  287. if(c ==null)return;
  288. try{
  289. c.close();
  290. catch(Throwable t) {
  291. // do nothing
  292. }
  293. }
  294. privatestaticParcelFileDescriptor makeInputStream(
  295. Uri uri, ContentResolver cr) {
  296. try{
  297. returncr.openFileDescriptor(uri,"r");
  298. catch(IOException ex) {
  299. returnnull;
  300. }
  301. }
  302. /**
  303. * Transform source Bitmap to targeted width and height.
  304. */
  305. privatestaticBitmap transform(Matrix scaler,
  306. Bitmap source,
  307. inttargetWidth,
  308. inttargetHeight,
  309. intoptions) {
  310. booleanscaleUp = (options & OPTIONS_SCALE_UP) !=0;
  311. booleanrecycle = (options & OPTIONS_RECYCLE_INPUT) !=0;
  312. intdeltaX = source.getWidth() - targetWidth;
  313. intdeltaY = source.getHeight() - targetHeight;
  314. if(!scaleUp && (deltaX <0|| deltaY <0)) {
  315. /*
  316. * In this case the bitmap is smaller, at least in one dimension,
  317. * than the target.  Transform it by placing as much of the image
  318. * as possible into the target and leaving the top/bottom or
  319. * left/right (or both) black.
  320. */
  321. Bitmap b2 = Bitmap.createBitmap(targetWidth, targetHeight,
  322. Bitmap.Config.ARGB_8888);
  323. Canvas c = newCanvas(b2);
  324. intdeltaXHalf = Math.max(0, deltaX /2);
  325. intdeltaYHalf = Math.max(0, deltaY /2);
  326. Rect src = newRect(
  327. deltaXHalf,
  328. deltaYHalf,
  329. deltaXHalf + Math.min(targetWidth, source.getWidth()),
  330. deltaYHalf + Math.min(targetHeight, source.getHeight()));
  331. intdstX = (targetWidth  - src.width())  /2;
  332. intdstY = (targetHeight - src.height()) /2;
  333. Rect dst = newRect(
  334. dstX,
  335. dstY,
  336. targetWidth - dstX,
  337. targetHeight - dstY);
  338. c.drawBitmap(source, src, dst, null);
  339. if(recycle) {
  340. source.recycle();
  341. }
  342. returnb2;
  343. }
  344. floatbitmapWidthF = source.getWidth();
  345. floatbitmapHeightF = source.getHeight();
  346. floatbitmapAspect = bitmapWidthF / bitmapHeightF;
  347. floatviewAspect   = (float) targetWidth / targetHeight;
  348. if(bitmapAspect > viewAspect) {
  349. floatscale = targetHeight / bitmapHeightF;
  350. if(scale < .9F || scale > 1F) {
  351. scaler.setScale(scale, scale);
  352. else{
  353. scaler = null;
  354. }
  355. else{
  356. floatscale = targetWidth / bitmapWidthF;
  357. if(scale < .9F || scale > 1F) {
  358. scaler.setScale(scale, scale);
  359. else{
  360. scaler = null;
  361. }
  362. }
  363. Bitmap b1;
  364. if(scaler !=null) {
  365. // this is used for minithumb and crop, so we want to filter here.
  366. b1 = Bitmap.createBitmap(source, 0,0,
  367. source.getWidth(), source.getHeight(), scaler, true);
  368. else{
  369. b1 = source;
  370. }
  371. if(recycle && b1 != source) {
  372. source.recycle();
  373. }
  374. intdx1 = Math.max(0, b1.getWidth() - targetWidth);
  375. intdy1 = Math.max(0, b1.getHeight() - targetHeight);
  376. Bitmap b2 = Bitmap.createBitmap(
  377. b1,
  378. dx1 / 2,
  379. dy1 / 2,
  380. targetWidth,
  381. targetHeight);
  382. if(b2 != b1) {
  383. if(recycle || b1 != source) {
  384. b1.recycle();
  385. }
  386. }
  387. returnb2;
  388. }
  389. /**
  390. * SizedThumbnailBitmap contains the bitmap, which is downsampled either from
  391. * the thumbnail in exif or the full image.
  392. * mThumbnailData, mThumbnailWidth and mThumbnailHeight are set together only if mThumbnail
  393. * is not null.
  394. *
  395. * The width/height of the sized bitmap may be different from mThumbnailWidth/mThumbnailHeight.
  396. */
  397. privatestaticclassSizedThumbnailBitmap {
  398. publicbyte[] mThumbnailData;
  399. publicBitmap mBitmap;
  400. publicintmThumbnailWidth;
  401. publicintmThumbnailHeight;
  402. }
  403. /**
  404. * Creates a bitmap by either downsampling from the thumbnail in EXIF or the full image.
  405. * The functions returns a SizedThumbnailBitmap,
  406. * which contains a downsampled bitmap and the thumbnail data in EXIF if exists.
  407. */
  408. privatestaticvoidcreateThumbnailFromEXIF(String filePath,inttargetSize,
  409. intmaxPixels, SizedThumbnailBitmap sizedThumbBitmap) {
  410. if(filePath ==null)return;
  411. ExifInterface exif = null;
  412. byte[] thumbData =null;
  413. try{
  414. exif = newExifInterface(filePath);
  415. if(exif !=null) {
  416. thumbData = exif.getThumbnail();
  417. }
  418. catch(IOException ex) {
  419. Log.w(TAG, ex);
  420. }
  421. BitmapFactory.Options fullOptions = newBitmapFactory.Options();
  422. BitmapFactory.Options exifOptions = newBitmapFactory.Options();
  423. intexifThumbWidth =0;
  424. intfullThumbWidth =0;
  425. // Compute exifThumbWidth.
  426. if(thumbData !=null) {
  427. exifOptions.inJustDecodeBounds = true;
  428. BitmapFactory.decodeByteArray(thumbData, 0, thumbData.length, exifOptions);
  429. exifOptions.inSampleSize = computeSampleSize(exifOptions, targetSize, maxPixels);
  430. exifThumbWidth = exifOptions.outWidth / exifOptions.inSampleSize;
  431. }
  432. // Compute fullThumbWidth.
  433. fullOptions.inJustDecodeBounds = true;
  434. BitmapFactory.decodeFile(filePath, fullOptions);
  435. fullOptions.inSampleSize = computeSampleSize(fullOptions, targetSize, maxPixels);
  436. fullThumbWidth = fullOptions.outWidth / fullOptions.inSampleSize;
  437. // Choose the larger thumbnail as the returning sizedThumbBitmap.
  438. if(thumbData !=null&& exifThumbWidth >= fullThumbWidth) {
  439. intwidth = exifOptions.outWidth;
  440. intheight = exifOptions.outHeight;
  441. exifOptions.inJustDecodeBounds = false;
  442. sizedThumbBitmap.mBitmap = BitmapFactory.decodeByteArray(thumbData, 0,
  443. thumbData.length, exifOptions);
  444. if(sizedThumbBitmap.mBitmap !=null) {
  445. sizedThumbBitmap.mThumbnailData = thumbData;
  446. sizedThumbBitmap.mThumbnailWidth = width;
  447. sizedThumbBitmap.mThumbnailHeight = height;
  448. }
  449. else{
  450. fullOptions.inJustDecodeBounds = false;
  451. sizedThumbBitmap.mBitmap = BitmapFactory.decodeFile(filePath, fullOptions);
  452. }
  453. }
  454. }

ThumbnailUtils.extractThumbnail Android图片缩略图显示总结及比较相关推荐

  1. Android 图片缩略图显示

    //通过openRawResource获取一个inputStream对象InputStream inputStream = getResources().openRawResource(R.drawa ...

  2. android 图片气泡,android图片上显示气泡消息

    经常需要在一个图片上面显示一个气泡,在气泡上面显示消息的数量.这里提供一种方法,直接设置textview的背景色,并且设置textview的文本信息. xmlns:tools="http:/ ...

  3. android 图片解码显示流程

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/jingxia2008/article/details/32327699 问题来源 android 能 ...

  4. android图片解码显示,android 图片解码显示流程

    问题来源 android 可以在 gallery 里面显示内部存储的图片,支持 jpeg,png,gif,bmp 等,甚至文件类型和图片后缀名不一致,只要是图片文件就能显示,然后 git 只会显示第一 ...

  5. Android 图片黑白显示 自定义饱和度

    Android 自定义显示黑白色图片 1.先下载下来需要显示的图片(或头像) 我模拟下,将图片放到assert文件夹下,拿到他的InputStream.代码如下: 1 InputStream in = ...

  6. android 图片百分比显示,Android编程实现等比例显示图片的方法

    本文实例讲述了Android编程实现等比例显示图片的方法.分享给大家供大家参考,具体如下: 在android中,由于密度的影响,如果想得到图片的宽高是不行的,具体为什么我就大概说一下,具体的请搜索度娘 ...

  7. 魅族note(电信版)缩略图显示不正确问题

    魅族note(电信版)缩略图显示不正确问题 [问题现象]      问题现象: 图片缩略图显示存在多处重复,展示缩略图与原本应该展示的图片不相同.      期待结果: 展示缩略图与原本应该展示的图片 ...

  8. wordpress搜索不了中文linux,WordPress上传带中文汉字名称的图片不显示的解决办法...

    以上是WordPress上传带中文汉字名称的图片不显示的情况,正常上传成功的话,在上图两个地方都会有图片缩略图显示.相信很多WordPress装载linux系统上的朋友都会遇到这样的错误. WordP ...

  9. Android中读取系统图库(包含相册)中的图片,显示图片与图片的路径

    最近有一个需求,是类似于手机相机的功能,拍照,多次拍照(调用系统相机只能进行一次拍照),拍照页面显示一个拍照后的缩略图,点击缩略图后进行拍过的照片的筛选(有单选和多选的问题),以及后续操作(设计相关业 ...

最新文章

  1. Radware LP配置步骤
  2. JQ之赋值方法,new的区别
  3. 二叉树的递归遍历(先序,中序,后序)
  4. python 动态编译代码,Python:在运行时动态创建函数
  5. 如何给数组赋值java_java怎样给数组赋值
  6. 计算机中的字体文件夹在哪,字体文件夹,教您怎么找字体文件夹
  7. windows office visio各版本下载
  8. 文字转换为音频mp3的方法
  9. BOM差异对比——Spreadsheet Compare
  10. (arxiv-2022)具有自适应距离对齐的时空步态特征
  11. 计算机桌面底边出现库如何去掉,桌面图标有蓝底怎么去掉? 去掉桌面图标阴影技巧...
  12. 该网页无法正常运作 HTTP ERROR 500
  13. 计算机硬件的共享,网心云计算机硬件共享app
  14. ubuntu安装discourse论坛----结合在apache服务上建立虚拟主机
  15. 码题集新手村600道(前300道)
  16. SQL的多条件查询语句
  17. Java项目结构及路径
  18. 怎么从微信群聊中引流?如何从群聊进行引流?微信群怎么引流
  19. 推荐系统实践(项亮)读书笔记
  20. matlab中的sig函数,MATLAB——sigmoid传递函数

热门文章

  1. 值得程序员去学习的一些东西
  2. 用ECS做HexMap:不规则化
  3. 安装vscode,下载很慢的解决
  4. 如何加速播放SWF格式文件——使用Enounce MySpeed轻松实现
  5. 转个有意思的东西: 脑残体全论(2007-08-20 13:48)
  6. OCH1660全极高灵敏低功耗霍尔开关
  7. 浏览器有些图片不能显示
  8. R语言作业:样本容量与好样本概率的关系
  9. 1.6.6 解释器 Interpreter
  10. 计算机在水产养殖学中的应用,计算机视觉技术在水产养殖中的应用