import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Point;
public class BitmapUtils {
private static final String TAG = "BitmapUtils";
private static final boolean FILTER = true;
private static BitmapFactory.Options _options = new BitmapFactory.Options(); //Q&D pool, assumes single threading
private static Point _dimensions = new Point(0,0); //Q&D pool, assumes single threading
private BitmapUtils(){super();}
//Set either of the dimensions for aspect-correct scaling, or both to force the aspect.
public static Bitmap loadScaledBitmap(final Context context, final String bitmapName,
final int targetWidth, final int targetHeight) throws OutOfMemoryError {
final Resources res = context.getResources();
final int resID = res.getIdentifier(bitmapName, "drawable", context.getPackageName());
return loadScaledBitmap(res, resID, targetWidth, targetHeight);
}
//Set either of the dimensions for aspect-correct scaling, or both to force the aspect.
public static Bitmap loadScaledBitmap(final Resources res, final int resID,
final int targetWidth, final int targetHeight) throws OutOfMemoryError{
_options = readBitmapMetaData(res, resID); //parse raw file info into _options
_dimensions = scaleToTargetDimensions(targetWidth, targetHeight, _options.outWidth, _options.outHeight);
Bitmap bitmap = loadSubSampledBitmap(res, resID, _dimensions.x, _dimensions.y, _options);
if(bitmap != null){
if(bitmap.getHeight() != _dimensions.y || bitmap.getWidth() != _dimensions.x) {
//scale to pixel-perfect dimensions in case we have non-uniform density on x / y
bitmap = Bitmap.createScaledBitmap(bitmap, _dimensions.x, _dimensions.y, FILTER);
}
}
return bitmap;
}
private static Bitmap loadSubSampledBitmap(final Resources res, final int resId, final int targetWidth, final int targetHeight, final BitmapFactory.Options opts) {
opts.inSampleSize = calculateInSampleSize(opts, targetWidth, targetHeight); //calculates clostest POT sample factor
opts.inJustDecodeBounds = false;
opts.inScaled = true; //scale after subsampling, to reach exact target density.
if(targetHeight > 0) {
opts.inDensity = opts.outHeight;
opts.inTargetDensity = targetHeight * opts.inSampleSize;
}else {
opts.inDensity = opts.outWidth;
opts.inTargetDensity = targetWidth * opts.inSampleSize;
}
return BitmapFactory.decodeResource(res, resId, opts);
}
private static int calculateInSampleSize(final BitmapFactory.Options opts, final int reqWidth, final int reqHeight) {
final int height = opts.outHeight;// original height and width of image
final int width = opts.outWidth;
int inSampleSize = 1;
if(height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 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;
}
//loads metadata about a Bitmap into the Options object. Does *not* load the Bitmap.
private static BitmapFactory.Options readBitmapMetaData(final Resources res, final int resID){
_options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resID, _options);
_options.inJustDecodeBounds = false;
return _options;
}
//provide both or either of targetWidth / targetHeight. If one is left at 0, the other is calculated
//based on source-dimensions. Ergo; should scale and keep aspect ratio.
private static Point scaleToTargetDimensions(float targetWidth, float targetHeight,
final float srcWidth, final float srcHeight){
if (targetWidth <= 0 && targetHeight <= 0){
targetWidth = srcWidth;
targetHeight = srcHeight;
}
_dimensions.x = (int) targetWidth;
_dimensions.y = (int) targetHeight;
if(targetWidth == 0 || targetHeight == 0){
//formula: new height = (original height / original width) x new width
if(targetHeight > 0) { //if Y is configured, calculate X
_dimensions.x = (int) ((srcWidth / srcHeight) * targetHeight);
}else { //calculate Y
_dimensions.y = (int) ((srcHeight / srcWidth) * targetWidth);
}
}
return _dimensions;
}
}
Comments
0 B
|0 👍
/0 👎
0 B
|0 👍
/0 👎