Android - 正在保存从相机拍摄的照片,内存不足
Android - Saving photo taken from Camera , Out of memory
我有一个用例,用户拍照并且照片必须保存在 sd 卡上。
我已经将相机的方向设置为纵向。
虽然 saving the photo on to SD card
我得到 out of memory
.
这是日志 -
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask.done(AsyncTask.java:300)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:841)
Caused by: java.lang.OutOfMemoryError
at android.graphics.Bitmap.nativeCreate(Native Method)
at android.graphics.Bitmap.createBitmap(Bitmap.java:809)
at android.graphics.Bitmap.createBitmap(Bitmap.java:786)
at android.graphics.Bitmap.createBitmap(Bitmap.java:718)
at com.philips.cl.di.haircare.util.AppUtility.changeOrientationAndwriteDataToFile(AppUtility.java:382)
at com.philips.cl.di.haircare.mirror.MirrorCameraViewFragment$SaveBitMap.doInBackground(MirrorCameraViewFragment.java:389)
at com.philips.cl.di.haircare.mirror.MirrorCameraViewFragment$SaveBitMap.doInBackground(MirrorCameraViewFragment.java:369)
at android.os.AsyncTask.call(AsyncTask.java:288)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
... 4 more
这是我用来保存的功能 -
public static boolean changeOrientationAndwriteDataToFile(Context context,
final File pictureFile, final byte[] data, final int camId)
throws Exception {
FileOutputStream fos = null;
Bitmap realImage = null;
try {
fos = new FileOutputStream(pictureFile);
realImage = BitmapFactory.decodeByteArray(data, 0, data.length);
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(camId, info);
Matrix matrix = new Matrix();
int rotation = info.orientation;
int camfacing = info.facing;
if (camfacing == 1) {
matrix.setScale(1, -1);
}
if (rotation != 0) {
matrix.postRotate(rotation);
} else {
matrix.postRotate(-90);
}
realImage = Bitmap.createBitmap(realImage, 0, 0,
realImage.getWidth(), realImage.getHeight(), matrix, false);
MediaScannerConnection.scanFile(context,
new String[] { pictureFile.getPath() },
new String[] { "image/jpeg" }, null);
// 100 means maximum quality
return realImage.compress(Bitmap.CompressFormat.JPEG, 100, fos);
} catch (final Exception e) {
throw e;
} finally {
if (realImage != null) {
realImage.recycle();
}
if (fos != null) {
fos.close();
}
}
}
行号 - 382 内存不足。
realImage = Bitmap.createBitmap(realImage, 0, 0,
realImage.getWidth(), realImage.getHeight(), matrix, false);
请帮忙解决这个问题。
谢谢。
您可以将 android:largeHeap="true"
添加到您的 AndroidManifest.xml
这是一种解决方法。小心使用。
创建新的位图对象而不是重新创建 realImage
我用BitmapFactory Options
解决了
这是更新后的方法 -
public static boolean changeOrientationAndwriteDataToFile(Context context,
final File pictureFile, final byte[] data, final int camId, int reqWidth , int reqHeight )
throws Exception {
FileOutputStream fos = null;
Bitmap realImage = null;
Bitmap transformedImage = null ;
try {
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(camId, info);
int rotation = info.orientation;
int camfacing = info.facing;
// Out of memory issue fixx -with the sample size concept
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true ;
BitmapFactory.decodeByteArray(data, 0, data.length, options);
options.inSampleSize = calculateInSampleSize(options,reqWidth,reqHeight);
System.out.println("Sample Size : " + options.inSampleSize);
options.inPreferredConfig = Bitmap.Config.RGB_565;
options.inJustDecodeBounds = false;
realImage= BitmapFactory.decodeByteArray(data, 0, data.length, options);
Matrix matrix = new Matrix();
if (camfacing == 1) {
matrix.setScale(1, -1);
}
if (rotation != 0) {
matrix.postRotate(rotation);
} else {
matrix.postRotate(-90);
}
transformedImage = Bitmap.createBitmap(realImage, 0, 0,
realImage.getWidth(), realImage.getHeight(), matrix, false);
MediaScannerConnection.scanFile(context,
new String[] { pictureFile.getPath() },
new String[] { "image/jpeg" }, null);
fos = new FileOutputStream(pictureFile);
// 100 means maximum quality
return transformedImage.compress(Bitmap.CompressFormat.JPEG, 100, fos);
} catch (final Exception e) {
throw e;
} finally {
if (realImage != null) {
realImage.recycle();
}
if(transformedImage !=null)
{
transformedImage.recycle();
}
if (fos != null) {
fos.close();
}
}
}
这里 - reqWidth
和 reqHeight
是 screen width
和 screen height
因为我必须在全屏上显示位图。
谢谢。
我有一个用例,用户拍照并且照片必须保存在 sd 卡上。
我已经将相机的方向设置为纵向。
虽然 saving the photo on to SD card
我得到 out of memory
.
这是日志 -
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask.done(AsyncTask.java:300)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:841)
Caused by: java.lang.OutOfMemoryError
at android.graphics.Bitmap.nativeCreate(Native Method)
at android.graphics.Bitmap.createBitmap(Bitmap.java:809)
at android.graphics.Bitmap.createBitmap(Bitmap.java:786)
at android.graphics.Bitmap.createBitmap(Bitmap.java:718)
at com.philips.cl.di.haircare.util.AppUtility.changeOrientationAndwriteDataToFile(AppUtility.java:382)
at com.philips.cl.di.haircare.mirror.MirrorCameraViewFragment$SaveBitMap.doInBackground(MirrorCameraViewFragment.java:389)
at com.philips.cl.di.haircare.mirror.MirrorCameraViewFragment$SaveBitMap.doInBackground(MirrorCameraViewFragment.java:369)
at android.os.AsyncTask.call(AsyncTask.java:288)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
... 4 more
这是我用来保存的功能 -
public static boolean changeOrientationAndwriteDataToFile(Context context,
final File pictureFile, final byte[] data, final int camId)
throws Exception {
FileOutputStream fos = null;
Bitmap realImage = null;
try {
fos = new FileOutputStream(pictureFile);
realImage = BitmapFactory.decodeByteArray(data, 0, data.length);
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(camId, info);
Matrix matrix = new Matrix();
int rotation = info.orientation;
int camfacing = info.facing;
if (camfacing == 1) {
matrix.setScale(1, -1);
}
if (rotation != 0) {
matrix.postRotate(rotation);
} else {
matrix.postRotate(-90);
}
realImage = Bitmap.createBitmap(realImage, 0, 0,
realImage.getWidth(), realImage.getHeight(), matrix, false);
MediaScannerConnection.scanFile(context,
new String[] { pictureFile.getPath() },
new String[] { "image/jpeg" }, null);
// 100 means maximum quality
return realImage.compress(Bitmap.CompressFormat.JPEG, 100, fos);
} catch (final Exception e) {
throw e;
} finally {
if (realImage != null) {
realImage.recycle();
}
if (fos != null) {
fos.close();
}
}
}
行号 - 382 内存不足。
realImage = Bitmap.createBitmap(realImage, 0, 0,
realImage.getWidth(), realImage.getHeight(), matrix, false);
请帮忙解决这个问题。
谢谢。
您可以将 android:largeHeap="true"
添加到您的 AndroidManifest.xml
这是一种解决方法。小心使用。
创建新的位图对象而不是重新创建 realImage
我用BitmapFactory Options
解决了
这是更新后的方法 -
public static boolean changeOrientationAndwriteDataToFile(Context context,
final File pictureFile, final byte[] data, final int camId, int reqWidth , int reqHeight )
throws Exception {
FileOutputStream fos = null;
Bitmap realImage = null;
Bitmap transformedImage = null ;
try {
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(camId, info);
int rotation = info.orientation;
int camfacing = info.facing;
// Out of memory issue fixx -with the sample size concept
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true ;
BitmapFactory.decodeByteArray(data, 0, data.length, options);
options.inSampleSize = calculateInSampleSize(options,reqWidth,reqHeight);
System.out.println("Sample Size : " + options.inSampleSize);
options.inPreferredConfig = Bitmap.Config.RGB_565;
options.inJustDecodeBounds = false;
realImage= BitmapFactory.decodeByteArray(data, 0, data.length, options);
Matrix matrix = new Matrix();
if (camfacing == 1) {
matrix.setScale(1, -1);
}
if (rotation != 0) {
matrix.postRotate(rotation);
} else {
matrix.postRotate(-90);
}
transformedImage = Bitmap.createBitmap(realImage, 0, 0,
realImage.getWidth(), realImage.getHeight(), matrix, false);
MediaScannerConnection.scanFile(context,
new String[] { pictureFile.getPath() },
new String[] { "image/jpeg" }, null);
fos = new FileOutputStream(pictureFile);
// 100 means maximum quality
return transformedImage.compress(Bitmap.CompressFormat.JPEG, 100, fos);
} catch (final Exception e) {
throw e;
} finally {
if (realImage != null) {
realImage.recycle();
}
if(transformedImage !=null)
{
transformedImage.recycle();
}
if (fos != null) {
fos.close();
}
}
}
这里 - reqWidth
和 reqHeight
是 screen width
和 screen height
因为我必须在全屏上显示位图。
谢谢。