OutOfMemoryError与Android中的图像选择。如何在将图像解码为位图之前调整图像大小?

我在我的Android应用程序中构建了一个imagepicker,为此我使用了example code on this page。这基本上给了我一个按钮,可以从SD卡上获取文件,或者通过拍照来打开文件。一旦我选择了一个图像,它会使用一个简单的ImageView来显示图像。一般来说,这很好地工作;我可以选择一个图像,然后再次单击选择图像按钮并选择另一个图像。到目前为止这么好..与小文件是。OutOfMemoryError与Android中的图像选择。如何在将图像解码为位图之前调整图像大小?

当我使用“较大的文件”时,问题就开始了;我只是用内置的手机相机拍下的照片。我可以选择一个,而且效果很好。当我再次打了选择图像按钮,然后选择另一个形象,我就在这行一个OutOfMemoryError(线链接到页面75):

bitmap = BitmapFactory.decodeFile(path); 

我的测试设备是一个相当现代化的一个(银河S4迷你),所以不应该是这个问题。因为我需要将图像发送为Base64字符串,对此我总有需要调整它的API,我可以用这样的调整图像大小:

Bitmap yourBitmap; 

Bitmap resized = Bitmap.createScaledBitmap(yourBitmap, newWidth, newHeight, true);

但不幸的是,为了这个,我首先需要解码该文件实际上首先导致问题。

所以我的问题是,有没有一种方法可以在将图像解码为位图之前调整图像大小?欢迎所有提示!

回答:

虽然加载大的位图文件,BitmapFactory类提供了几种解码方法(decodeByteArray(),decodeFile(),decodeResource(),等等)。

STEP 1

的inJustDecodeBounds属性设置为true,而解码避免了内存分配,为位图对象返回空但设置outWidth,outHeight和outMimeType。该技术允许您在构建位图之前读取图像数据的尺寸和类型(以及内存分配)。

BitmapFactory.Options options = new BitmapFactory.Options(); 

options.inJustDecodeBounds = true;

BitmapFactory.decodeResource(getResources(), R.id.myimage, options);

int imageHeight = options.outHeight;

int imageWidth = options.outWidth;

String imageType = options.outMimeType;

要避免java.lang.OutOfMemory异常,请在解码之前检查位图的维数。

STEP 2

告诉解码器子样本图像,加载一个较小的版本到内存中,设置inSampleSize为true你BitmapFactory.Options对象。

例如,分辨率为2048x1536且用inSampleSize为4解码的图像会生成大约512x384的位图。将其加载到内存中时,整个图像使用0.75MB而不是12MB。

这里的计算样本大小值是两个基于目标宽度和高度的功率的方法:

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, 

int reqWidth, int reqHeight) {

// First decode with inJustDecodeBounds=true to check dimensions

final BitmapFactory.Options options = new BitmapFactory.Options();

options.inJustDecodeBounds = true;

BitmapFactory.decodeResource(res, resId, options);

// Calculate inSampleSize

options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

// Decode bitmap with inSampleSize set

options.inJustDecodeBounds = false;

return BitmapFactory.decodeResource(res, resId, options);

}

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;

}

请仔细阅读本链接了解详情。 http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

回答:

避免这种错误,清单中使用该AQUIRE一大堆:

android:largeHeap="true" 

然后根据你的需要

回答:

试试这个我曾经用它解码位图,再大小。它为我工作。

private Bitmap getBitmap(String path) { 

Uri uri = getImageUri(path);

InputStream in = null;

try {

final int IMAGE_MAX_SIZE = 1200000; // 1.2MP

in = mContentResolver.openInputStream(uri);

// Decode image size

BitmapFactory.Options o = new BitmapFactory.Options();

o.inJustDecodeBounds = true;

BitmapFactory.decodeStream(in, null, o);

in.close();

int scale = 1;

while ((o.outWidth * o.outHeight) * (1/Math.pow(scale, 2)) >

IMAGE_MAX_SIZE) {

scale++;

}

Log.d(TAG, "scale = " + scale + ", orig-width: " + o.outWidth + ",

orig-height: " + o.outHeight);

Bitmap b = null;

in = mContentResolver.openInputStream(uri);

if (scale > 1) {

scale--;

// scale to max possible inSampleSize that still yields an image

// larger than target

o = new BitmapFactory.Options();

o.inSampleSize = scale;

b = BitmapFactory.decodeStream(in, null, o);

// resize to desired dimensions

int height = b.getHeight();

int width = b.getWidth();

Log.d(TAG, "1th scale operation dimenions - width: " + width + ",

height: " + height);

double y = Math.sqrt(IMAGE_MAX_SIZE

/(((double) width)/height));

double x = (y/height) * width;

Bitmap scaledBitmap = Bitmap.createScaledBitmap(b, (int) x,

(int) y, true);

b.recycle();

b = scaledBitmap;

System.gc();

} else {

b = BitmapFactory.decodeStream(in);

}

in.close();

Log.d(TAG, "bitmap size - width: " +b.getWidth() + ", height: " +

b.getHeight());

return b;

} catch (IOException e) {

Log.e(TAG, e.getMessage(),e);

return null;

}

回答:

基本上,您应该使用BitmapFactory.decodeFile(path, options)传递Bitmap.Options.inSampleSize来解码原始位图的子采样版本。

您的代码将是这个样子:

public Bitmap decodeBitmap(String path, int maxWidth, int maxHeight) { 

BitmapFactory.Options options = new BitmapFactory.Options();

options.inJustDecodeBounds = true;

BitmapFactory.decodeFile(path, options);

options.inJustDecodeBounds = false;

options.inSampleSize = calculateInSampleSize(maxWidth, maxHeight, options.outWidth, options.outHeight);

return BitmapFactory.decodeFile(path, options);

}

而且calculateInSampleSize代码:

private int calculateInSampleSize(int maxWidth, int maxHeight, int width, int height) { 

double widthRatio = (double) width/maxWidth;

double heightRatio = (double) height/maxHeight;

double ratio = Math.min(widthRatio, heightRatio);

float n = 1.0f;

while ((n * 2) <= ratio) {

n *= 2;

}

return (int) n;

}

回答:

您可以使用图像采集其加载较小尺寸的图像,而无需加载大。你可以用Options参数传递给BitmapFactory。设置Options.inJustDecodeBoundstrue并且BitmapFactory会将Options.outWidth和Options.outHeight字段设置为图像的原始大小。请注意,将inJustDecodeBounds设置为true时,返回的位图为空。还可以使用Options.inSampleSize解码采样图像。样本大小显示结果图像缩小的程度。

以上是 OutOfMemoryError与Android中的图像选择。如何在将图像解码为位图之前调整图像大小? 的全部内容, 来源链接: utcz.com/qa/259211.html

回到顶部