Sta*_*tan 7 memory android memory-management image out-of-memory
public static boolean rotateBitmapByExifAndSave(File targetFile){
if (targetFile==null || !targetFile.exists() || !targetFile.canRead() || !targetFile.canWrite())
return false;
boolean isSucceed = false;
// detect if photo is need to be rotated
try {
final Matrix matrix = new Matrix();
ExifInterface exifReader = new ExifInterface(targetFile.getAbsolutePath());
int orientation = exifReader.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
boolean isRotationNeeded = true;
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
matrix.postRotate(90);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
matrix.postRotate(180);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
matrix.postRotate(270);
break;
default: // ExifInterface.ORIENTATION_NORMAL
// Do nothing. The original image is fine.
isRotationNeeded = false;
isSucceed = true;
break;
}
if (isRotationNeeded){
BitmapFactory.Options bmfOtions = new BitmapFactory.Options();
Bitmap bitmap = null;
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(targetFile);
bitmap = BitmapFactory.decodeStream(fileInputStream,null,bmfOtions);
} catch (FileNotFoundException e){
isSucceed = false;
}
finally {
if (fileInputStream != null)
try {
fileInputStream.close();
} catch (IOException e) {}
}
if (bitmap!=null){
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
isSucceed = ImageUtils.saveBitmapToFile(bitmap, targetFile, 100);
bitmap.recycle();
}
}
} catch (IOException e) {
Log.e("ImageUtils", e);
} catch (Exception e) {
// like there is no EXIF support?
Log.e("ImageUtils", e);
} catch (Throwable e) {
// stupid Out of VM's memory
Log.e("ImageUtils", e.toString());
}
return isSucceed;
}
Run Code Online (Sandbox Code Playgroud)
我用这种方法旋转设备相机拍摄的原始照片.如今相机可能大于8MPix(三星Galaxy S4拥有13百万像素摄像头).即使使用较少的MPix相机(我的是5 MP,2592 x 1944像素,结合ARGB_888 根据官方文档需要19Mb RAM)我已经获得OutOfMemory.所以问题是如何在不损失初始分辨率和质量的情况下旋转照片?
由于没有答案,我认为没有答案,或者也许我只是问得有点不正确。看起来这里唯一的选择是增加应用程序的堆大小
更新:
还有另一种选择 - 通过 NDK/JNI 处理位图(如下所示)或使用Android Image-Magic lib。Image Magic 库非常酷,要旋转图像,您只需要:
ImageInfo imageInfo = new ImageInfo(imageFile.getAbsolutePath());
MagickImage magickImage = new MagickImage(imageInfo);
magickImage.setCompression(100); // to minimize loss
magickImage.rotateImage(90.0f).writeImage(imageInfo);
Run Code Online (Sandbox Code Playgroud)
MagickImage 还有许多其他图像操作选项。模糊、哑光、比例、木炭等等。然而它的库大小是值得注意的。作者做得很好,他们涵盖了所有可能的平台:arm64-v8a、armeabi、armeabi-v7a、mips、mips64、x86、x86_64,所有这些库的最终大小超过 36Mb。因此,在将所有库添加到一个 apk 中之前,您应该考虑一下,也许使用清单按芯片组/平台过滤来打包 6 个不同版本是正确的方法。
更新
另一个选择是将不可变位图转换为可变(将位图包装到 MappedByteBuffer 中)
| 归档时间: |
|
| 查看次数: |
4165 次 |
| 最近记录: |