diff options
Diffstat (limited to 'src/org/cyanogenmod/themes/provider/util/BitmapUtils.java')
-rw-r--r-- | src/org/cyanogenmod/themes/provider/util/BitmapUtils.java | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/src/org/cyanogenmod/themes/provider/util/BitmapUtils.java b/src/org/cyanogenmod/themes/provider/util/BitmapUtils.java new file mode 100644 index 0000000..002970b --- /dev/null +++ b/src/org/cyanogenmod/themes/provider/util/BitmapUtils.java @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2014 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.cyanogenmod.themes.provider.util; + +import android.content.Context; +import android.content.res.AssetManager; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.BitmapRegionDecoder; +import android.graphics.Rect; +import android.net.Uri; +import android.util.Log; +import android.util.TypedValue; + +import java.io.Closeable; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; + +public class BitmapUtils { + private static final String TAG = "BitmapUtils"; + + /** + * Returns the bitmap from the given uri loaded using the given options. + * Returns null on failure. + */ + public static Bitmap loadBitmap(Context context, InputStream is, BitmapFactory.Options o) { + try { + return BitmapFactory.decodeStream(is, null, o); + } finally { + closeSilently(is); + } + } + + public static Bitmap decodeFile(String path, int reqWidth, int reqHeight) { + FileInputStream fis = null; + try { + fis = new FileInputStream(path); + return decodeStream(fis, reqWidth, reqHeight); + } catch (FileNotFoundException e) { + Log.e(TAG, "Unable to open resource in path" + path, e); + } finally { + closeSilently(fis); + } + return null; + } + + public static Bitmap decodeStream(InputStream is, int reqWidth, int reqHeight) { + BitmapFactory.Options opts = new BitmapFactory.Options(); + + // Determine insample size + opts.inJustDecodeBounds = true; + BitmapFactory.decodeStream(is, null, opts); + opts.inSampleSize = calculateInSampleSize(opts, reqWidth, reqHeight); + + // Decode the bitmap, regionally if necessary + Bitmap bitmap = null; + opts.inJustDecodeBounds = false; + Rect rect = getCropRectIfNecessary(opts, reqWidth, reqHeight); + try { + if (rect != null) { + BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is, false); + bitmap = decoder.decodeRegion(rect, opts); + } else { + bitmap = BitmapFactory.decodeStream(is, null, opts); + } + } catch (IOException e) { + Log.e(TAG, "Unable to decode bitmap from stream", e); + } + return bitmap; + } + + public static Bitmap decodeResource(Resources res, int resId, int reqWidth, int reqHeight) { + BitmapFactory.Options opts = new BitmapFactory.Options(); + + // Determine insample size + opts.inJustDecodeBounds = true; + BitmapFactory.decodeResource(res, resId, opts); + opts.inSampleSize = calculateInSampleSize(opts, reqWidth, reqHeight); + + // Decode the bitmap, regionally if necessary + Bitmap bitmap = null; + opts.inJustDecodeBounds = false; + Rect rect = getCropRectIfNecessary(opts, reqWidth, reqHeight); + + InputStream stream = null; + try { + if (rect != null) { + stream = res.openRawResource(resId, new TypedValue()); + if (stream == null) return null; + BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(stream, false); + bitmap = decoder.decodeRegion(rect, opts); + } else { + bitmap = BitmapFactory.decodeResource(res, resId, opts); + } + } catch (IOException e) { + Log.e(TAG, "Unable to open resource " + resId, e); + } finally { + closeSilently(stream); + } + return bitmap; + } + + + public static Bitmap decodeByteArray(byte[] buffer, int reqWidth, int reqHeight) { + BitmapFactory.Options opts = new BitmapFactory.Options(); + + // Determine insample size + opts.inJustDecodeBounds = true; + BitmapFactory.decodeByteArray(buffer, 0, buffer.length, opts); + opts.inSampleSize = calculateInSampleSize(opts, reqWidth, reqHeight); + + // Decode the bitmap, regionally if necessary + Bitmap bitmap = null; + opts.inJustDecodeBounds = false; + Rect rect = getCropRectIfNecessary(opts, reqWidth, reqHeight); + try { + if (rect != null) { + BitmapRegionDecoder decoder = + BitmapRegionDecoder.newInstance(buffer, 0, buffer.length, false); + bitmap = decoder.decodeRegion(rect, opts); + } else { + bitmap = BitmapFactory.decodeByteArray(buffer, 0, buffer.length, opts); + } + } catch (IOException e) { + Log.e(TAG, "Unable to decode bitmap from stream", e); + } + return bitmap; + } + + public static Bitmap getBitmapFromAsset(Context ctx, String path, int reqWidth, int reqHeight) { + if (ctx == null || path == null) + return null; + + Bitmap bitmap = null; + try { + AssetManager assets = ctx.getAssets(); + InputStream is = assets.open(path); + bitmap = decodeStream(is, reqWidth, reqHeight); + } catch (IOException e) { + e.printStackTrace(); + } + return bitmap; + } + + + /** + * For excessively large images with an awkward ratio we + * will want to crop them + * @return + */ + public static Rect getCropRectIfNecessary( + BitmapFactory.Options options,int reqWidth, int reqHeight) { + final int width = options.outWidth; + final int height = options.outHeight; + Rect rect = new Rect(0, 0, width, height); + // Determine downsampled size + int targetWidth = reqWidth * options.inSampleSize; + int targetHeight = reqHeight * options.inSampleSize; + + if (targetHeight < height) { + rect.top = (height - targetHeight) / 2; + rect.bottom = rect.top + targetHeight; + } + if (targetWidth < width) { + rect.left = (width - targetWidth) / 2; + rect.right = rect.left + targetWidth; + } + return rect; + } + + public static int calculateInSampleSize( + BitmapFactory.Options options, int reqWidth, int reqHeight) { + return calculateInSampleSize(options.outWidth, options.outHeight, reqWidth, reqHeight); + } + + // Modified from original source: + // http://developer.android.com/training/displaying-bitmaps/load-bitmap.html + public static int calculateInSampleSize( + int decodeWidth, int decodeHeight, int reqWidth, int reqHeight) { + // Raw height and width of image + int inSampleSize = 1; + + if (decodeHeight > reqHeight || decodeWidth > reqWidth) { + final int halfHeight = decodeHeight / 2; + final int halfWidth = decodeWidth / 2; + + // Calculate the largest inSampleSize value that is a power of 2 and keeps both + // height and width larger than the requested height and width. + while ((halfHeight / inSampleSize) > reqHeight && + (halfWidth / inSampleSize) > reqWidth) { + inSampleSize *= 2; + } + } + + return inSampleSize; + } + + public static void closeSilently(Closeable c) { + if (c == null) return; + try { + c.close(); + } catch (IOException t) { + Log.w(TAG, "close fail ", t); + } + } +} |