0
votes

I want to scale an existing bitmap. So I use Bitmap.createBitmap(Bitmap b, int x, int y, int width, int height, Matrix m, boolean filter) to create a scaled bitmap. If the scale ratio of the Matrix object is less than 1, this method works well. However, if the ratio is equal to or greater than 1, the method returns a bitmap with the width and height i desire but without an image (is transparent). I wonder why and how to solve this.

    Bitmap imageBitmap;
    imageBitmap = weiboView.getDrawingCache();
    Log.d("cosmo", "bitmap generated: "+imageBitmap.getWidth()+" * "+imageBitmap.getHeight());

    //Init and configure and load the image view
    ImageView imageView = new ImageView(this);
    imageView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
    imageView.setScaleType(ScaleType.FIT_CENTER);
    containerLayout.addView(imageView);

    //create a scaled bitmap to assign to the image view
    Bitmap scaledImageBitmap = MyBitmapUtils.getBitmapScaledToFitWidth(getWindowManager().getDefaultDisplay().getWidth(), imageBitmap);
    Log.d("cosmo", "scaled: "+scaledImageBitmap.getWidth()+" * "+scaledImageBitmap.getHeight());
    //Here if I set imageBitmap as the image of imageView it works well
    imageView.setImageBitmap(scaledImageBitmap);

Here is MyBitmapUtils.getBitmapScaledToFitWidth:

public static Bitmap getBitmapScaledToFitWidth(int targetWidth, Bitmap bitmap) {
    float ratio = (float)targetWidth/(float)bitmap.getWidth();
    Log.d("cosmo", "ratio is "+ratio);
    //ratio = 0.5f;
    Matrix matrix = new Matrix();
    matrix.postScale(ratio, ratio);
    Bitmap target = Bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),bitmap.getHeight(),matrix,false);
    return target;
}

I have known how did this happen. It's because that the height of the Image is greater than 2048, and in android's system creating a bitmap bigger than 2048*2048 will cause OOM (My logcat didn't report this error, oddly)

1
and why do you need scaled Bitmap? do you want to save it on the sdcard or send somewhere?pskink
Just want to scale it to fit an image view with a specified widthCosmo
no, no, no, dont do that, use scaleType="matrix" and call setImageMatrix, or use any other aspect ratio preserving scaleTypepskink

1 Answers

0
votes

Why don't you just use createScaledBitmap?

Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, targetWidth, targetHeight, true);

You can supply the targetWidth and targetHeight directly and it should be more reliable than scaling the bitmap yourself with a Matrix.

If you just supply the targetWidth to your method then you have to calculate the targetHeight which would look something like this:

float ratio = (float)targetWidth/(float)bitmap.getWidth();
int targetHeight = (int)((float)bitmap.getHeight * ratio);

And if you put that in your method it would look like this:

public static Bitmap getBitmapScaledToFitWidth(double targetWidth, Bitmap bitmap) {
    double bitmapWidth = bitmap.getWidth();
    double bitmapHeight = bitmap.getHeight();

    double widthRatio = targetWidth / bitmapWidth;
    double targetHeight = widthRatio * bitmapHeight;

    Bitmap target = Bitmap.createScaledBitmap(bitmap, (int)targetWidth, (int)targetHeight, true);
    return target;
}

Also don't forget to recycle() not needed bitmaps as often and as soon as possible. That can prevent you from running into memory problems, for example if you don't need the not scaled bitmap anymore after scaling it you can recycle it directly in your helper method:

public static Bitmap getBitmapScaledToFitWidth(double targetWidth, Bitmap bitmap) {
    double bitmapWidth = bitmap.getWidth();
    double bitmapHeight = bitmap.getHeight();

    double widthRatio = targetWidth / bitmapWidth;
    double targetHeight = widthRatio * bitmapHeight;

    Bitmap target = Bitmap.createScaledBitmap(bitmap, (int)targetWidth, (int)targetHeight, true);

    // Recycle old bitmap to free up memory.
    bitmap.recycle();

    return target;
}