1 /*
2  * Copyright (C) 2013 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 com.android.gallery3d.ingest.data;
18 
19 import android.annotation.TargetApi;
20 import android.content.Context;
21 import android.graphics.Bitmap;
22 import android.graphics.BitmapFactory;
23 import android.mtp.MtpDevice;
24 import android.os.Build;
25 import android.util.DisplayMetrics;
26 import android.view.WindowManager;
27 
28 import com.android.gallery3d.data.Exif;
29 import com.android.photos.data.GalleryBitmapPool;
30 
31 /**
32  * Helper class for fetching bitmaps from MTP devices.
33  */
34 @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
35 public class MtpBitmapFetch {
36   private static int sMaxSize = 0;
37 
recycleThumbnail(Bitmap b)38   public static void recycleThumbnail(Bitmap b) {
39     if (b != null) {
40       GalleryBitmapPool.getInstance().put(b);
41     }
42   }
43 
getThumbnail(MtpDevice device, IngestObjectInfo info)44   public static Bitmap getThumbnail(MtpDevice device, IngestObjectInfo info) {
45     byte[] imageBytes = device.getThumbnail(info.getObjectHandle());
46     if (imageBytes == null) {
47       return null;
48     }
49     BitmapFactory.Options o = new BitmapFactory.Options();
50     o.inJustDecodeBounds = true;
51     BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length, o);
52     if (o.outWidth == 0 || o.outHeight == 0) {
53       return null;
54     }
55     o.inBitmap = GalleryBitmapPool.getInstance().get(o.outWidth, o.outHeight);
56     o.inMutable = true;
57     o.inJustDecodeBounds = false;
58     o.inSampleSize = 1;
59     try {
60       return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length, o);
61     } catch (IllegalArgumentException e) {
62       // BitmapFactory throws an exception rather than returning null
63       // when image decoding fails and an existing bitmap was supplied
64       // for recycling, even if the failure was not caused by the use
65       // of that bitmap.
66       return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
67     }
68   }
69 
getFullsize(MtpDevice device, IngestObjectInfo info)70   public static BitmapWithMetadata getFullsize(MtpDevice device, IngestObjectInfo info) {
71     return getFullsize(device, info, sMaxSize);
72   }
73 
getFullsize(MtpDevice device, IngestObjectInfo info, int maxSide)74   public static BitmapWithMetadata getFullsize(MtpDevice device, IngestObjectInfo info,
75       int maxSide) {
76     byte[] imageBytes = device.getObject(info.getObjectHandle(), info.getCompressedSize());
77     if (imageBytes == null) {
78       return null;
79     }
80     Bitmap created;
81     if (maxSide > 0) {
82       BitmapFactory.Options o = new BitmapFactory.Options();
83       o.inJustDecodeBounds = true;
84       BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length, o);
85       int w = o.outWidth;
86       int h = o.outHeight;
87       int comp = Math.max(h, w);
88       int sampleSize = 1;
89       while ((comp >> 1) >= maxSide) {
90         comp = comp >> 1;
91         sampleSize++;
92       }
93       o.inSampleSize = sampleSize;
94       o.inJustDecodeBounds = false;
95       created = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length, o);
96     } else {
97       created = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
98     }
99     if (created == null) {
100       return null;
101     }
102 
103     int orientation = Exif.getOrientation(imageBytes);
104     return new BitmapWithMetadata(created, orientation);
105   }
106 
configureForContext(Context context)107   public static void configureForContext(Context context) {
108     DisplayMetrics metrics = new DisplayMetrics();
109     WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
110     wm.getDefaultDisplay().getMetrics(metrics);
111     sMaxSize = Math.max(metrics.heightPixels, metrics.widthPixels);
112   }
113 }
114