我需要将位图转换为字节数组以便上传到服务器。我成功地通过将位图转换为字节数组,然后按照这里的说明再将其转换为Base 64字符串来实现此操作。它的工作效果很好,但在我的Galaxy S2手机上,如果图像大小为6MB,分辨率为72像素/英寸,它占用了约600MB的RAM,并因OutOfMemoryException而崩溃。我尝试通过压缩位图来上传,它可以正常工作,但根据我的项目要求,我需要上传原始图像,即不进行任何压缩。
请帮助我如何实现这一点,无论是否有可能。
谢谢您提前的帮助。
请帮助我如何实现这一点,无论是否有可能。
谢谢您提前的帮助。
上传时转换为JPEG流
BufferedStream bs = //...
然后调用bitmap.compress("JPEG", 0, length, bs)
将bs转换为数组并上传到服务器
Android应用程序分配内存堆是有限的,特别是在低内存设备上。
您正在犯两个常见错误:
首先,关于上传问题 - 您正在持有完整大小图像的位图对象(可能是使用相机拍摄的)。这是第一次犯错。如果您必须在用户界面上显示捕获的图像,则应根据所需的显示大小(ImageView
的宽度和高度)从刚刚捕获和创建的捕获图像文件中加载缩放版本位图:
public static Bitmap getSampleBitmapFromFile(String bitmapFilePath, int reqWidth, int reqHeight) {
try {
File f = new File(bitmapFilePath);
ExifInterface exif = new ExifInterface(f.getPath());
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
int angle = 0;
if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
angle = 90;
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) {
angle = 180;
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
angle = 270;
}
Matrix mat = new Matrix();
mat.postRotate(angle);
// 计算图像大小
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f), null, options);
int scale = calculateInSampleSize(options, reqWidth, reqHeight);
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
Bitmap bmp = BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
Bitmap correctBmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), mat, true);
return correctBmp;
} catch (IOException e) {
Log.e(TAG, "cant butmaputils.getSampleBitmapFromFile failed with IO exception: ", e);
if (e != null)
e.printStackTrace();
} catch (OutOfMemoryError oom) {
Log.e(TAG, "cant butmaputils.getSampleBitmapFromFile failed with OOM error: ");
if (oom != null)
oom.printStackTrace();
} catch (Exception e) {
Log.e(TAG, "cant butmaputils.getSampleBitmapFromFile failed with exception: ", e);
}
Log.e(TAG, "butmaputils.getSampleBitmapFromFilereturn null for file: " + bitmapFilePath);
return null;
}
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
// 图像的原始高度和宽度
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
// 计算高度和宽度与请求高度和宽度的比率
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
// 选择最小比率作为inSampleSize值,这将保证
// 最终图像的两个尺寸都大于或等于所请求的高度和宽度。
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
仅通过这种方式,您就可以大大减少内存分配堆的压力,因为您可以只分配100x200而不是1080x1920个整数,如果这是您的imageView屏幕尺寸。
使用这种方法,不会对内存分配堆产生任何影响,即使您想上传100M-1000M的文件也没有关系。
更多阅读材料,请参阅http://developer.android.com/training/displaying-bitmaps/load-bitmap.html