Chromium Code Reviews| Index: chrome/android/java/src/org/chromium/chrome/browser/photo_picker/BitmapUtils.java |
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/BitmapUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/BitmapUtils.java |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..f448622a203b96a98a89e8c7de336ad86435dfce |
| --- /dev/null |
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/BitmapUtils.java |
| @@ -0,0 +1,160 @@ |
| +// Copyright 2017 The Chromium Authors. All rights reserved. |
|
Theresa
2017/03/31 18:05:55
Is this class being used anywhere currently?
Finnur
2017/04/03 17:30:29
Huh... You are right. Removed.
|
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +package org.chromium.chrome.browser.photo_picker; |
| + |
| +import android.graphics.Bitmap; |
| +import android.graphics.BitmapFactory; |
| + |
| +import java.io.FileDescriptor; |
| + |
| +class BitmapUtils { |
| + /** |
| + * Takes a |bitmap| and returns a square thumbnail of |width| from the center of the bitmap |
| + * specified. |
| + * @param bitmap The bitmap to adjust. |
| + * @param width The desired width. |
| + * @return The new bitmap thumbnail. |
| + */ |
| + public static Bitmap sizeBitmap(Bitmap bitmap, int width) { |
| + bitmap = ensureMinSize(bitmap, width); |
| + bitmap = cropToSquare(bitmap, width); |
| + return bitmap; |
| + } |
| + |
| + /** |
| + * Given a FileDescriptor, decodes the contents and returns a bitmap of size |width|x|width|. |
| + * @param descriptor The FileDescriptor for the file to read. |
| + * @param width The width of the bitmap to return. |
| + * @return The resulting bitmap. |
| + */ |
| + public static Bitmap decodeBitmapFromFileDescriptor(FileDescriptor descriptor, int width) { |
| + BitmapFactory.Options options = createSizingOptions(); |
| + BitmapFactory.decodeFileDescriptor(descriptor, null, options); |
| + Bitmap bitmap = BitmapFactory.decodeFileDescriptor( |
|
Theresa
2017/03/31 18:05:55
Why does this call decodeFileDescriptor twice? Sam
Finnur
2017/04/03 17:30:29
Because that's how the sub-sampling is implemented
|
| + descriptor, null, createDecodingOptions(options, width)); |
| + |
| + if (bitmap == null) return null; |
| + |
| + return sizeBitmap(bitmap, width); |
| + } |
| + |
| + /** |
| + * Given a file path, decodes the contents of the file and returns a bitmap of size |
| + * |width|x|width|. |
| + * @param filePath The path to the file to read. |
| + * @param width The width of the bitmap to return. |
| + * @return The resulting bitmap. |
| + */ |
| + public static Bitmap decodeBitmapFromDisk(String filePath, int width) { |
| + BitmapFactory.Options options = createSizingOptions(); |
| + BitmapFactory.decodeFile(filePath, options); |
| + Bitmap bitmap = BitmapFactory.decodeFile(filePath, createDecodingOptions(options, width)); |
| + |
| + if (bitmap == null) return null; |
| + |
| + return sizeBitmap(bitmap, width); |
| + } |
| + |
| + /** |
| + * Creates a {@link BitmapFactory#Options} object ready for size calculations. |
| + */ |
| + private static BitmapFactory.Options createSizingOptions() { |
| + BitmapFactory.Options options = new BitmapFactory.Options(); |
| + options.inJustDecodeBounds = true; |
| + return options; |
| + } |
| + |
| + /** |
| + * Converts a {@link BitmapFactory#Options} object for size calculations into a decoding options |
| + * object, with optimal decoding size specified. |
| + */ |
| + private static BitmapFactory.Options createDecodingOptions( |
| + BitmapFactory.Options sizingOptions, int width) { |
| + sizingOptions.inSampleSize = calculateInSampleSize(sizingOptions, width, width); |
| + sizingOptions.inJustDecodeBounds = false; |
| + return sizingOptions; |
| + } |
| + |
| + /** |
| + * Calculates the sub-sampling factor {@link BitmapFactory#inSampleSize} option for a given |
| + * bitmap option, which will be used to create a bitmap of a pre-determined size (no larger than |
| + * |width| and |height|). |
| + * @param options The bitmap options to consider. |
| + * @param width The requested width. |
| + * @param height The requested height. |
| + * @return The sub-sampling factor (1 = no change, 2 = half-size, etc). |
| + */ |
| + private static int calculateInSampleSize(BitmapFactory.Options options, int width, int height) { |
| + int inSampleSize = 1; |
| + |
| + if (options.outHeight > height || options.outWidth > width) { |
| + final int halfHeight = options.outHeight / 2; |
| + final int halfWidth = options.outWidth / 2; |
| + |
| + while ((halfHeight / inSampleSize) >= height || (halfWidth / inSampleSize) >= width) { |
| + inSampleSize *= 2; |
| + } |
| + } |
| + |
| + return inSampleSize; |
| + } |
| + |
| + /** |
| + * Scales a |bitmap| to a certain size. |
| + * @param bitmap The bitmap to scale. |
| + * @param scaleMaxSize What to scale it to. |
| + * @param filter True if the source should be filtered. |
| + * @return The resulting scaled bitmap. |
| + */ |
| + public static Bitmap scale(Bitmap bitmap, float scaleMaxSize, boolean filter) { |
| + float ratio = Math.min((float) scaleMaxSize / bitmap.getWidth(), |
| + (float) scaleMaxSize / bitmap.getHeight()); |
| + int height = Math.round(ratio * bitmap.getHeight()); |
| + int width = Math.round(ratio * bitmap.getWidth()); |
| + |
| + return Bitmap.createScaledBitmap(bitmap, width, height, filter); |
| + } |
| + |
| + /** |
| + * Ensures a |bitmap| is at least |size| in both width and height. |
| + * @param bitmap The bitmap to modify. |
| + * @param size The minimum size (width and height). |
| + * @return The resulting (scaled) bitmap. |
| + */ |
| + private static Bitmap ensureMinSize(Bitmap bitmap, int size) { |
| + int width = bitmap.getWidth(); |
| + int height = bitmap.getHeight(); |
| + if (width < size) { |
| + float scale = (float) size / width; |
| + width = size; |
| + height *= scale; |
| + } |
| + |
| + if (height < size) { |
| + float scale = (float) size / height; |
| + height = size; |
| + width *= scale; |
| + } |
| + |
| + return Bitmap.createScaledBitmap(bitmap, width, height, true); |
| + } |
| + |
| + /** |
| + * Crops a |bitmap| to a certain square |size| |
| + * @param bitmap The bitmap to crop. |
| + * @param size The size desired (width and height). |
| + * @return The resulting (square) bitmap. |
| + */ |
| + private static Bitmap cropToSquare(Bitmap bitmap, int size) { |
| + int x = 0; |
| + int y = 0; |
| + int width = bitmap.getWidth(); |
| + int height = bitmap.getHeight(); |
| + |
| + if (width > size) x = (width - size) / 2; |
| + if (height > size) y = (height - size) / 2; |
| + return Bitmap.createBitmap(bitmap, x, y, size, size); |
| + } |
| +} |