MediaImageItem.java revision ce03445c320042ca144bd4efd8c0356bb7775f9d
1/* 2 * Copyright (C) 2010 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 17package android.media.videoeditor; 18 19import java.io.IOException; 20 21import android.graphics.Bitmap; 22import android.graphics.BitmapFactory; 23import android.graphics.Canvas; 24import android.graphics.Paint; 25import android.graphics.Rect; 26import android.util.Log; 27import android.util.Pair; 28 29/** 30 * This class represents an image item on the storyboard. Note that images are 31 * scaled down to the maximum supported resolution by preserving the native 32 * aspect ratio. To learn the scaled image dimensions use 33 * {@link #getScaledWidth()} and {@link #getScaledHeight()} respectively. 34 * 35 * {@hide} 36 */ 37public class MediaImageItem extends MediaItem { 38 // Logging 39 private static final String TAG = "MediaImageItem"; 40 41 // The resize paint 42 private static final Paint sResizePaint = new Paint(Paint.FILTER_BITMAP_FLAG); 43 44 // Instance variables 45 private final int mWidth; 46 private final int mHeight; 47 private final int mAspectRatio; 48 private long mDurationMs; 49 private int mScaledWidth, mScaledHeight; 50 51 /** 52 * This class cannot be instantiated by using the default constructor 53 */ 54 @SuppressWarnings("unused") 55 private MediaImageItem() throws IOException { 56 this(null, null, null, 0, RENDERING_MODE_BLACK_BORDER); 57 } 58 59 /** 60 * Constructor 61 * 62 * @param editor The video editor reference 63 * @param mediaItemId The media item id 64 * @param filename The image file name 65 * @param durationMs The duration of the image on the storyboard 66 * @param renderingMode The rendering mode 67 * 68 * @throws IOException 69 */ 70 public MediaImageItem(VideoEditor editor, String mediaItemId, String filename, long durationMs, 71 int renderingMode) 72 throws IOException { 73 super(editor, mediaItemId, filename, renderingMode); 74 75 // Determine the dimensions of the image 76 final BitmapFactory.Options dbo = new BitmapFactory.Options(); 77 dbo.inJustDecodeBounds = true; 78 BitmapFactory.decodeFile(filename, dbo); 79 80 mWidth = dbo.outWidth; 81 mHeight = dbo.outHeight; 82 mDurationMs = durationMs; 83 84 // TODO: Determine the aspect ratio from the width and height 85 mAspectRatio = MediaProperties.ASPECT_RATIO_4_3; 86 87 // Images are stored in memory scaled to the maximum resolution to 88 // save memory. 89 final Pair<Integer, Integer>[] resolutions = 90 MediaProperties.getSupportedResolutions(mAspectRatio); 91 // Get the highest resolution 92 final Pair<Integer, Integer> maxResolution = resolutions[resolutions.length - 1]; 93 if (mHeight > maxResolution.second) { 94 // We need to scale the image 95 scaleImage(filename, maxResolution.first, maxResolution.second); 96 mScaledWidth = maxResolution.first; 97 mScaledHeight = maxResolution.second; 98 } else { 99 mScaledWidth = mWidth; 100 mScaledHeight = mHeight; 101 } 102 } 103 104 /* 105 * {@inheritDoc} 106 */ 107 @Override 108 public int getFileType() { 109 if (mFilename.endsWith(".jpg") || mFilename.endsWith(".jpeg")) { 110 return MediaProperties.FILE_JPEG; 111 } else if (mFilename.endsWith(".png")) { 112 return MediaProperties.FILE_PNG; 113 } else { 114 return MediaProperties.FILE_UNSUPPORTED; 115 } 116 } 117 118 /* 119 * {@inheritDoc} 120 */ 121 @Override 122 public int getWidth() { 123 return mWidth; 124 } 125 126 /* 127 * {@inheritDoc} 128 */ 129 @Override 130 public int getHeight() { 131 return mHeight; 132 } 133 134 /** 135 * @return The scaled width of the image. 136 */ 137 public int getScaledWidth() { 138 return mScaledWidth; 139 } 140 141 /** 142 * @return The scaled height of the image. 143 */ 144 public int getScaledHeight() { 145 return mScaledHeight; 146 } 147 148 /* 149 * {@inheritDoc} 150 */ 151 @Override 152 public int getAspectRatio() { 153 return mAspectRatio; 154 } 155 156 /** 157 * This method will adjust the duration of bounding transitions, effects 158 * and overlays if the current duration of the transactions become greater 159 * than the maximum allowable duration. 160 * 161 * @param durationMs The duration of the image in the storyboard timeline 162 */ 163 public void setDuration(long durationMs) { 164 mDurationMs = durationMs; 165 166 adjustTransitions(); 167 adjustOverlays(); 168 adjustEffects(); 169 } 170 171 /* 172 * {@inheritDoc} 173 */ 174 @Override 175 public long getTimelineDuration() { 176 return mDurationMs; 177 } 178 179 /* 180 * {@inheritDoc} 181 */ 182 @Override 183 public Bitmap getThumbnail(int width, int height, long timeMs) throws IOException { 184 return scaleImage(mFilename, width, height); 185 } 186 187 /* 188 * {@inheritDoc} 189 */ 190 @Override 191 public Bitmap[] getThumbnailList(int width, int height, long startMs, long endMs, 192 int thumbnailCount) throws IOException { 193 final Bitmap thumbnail = scaleImage(mFilename, width, height); 194 final Bitmap[] thumbnailArray = new Bitmap[thumbnailCount]; 195 for (int i = 0; i < thumbnailCount; i++) { 196 thumbnailArray[i] = thumbnail; 197 } 198 return thumbnailArray; 199 } 200 201 /** 202 * Resize a bitmap to the specified width and height 203 * 204 * @param filename The filename 205 * @param width The thumbnail width 206 * @param height The thumbnail height 207 * 208 * @return The resized bitmap 209 */ 210 private Bitmap scaleImage(String filename, int width, int height) 211 throws IOException { 212 final BitmapFactory.Options dbo = new BitmapFactory.Options(); 213 dbo.inJustDecodeBounds = true; 214 BitmapFactory.decodeFile(filename, dbo); 215 216 final int nativeWidth = dbo.outWidth; 217 final int nativeHeight = dbo.outHeight; 218 if (Log.isLoggable(TAG, Log.DEBUG)) { 219 Log.d(TAG, "generateThumbnail: Input: " + nativeWidth + "x" + nativeHeight 220 + ", resize to: " + width + "x" + height); 221 } 222 223 final Bitmap srcBitmap; 224 float bitmapWidth, bitmapHeight; 225 if (nativeWidth > width || nativeHeight > height) { 226 float dx = ((float)nativeWidth) / ((float)width); 227 float dy = ((float)nativeHeight) / ((float)height); 228 if (dx > dy) { 229 bitmapWidth = width; 230 bitmapHeight = nativeHeight / dx; 231 } else { 232 bitmapWidth = nativeWidth / dy; 233 bitmapHeight = height; 234 } 235 // Create the bitmap from file 236 if (nativeWidth / bitmapWidth > 1) { 237 final BitmapFactory.Options options = new BitmapFactory.Options(); 238 options.inSampleSize = nativeWidth / (int)bitmapWidth; 239 srcBitmap = BitmapFactory.decodeFile(filename, options); 240 } else { 241 srcBitmap = BitmapFactory.decodeFile(filename); 242 } 243 } else { 244 bitmapWidth = width; 245 bitmapHeight = height; 246 srcBitmap = BitmapFactory.decodeFile(filename); 247 } 248 249 if (srcBitmap == null) { 250 Log.e(TAG, "generateThumbnail: Cannot decode image bytes"); 251 throw new IOException("Cannot decode file: " + mFilename); 252 } 253 254 // Create the canvas bitmap 255 final Bitmap bitmap = Bitmap.createBitmap((int)bitmapWidth, (int)bitmapHeight, 256 Bitmap.Config.ARGB_8888); 257 final Canvas canvas = new Canvas(bitmap); 258 canvas.drawBitmap(srcBitmap, new Rect(0, 0, srcBitmap.getWidth(), srcBitmap.getHeight()), 259 new Rect(0, 0, (int)bitmapWidth, (int)bitmapHeight), sResizePaint); 260 // Release the source bitmap 261 srcBitmap.recycle(); 262 return bitmap; 263 } 264} 265