15052117cc429d85cf446421ca74859f4365747d3Angus Kong/* 25052117cc429d85cf446421ca74859f4365747d3Angus Kong * Copyright (C) 2014 The Android Open Source Project 35052117cc429d85cf446421ca74859f4365747d3Angus Kong * 45052117cc429d85cf446421ca74859f4365747d3Angus Kong * Licensed under the Apache License, Version 2.0 (the "License"); 55052117cc429d85cf446421ca74859f4365747d3Angus Kong * you may not use this file except in compliance with the License. 65052117cc429d85cf446421ca74859f4365747d3Angus Kong * You may obtain a copy of the License at 75052117cc429d85cf446421ca74859f4365747d3Angus Kong * 85052117cc429d85cf446421ca74859f4365747d3Angus Kong * http://www.apache.org/licenses/LICENSE-2.0 95052117cc429d85cf446421ca74859f4365747d3Angus Kong * 105052117cc429d85cf446421ca74859f4365747d3Angus Kong * Unless required by applicable law or agreed to in writing, software 115052117cc429d85cf446421ca74859f4365747d3Angus Kong * distributed under the License is distributed on an "AS IS" BASIS, 125052117cc429d85cf446421ca74859f4365747d3Angus Kong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135052117cc429d85cf446421ca74859f4365747d3Angus Kong * See the License for the specific language governing permissions and 145052117cc429d85cf446421ca74859f4365747d3Angus Kong * limitations under the License. 155052117cc429d85cf446421ca74859f4365747d3Angus Kong */ 165052117cc429d85cf446421ca74859f4365747d3Angus Kong 175052117cc429d85cf446421ca74859f4365747d3Angus Kongpackage com.android.camera.data; 185052117cc429d85cf446421ca74859f4365747d3Angus Kong 195052117cc429d85cf446421ca74859f4365747d3Angus Kongimport android.graphics.Bitmap; 205052117cc429d85cf446421ca74859f4365747d3Angus Kongimport android.graphics.BitmapFactory; 215052117cc429d85cf446421ca74859f4365747d3Angus Kongimport android.graphics.Matrix; 225052117cc429d85cf446421ca74859f4365747d3Angus Kongimport android.graphics.Point; 235052117cc429d85cf446421ca74859f4365747d3Angus Kongimport android.media.MediaMetadataRetriever; 245052117cc429d85cf446421ca74859f4365747d3Angus Kong 252bca210e5fc8a77685775ffb403096167b017dceAngus Kongimport com.android.camera.debug.Log; 265052117cc429d85cf446421ca74859f4365747d3Angus Kong 275052117cc429d85cf446421ca74859f4365747d3Angus Kongimport java.io.InputStream; 285052117cc429d85cf446421ca74859f4365747d3Angus Kong 295052117cc429d85cf446421ca74859f4365747d3Angus Kongimport javax.microedition.khronos.opengles.GL11; 305052117cc429d85cf446421ca74859f4365747d3Angus Kong 315052117cc429d85cf446421ca74859f4365747d3Angus Kong/** 325052117cc429d85cf446421ca74859f4365747d3Angus Kong * An utility class for data in content provider. 335052117cc429d85cf446421ca74859f4365747d3Angus Kong */ 348ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohdepublic class FilmstripItemUtils { 355052117cc429d85cf446421ca74859f4365747d3Angus Kong 362bca210e5fc8a77685775ffb403096167b017dceAngus Kong private static final Log.Tag TAG = new Log.Tag("LocalDataUtil"); 375052117cc429d85cf446421ca74859f4365747d3Angus Kong 385052117cc429d85cf446421ca74859f4365747d3Angus Kong /** 395052117cc429d85cf446421ca74859f4365747d3Angus Kong * @param mimeType The MIME type to check. 405052117cc429d85cf446421ca74859f4365747d3Angus Kong * @return Whether the MIME is a video type. 415052117cc429d85cf446421ca74859f4365747d3Angus Kong */ 425052117cc429d85cf446421ca74859f4365747d3Angus Kong public static boolean isMimeTypeVideo(String mimeType) { 43e11ad6d67ad95a9ecab8a594bcb55a05708abc0fSascha Haeberling return mimeType != null && mimeType.startsWith("video/"); 445052117cc429d85cf446421ca74859f4365747d3Angus Kong } 455052117cc429d85cf446421ca74859f4365747d3Angus Kong 465052117cc429d85cf446421ca74859f4365747d3Angus Kong /** 47732e5c323f495346a7d938b31c180741f95a4a48Radford Juang * Checks whether the MIME type represents an image media item. 48732e5c323f495346a7d938b31c180741f95a4a48Radford Juang * 495052117cc429d85cf446421ca74859f4365747d3Angus Kong * @param mimeType The MIME type to check. 505052117cc429d85cf446421ca74859f4365747d3Angus Kong * @return Whether the MIME is a image type. 515052117cc429d85cf446421ca74859f4365747d3Angus Kong */ 525052117cc429d85cf446421ca74859f4365747d3Angus Kong public static boolean isMimeTypeImage(String mimeType) { 53e11ad6d67ad95a9ecab8a594bcb55a05708abc0fSascha Haeberling return mimeType != null && mimeType.startsWith("image/"); 545052117cc429d85cf446421ca74859f4365747d3Angus Kong } 555052117cc429d85cf446421ca74859f4365747d3Angus Kong 562666dc8a1c23b7c2b7c80d7c09104f113fb7dbb2Sam Judd 572666dc8a1c23b7c2b7c80d7c09104f113fb7dbb2Sam Judd /** 582666dc8a1c23b7c2b7c80d7c09104f113fb7dbb2Sam Judd * Decodes the dimension of a bitmap. 592666dc8a1c23b7c2b7c80d7c09104f113fb7dbb2Sam Judd * 602666dc8a1c23b7c2b7c80d7c09104f113fb7dbb2Sam Judd * @param is An input stream with the data of the bitmap. 612666dc8a1c23b7c2b7c80d7c09104f113fb7dbb2Sam Judd * @return The decoded width/height is stored in Point.x/Point.y 622666dc8a1c23b7c2b7c80d7c09104f113fb7dbb2Sam Judd * respectively. 632666dc8a1c23b7c2b7c80d7c09104f113fb7dbb2Sam Judd */ 642666dc8a1c23b7c2b7c80d7c09104f113fb7dbb2Sam Judd public static Point decodeBitmapDimension(InputStream is) { 652666dc8a1c23b7c2b7c80d7c09104f113fb7dbb2Sam Judd Point size = null; 665052117cc429d85cf446421ca74859f4365747d3Angus Kong BitmapFactory.Options justBoundsOpts = new BitmapFactory.Options(); 675052117cc429d85cf446421ca74859f4365747d3Angus Kong justBoundsOpts.inJustDecodeBounds = true; 682666dc8a1c23b7c2b7c80d7c09104f113fb7dbb2Sam Judd BitmapFactory.decodeStream(is, null, justBoundsOpts); 695052117cc429d85cf446421ca74859f4365747d3Angus Kong if (justBoundsOpts.outWidth > 0 && justBoundsOpts.outHeight > 0) { 702666dc8a1c23b7c2b7c80d7c09104f113fb7dbb2Sam Judd size = new Point(justBoundsOpts.outWidth, justBoundsOpts.outHeight); 71de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd } else { 722666dc8a1c23b7c2b7c80d7c09104f113fb7dbb2Sam Judd Log.e(TAG, "Bitmap dimension decoding failed"); 735052117cc429d85cf446421ca74859f4365747d3Angus Kong } 745052117cc429d85cf446421ca74859f4365747d3Angus Kong return size; 755052117cc429d85cf446421ca74859f4365747d3Angus Kong } 765052117cc429d85cf446421ca74859f4365747d3Angus Kong 775052117cc429d85cf446421ca74859f4365747d3Angus Kong /** 785052117cc429d85cf446421ca74859f4365747d3Angus Kong * Load the thumbnail of an image from an {@link java.io.InputStream}. 795052117cc429d85cf446421ca74859f4365747d3Angus Kong * 805052117cc429d85cf446421ca74859f4365747d3Angus Kong * @param stream The input stream of the image. 815052117cc429d85cf446421ca74859f4365747d3Angus Kong * @param imageWidth Image width. 825052117cc429d85cf446421ca74859f4365747d3Angus Kong * @param imageHeight Image height. 835052117cc429d85cf446421ca74859f4365747d3Angus Kong * @param widthBound The bound of the width of the decoded image. 845052117cc429d85cf446421ca74859f4365747d3Angus Kong * @param heightBound The bound of the height of the decoded image. 855052117cc429d85cf446421ca74859f4365747d3Angus Kong * @param orientation The orientation of the image. The image will be rotated 865052117cc429d85cf446421ca74859f4365747d3Angus Kong * clockwise in degrees. 875052117cc429d85cf446421ca74859f4365747d3Angus Kong * @param maximumPixels The bound for the number of pixels of the decoded image. 885052117cc429d85cf446421ca74859f4365747d3Angus Kong * @return {@code null} if the decoding failed. 895052117cc429d85cf446421ca74859f4365747d3Angus Kong */ 905052117cc429d85cf446421ca74859f4365747d3Angus Kong public static Bitmap loadImageThumbnailFromStream(InputStream stream, int imageWidth, 915052117cc429d85cf446421ca74859f4365747d3Angus Kong int imageHeight, int widthBound, int heightBound, int orientation, 925052117cc429d85cf446421ca74859f4365747d3Angus Kong int maximumPixels) { 935052117cc429d85cf446421ca74859f4365747d3Angus Kong 945052117cc429d85cf446421ca74859f4365747d3Angus Kong /** 32K buffer. */ 955052117cc429d85cf446421ca74859f4365747d3Angus Kong byte[] decodeBuffer = new byte[32 * 1024]; 965052117cc429d85cf446421ca74859f4365747d3Angus Kong 97c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong if (orientation % 180 != 0) { 98c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong int dummy = imageHeight; 99c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong imageHeight = imageWidth; 100c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong imageWidth = dummy; 101c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong } 102c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong 1035052117cc429d85cf446421ca74859f4365747d3Angus Kong // Generate Bitmap of maximum size that fits into widthBound x heightBound. 1045052117cc429d85cf446421ca74859f4365747d3Angus Kong // Algorithm: start with full size and step down in powers of 2. 1055052117cc429d85cf446421ca74859f4365747d3Angus Kong int targetWidth = imageWidth; 1065052117cc429d85cf446421ca74859f4365747d3Angus Kong int targetHeight = imageHeight; 1075052117cc429d85cf446421ca74859f4365747d3Angus Kong int sampleSize = 1; 1085052117cc429d85cf446421ca74859f4365747d3Angus Kong while (targetHeight > heightBound || targetWidth > widthBound || 1095052117cc429d85cf446421ca74859f4365747d3Angus Kong targetHeight > GL11.GL_MAX_TEXTURE_SIZE || targetWidth > GL11.GL_MAX_TEXTURE_SIZE || 1105052117cc429d85cf446421ca74859f4365747d3Angus Kong targetHeight * targetWidth > maximumPixels) { 1115052117cc429d85cf446421ca74859f4365747d3Angus Kong sampleSize <<= 1; 1125052117cc429d85cf446421ca74859f4365747d3Angus Kong targetWidth = imageWidth / sampleSize; 1135052117cc429d85cf446421ca74859f4365747d3Angus Kong targetHeight = imageWidth / sampleSize; 1145052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1155052117cc429d85cf446421ca74859f4365747d3Angus Kong 1165052117cc429d85cf446421ca74859f4365747d3Angus Kong // For large (> MAXIMUM_TEXTURE_SIZE) high aspect ratio (panorama) 1175052117cc429d85cf446421ca74859f4365747d3Angus Kong // Bitmap requests: 1185052117cc429d85cf446421ca74859f4365747d3Angus Kong // Step 1: ask for double size. 1195052117cc429d85cf446421ca74859f4365747d3Angus Kong // Step 2: scale maximum edge down to MAXIMUM_TEXTURE_SIZE. 1205052117cc429d85cf446421ca74859f4365747d3Angus Kong // 1215052117cc429d85cf446421ca74859f4365747d3Angus Kong // Here's the step 1: double size. 1225052117cc429d85cf446421ca74859f4365747d3Angus Kong if ((heightBound > GL11.GL_MAX_TEXTURE_SIZE || widthBound > GL11.GL_MAX_TEXTURE_SIZE) && 1235052117cc429d85cf446421ca74859f4365747d3Angus Kong targetWidth * targetHeight < maximumPixels / 4 && sampleSize > 1) { 1245052117cc429d85cf446421ca74859f4365747d3Angus Kong sampleSize >>= 2; 1255052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1265052117cc429d85cf446421ca74859f4365747d3Angus Kong 1275052117cc429d85cf446421ca74859f4365747d3Angus Kong BitmapFactory.Options opts = new BitmapFactory.Options(); 1285052117cc429d85cf446421ca74859f4365747d3Angus Kong opts.inSampleSize = sampleSize; 1295052117cc429d85cf446421ca74859f4365747d3Angus Kong opts.inTempStorage = decodeBuffer; 1305052117cc429d85cf446421ca74859f4365747d3Angus Kong Bitmap b = BitmapFactory.decodeStream(stream, null, opts); 1315052117cc429d85cf446421ca74859f4365747d3Angus Kong 1325052117cc429d85cf446421ca74859f4365747d3Angus Kong if (b == null) { 1335052117cc429d85cf446421ca74859f4365747d3Angus Kong return null; 1345052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1355052117cc429d85cf446421ca74859f4365747d3Angus Kong 1365052117cc429d85cf446421ca74859f4365747d3Angus Kong // Step 2: scale maximum edge down to maximum texture size. 1375052117cc429d85cf446421ca74859f4365747d3Angus Kong // If Bitmap maximum edge > MAXIMUM_TEXTURE_SIZE, which can happen for panoramas, 1385052117cc429d85cf446421ca74859f4365747d3Angus Kong // scale to fit in MAXIMUM_TEXTURE_SIZE. 1395052117cc429d85cf446421ca74859f4365747d3Angus Kong if (b.getWidth() > GL11.GL_MAX_TEXTURE_SIZE || b.getHeight() > 1405052117cc429d85cf446421ca74859f4365747d3Angus Kong GL11.GL_MAX_TEXTURE_SIZE) { 1415052117cc429d85cf446421ca74859f4365747d3Angus Kong int maxEdge = Math.max(b.getWidth(), b.getHeight()); 1425052117cc429d85cf446421ca74859f4365747d3Angus Kong b = Bitmap.createScaledBitmap(b, b.getWidth() * GL11.GL_MAX_TEXTURE_SIZE / maxEdge, 1435052117cc429d85cf446421ca74859f4365747d3Angus Kong b.getHeight() * GL11.GL_MAX_TEXTURE_SIZE / maxEdge, false); 1445052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1455052117cc429d85cf446421ca74859f4365747d3Angus Kong 1465052117cc429d85cf446421ca74859f4365747d3Angus Kong // Not called often because most modes save image data non-rotated. 1475052117cc429d85cf446421ca74859f4365747d3Angus Kong if (orientation != 0 && b != null) { 1485052117cc429d85cf446421ca74859f4365747d3Angus Kong Matrix m = new Matrix(); 1495052117cc429d85cf446421ca74859f4365747d3Angus Kong m.setRotate(orientation); 1505052117cc429d85cf446421ca74859f4365747d3Angus Kong b = Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), m, false); 1515052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1525052117cc429d85cf446421ca74859f4365747d3Angus Kong 1535052117cc429d85cf446421ca74859f4365747d3Angus Kong return b; 1545052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1555052117cc429d85cf446421ca74859f4365747d3Angus Kong 1565052117cc429d85cf446421ca74859f4365747d3Angus Kong /** 1575052117cc429d85cf446421ca74859f4365747d3Angus Kong * Loads the thumbnail of a video. 1585052117cc429d85cf446421ca74859f4365747d3Angus Kong * 1595052117cc429d85cf446421ca74859f4365747d3Angus Kong * @param path The path to the video file. 1605052117cc429d85cf446421ca74859f4365747d3Angus Kong * @return {@code null} if the loading failed. 1615052117cc429d85cf446421ca74859f4365747d3Angus Kong */ 1625052117cc429d85cf446421ca74859f4365747d3Angus Kong public static Bitmap loadVideoThumbnail(String path) { 1635052117cc429d85cf446421ca74859f4365747d3Angus Kong Bitmap bitmap = null; 1645052117cc429d85cf446421ca74859f4365747d3Angus Kong MediaMetadataRetriever retriever = new MediaMetadataRetriever(); 1655052117cc429d85cf446421ca74859f4365747d3Angus Kong try { 1665052117cc429d85cf446421ca74859f4365747d3Angus Kong retriever.setDataSource(path); 1675052117cc429d85cf446421ca74859f4365747d3Angus Kong byte[] data = retriever.getEmbeddedPicture(); 1685052117cc429d85cf446421ca74859f4365747d3Angus Kong if (data != null) { 1695052117cc429d85cf446421ca74859f4365747d3Angus Kong bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); 1705052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1715052117cc429d85cf446421ca74859f4365747d3Angus Kong if (bitmap == null) { 1725052117cc429d85cf446421ca74859f4365747d3Angus Kong bitmap = retriever.getFrameAtTime(); 1735052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1745052117cc429d85cf446421ca74859f4365747d3Angus Kong } catch (IllegalArgumentException e) { 1755052117cc429d85cf446421ca74859f4365747d3Angus Kong Log.e(TAG, "MediaMetadataRetriever.setDataSource() fail:" + e.getMessage()); 1765052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1775052117cc429d85cf446421ca74859f4365747d3Angus Kong retriever.release(); 1785052117cc429d85cf446421ca74859f4365747d3Angus Kong return bitmap; 1795052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1805052117cc429d85cf446421ca74859f4365747d3Angus Kong} 181