如果需要,BitMapFactory可以增加图像的大小

时间:2013-12-26 17:37:15

标签: java android bitmap

我正在浏览BitmapFactory,发现我们可以减小图像的大小,如果它高于我们想要的大小,以避免内存异常。但是增加高度+宽度的方法是什么。目前我正在使用Bitmap.createScaledBitmap ..

以下是代码:

package sudipta.deb.imagedisplayer;

import sudipta.deb.image.ImageSources;
import android.os.Bundle;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener {

    private static final String IMAGE_TAG = "Image Tag";
    private final int PREFERRED_HEIGHT = 400;
    private final int PREFERRED_WIDTH = 533;
    private static int imageIndex;
    private int totalImages;
    private Bitmap bitmap;
    private ImageView imageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initialize();
    }

    private void initialize() {
        ImageSources.configureImages();
        imageIndex = 0;
        totalImages = ImageSources.totalImages();

        imageView = ((ImageView) findViewById(R.id.imageView1));
        imageView.setOnClickListener(this);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    private Bitmap checkBitmapDetails(int index) {
        Bitmap bitmap;
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;

        BitmapFactory.decodeResource(getResources(),
                ImageSources.getImageId(index), options);

        int imageHeight = options.outHeight;
        int imageWidth = options.outWidth;

        Log.i(IMAGE_TAG, "Image: " + index);
        Log.i(IMAGE_TAG, "Image Height: " + imageHeight);
        Log.i(IMAGE_TAG, "Image width: " + imageWidth);

        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, PREFERRED_WIDTH,
                PREFERRED_HEIGHT);

        options.inJustDecodeBounds = false;

        bitmap = BitmapFactory.decodeResource(getResources(),
                ImageSources.getImageId(index), options);
        bitmap = Bitmap.createScaledBitmap(bitmap, PREFERRED_WIDTH,
                PREFERRED_HEIGHT, false);
        return bitmap;
    }

    public static int calculateInSampleSize(BitmapFactory.Options options,
            int reqWidth, int reqHeight) {
        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.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;
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.imageView1:
            imageIndex++;
            if (imageIndex >= totalImages) {
                imageIndex = 0;
            }
            Log.i(IMAGE_TAG, "Loading Image: " + imageIndex);
            bitmap = checkBitmapDetails(imageIndex);
            imageView.setImageBitmap(bitmap);
            break;

        default:
            break;
        }

    }

}

您是否有更好的信息以更好的方式执行此操作?感谢。

3 个答案:

答案 0 :(得分:0)

您可以使用ImageViewscaleTypeadjustViewBounds参数对其进行拉伸,但在屏幕上显示时会有效。但是如果你想在这里调整bmp的大小,你可以去:

 /**
  * Returns given @Bitmap resized the to given size.
  * 
  * @param bm : Bitmap to resize.
  * @param newHeight : Height to resize.
  * @param newWidth : Width to resize.
  * @return Resized Bitmap.
  */
public static Bitmap getResizedBitmap(Bitmap bitmap, int newHeight, int newWidth) {

    if (bitmap == null || newHeight<0 ||  newWidth<0 || newHeight+newWidth==0)
        return null;

    Bitmap resizedBitmap = null;
    final int height = bitmap.getHeight();
    final int width = bitmap.getWidth();

    if (newHeight==0)
        newHeight = (int)((float)newWidth * (float)height / (float)width);

    if (newWidth==0)
        newWidth = (int)((float)newHeight * (float)width / (float)height);

    float scaleHeight = ((float) newHeight) / height;
    float scaleWidth = ((float) newWidth) / width;

    // create a matrix for the manipulation
    final Matrix matrix = new Matrix();
    // resize the bit map
    matrix.postScale(scaleWidth, scaleHeight);

    try {
        // recreate the new Bitmap
        resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
        // resizedBitmap = Bitmap.createScaledBitmap(bm, newWidth, // newHeight, true);
    } catch (Exception e) {
        android.util.Log.e(TAG, e.getMessage());
        resizedBitmap = null;
    } catch (Throwable e) {
        android.util.Log.e(TAG, e.getMessage());
        resizedBitmap = null;
    } 

    return resizedBitmap;
}

答案 1 :(得分:0)

最后,我找到了处理这种情况的解决方案。 我所做的是,如果图像大小大于首选大小,那么首先缩小大小,然后使用createScaledBitmap将图像缩放到精确大小。

private Bitmap checkBitmapDetails(int index) {
        Bitmap bitmap;
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;

        bitmap = BitmapFactory.decodeResource(getResources(),
                ImageSources.getImageId(index), options);

        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, PREFERRED_WIDTH,
                PREFERRED_HEIGHT);

        options.inJustDecodeBounds = false;

        bitmap = BitmapFactory.decodeResource(getResources(),
                ImageSources.getImageId(index), options);
        bitmap = Bitmap.createScaledBitmap(bitmap, PREFERRED_WIDTH, PREFERRED_HEIGHT, true);
        return bitmap;
    }

    public static int calculateInSampleSize(BitmapFactory.Options options,
            int reqWidth, int reqHeight) {
        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.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;
    }

答案 2 :(得分:0)

createScaledBitmap导致存在两个位图(原始位置和放大位置)的情况,这可能会在某些情况下导致OOM(取决于堆大小和位移操作的大小)。

如果可能,请尝试仅在放大的图像视图中使用原件。

如果您愿意,可以尝试使用我为了克服同时存在2个位图的内存问题而创建的库,here(关于它的帖子here)。