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.inJustDecodeBounds
true
并且BitmapFactory会将Options.outWidth和Options.outHeight字段设置为图像的原始大小。请注意,将inJustDecodeBounds设置为true时,返回的位图为空。还可以使用Options.inSampleSize解码采样图像。样本大小显示结果图像缩小的程度。
以上是 OutOfMemoryError与Android中的图像选择。如何在将图像解码为位图之前调整图像大小? 的全部内容, 来源链接: utcz.com/qa/259211.html