如何从 Android 上的相机获取位图?
Posted
技术标签:
【中文标题】如何从 Android 上的相机获取位图?【英文标题】:How can i get bitmap from camera on android? 【发布时间】:2017-03-16 12:23:24 【问题描述】:代码:
public void startCameraActivity()
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (cameraIntent.resolveActivity(getActivity().getPackageManager()) != null)
startActivityForResult(cameraIntent, 1000);
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
if(resultCode == Activity.RESULT_OK)
if (requestCode == 1000)
File photo = new File(Environment.getExternalStorageDirectory(), ".camera.jpg");
OutputStream out = null;
String imagePath = data.getData().getPath();
Bitmap image = BitmapFactory.decodeFile(imagePath);
ExifInterface exif = null;
try
exif = new ExifInterface(imagePath);
int exifOrientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
int exifDegree = exifOrientationToDegrees(exifOrientation);
image = rotate(image, exifDegree);
photo.createNewFile();
out = new FileOutputStream(Environment.getExternalStorageDirectory());
image.compress(Bitmap.CompressFormat.PNG, 100, out);
out.close();
catch (IOException e)
Toast.makeText(getContext(), "hello error", Toast.LENGTH_LONG).show();
returnUri = Uri.fromFile(photo);
Glide.with(this)
.load(returnUri)
.into(mImageview);
用于旋转图像
public int exifOrientationToDegrees(int exifOrientation)
if(exifOrientation == ExifInterface.ORIENTATION_ROTATE_90)
return 90;
else if(exifOrientation == ExifInterface.ORIENTATION_ROTATE_180)
return 180;
else if(exifOrientation == ExifInterface.ORIENTATION_ROTATE_270)
return 270;
return 0;
public Bitmap rotate(Bitmap bitmap, int degrees)
if(degrees != 0 && bitmap != null)
Matrix m = new Matrix();
m.setRotate(degrees, (float) bitmap.getWidth() / 2,
(float) bitmap.getHeight() / 2);
try
Bitmap converted = Bitmap.createBitmap(bitmap, 0, 0,
bitmap.getWidth(), bitmap.getHeight(), m, true);
if(bitmap != converted)
bitmap.recycle();
bitmap = converted;
catch(OutOfMemoryError ex)
return bitmap;
我编写了一个从相机获取图片的代码。
但是那张来自相机的照片方向不正确。
所以我搜索旋转该图像。
但上面的代码不起作用。
问题出在哪里? 我该如何解决?
android 显示器说
java.lang.RuntimeException: Failure delivering result ResultInfowho=null, request=66536, result=-1, data=Intent act=inline-data dat=content://media/external/images/media/8464 flg=0x1 (has extras) to activity ~~!@.MainActivity: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.graphics.Bitmap.compress(android.graphics.Bitmap$CompressFormat, int, java.io.OutputStream)' on a null object reference
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.graphics.Bitmap.compress(android.graphics.Bitmap$CompressFormat, int, java.io.OutputStream)' on a null object reference
编辑完整的logcat
11-03 11:21:42.060 16104-16104/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.keepair.www.pinair, PID: 16104
java.lang.RuntimeException: Failure delivering result ResultInfowho=null, request=66536, result=-1, data=Intent act=inline-data dat=content://media/external/images/media/8465 flg=0x1 (has extras) to activity com.keepair.www.pinair/com.keepair.www.pinair.MainActivity: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.graphics.Bitmap.compress(android.graphics.Bitmap$CompressFormat, int, java.io.OutputStream)' on a null object reference
at android.app.ActivityThread.deliverResults(ActivityThread.java:4173)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4216)
at android.app.ActivityThread.access$1400(ActivityThread.java:181)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1523)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6117)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.graphics.Bitmap.compress(android.graphics.Bitmap$CompressFormat, int, java.io.OutputStream)' on a null object reference
at com.keepair.www.pinair.GreenFragment.onActivityResult(GreenFragment.java:296)
at android.support.v4.app.FragmentActivity.onActivityResult(FragmentActivity.java:165)
at android.app.Activity.dispatchActivityResult(Activity.java:6632)
at android.app.ActivityThread.deliverResults(ActivityThread.java:4169)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4216)
at android.app.ActivityThread.access$1400(ActivityThread.java:181)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1523)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6117)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
【问题讨论】:
能否显示完整的 logcat 异常? 我添加了@criket_007image.compress
正在抛出错误。似乎您从旋转方法返回了 null
【参考方案1】:
这是我写的,你可以试试。
public static final int PICK_USER_PROFILE_IMAGE = 1000;
public void startCameraActivity()
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (cameraIntent.resolveActivity(getActivity().getPackageManager()) != null)
startActivityForResult(cameraIntent, PICK_USER_PROFILE_IMAGE);
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK)
if (requestCode == Constants.PICK_USER_PROFILE_IMAGE)
if (resultCode == RESULT_OK)
Bitmap bmp = ImagePicker.getImageFromResult(this, resultCode, data);
//your compressed rotated bitmap here
下面是 ImagePicker 类,它有一系列的方法来完成你的工作
public class ImagePicker
private static final int DEFAULT_MIN_WIDTH_QUALITY = 400; // min pixels
private static final String TAG = "ImagePicker";
private static final String TEMP_IMAGE_NAME = "tempImage";
public static int minWidthQuality = DEFAULT_MIN_WIDTH_QUALITY;
public static Bitmap getImageFromResult(Context context, int resultCode,
Intent imageReturnedIntent)
Log.d(TAG, "getImageFromResult, resultCode: " + resultCode);
Bitmap bm = null;
File imageFile = getTempFile(context);
if (resultCode == Activity.RESULT_OK)
Uri selectedImage;
boolean isCamera = (imageReturnedIntent == null ||
imageReturnedIntent.getData() == null ||
imageReturnedIntent.getData().equals(Uri.fromFile(imageFile)));
if (isCamera) /** CAMERA **/
selectedImage = Uri.fromFile(imageFile);
else /** ALBUM **/
selectedImage = imageReturnedIntent.getData();
Log.d(TAG, "selectedImage: " + selectedImage);
bm = getImageResized(context, selectedImage);
int rotation = getRotation(context, selectedImage, isCamera);
bm = rotate(bm, rotation);
return bm;
private static Bitmap decodeBitmap(Context context, Uri theUri, int sampleSize)
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = sampleSize;
AssetFileDescriptor fileDescriptor = null;
try
fileDescriptor = context.getContentResolver().openAssetFileDescriptor(theUri, "r");
catch (FileNotFoundException e)
e.printStackTrace();
Bitmap actuallyUsableBitmap = BitmapFactory.decodeFileDescriptor(
fileDescriptor.getFileDescriptor(), null, options);
Log.d(TAG, options.inSampleSize + " sample method bitmap ... " +
actuallyUsableBitmap.getWidth() + " " + actuallyUsableBitmap.getHeight());
return actuallyUsableBitmap;
/**
* Resize to avoid using too much memory loading big images (e.g.: 2560*1920)
**/
private static Bitmap getImageResized(Context context, Uri selectedImage)
Bitmap bm = null;
int[] sampleSizes = new int[]5, 3, 2, 1;
int i = 0;
do
bm = decodeBitmap(context, selectedImage, sampleSizes[i]);
Log.d(TAG, "resizer: new bitmap width = " + bm.getWidth());
i++;
while (bm.getWidth() < minWidthQuality && i < sampleSizes.length);
return bm;
private static int getRotation(Context context, Uri imageUri, boolean isCamera)
int rotation;
if (isCamera)
rotation = getRotationFromCamera(context, imageUri);
else
rotation = getRotationFromGallery(context, imageUri);
Log.d(TAG, "Image rotation: " + rotation);
return rotation;
private static int getRotationFromCamera(Context context, Uri imageFile)
int rotate = 0;
try
context.getContentResolver().notifyChange(imageFile, null);
ExifInterface exif = new ExifInterface(imageFile.getPath());
int orientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
switch (orientation)
case ExifInterface.ORIENTATION_ROTATE_270:
rotate = 270;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotate = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_90:
rotate = 90;
break;
catch (Exception e)
e.printStackTrace();
return rotate;
public static int getRotationFromGallery(Context context, Uri imageUri)
String[] columns = MediaStore.Images.Media.ORIENTATION;
Cursor cursor = context.getContentResolver().query(imageUri, columns, null, null, null);
if (cursor == null) return 0;
cursor.moveToFirst();
int orientationColumnIndex = cursor.getColumnIndex(columns[0]);
return cursor.getInt(orientationColumnIndex);
private static Bitmap rotate(Bitmap bm, int rotation)
if (rotation != 0)
Matrix matrix = new Matrix();
matrix.postRotate(rotation);
Bitmap bmOut = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
return bmOut;
return bm;
private static File getTempFile(Context context)
File imageFile = new File(context.getExternalCacheDir(), TEMP_IMAGE_NAME);
imageFile.getParentFile().mkdirs();
return imageFile;
ImagePicker 类具有处理图像压缩和旋转的所有方法。
希望对你有帮助
【讨论】:
感谢您的回答 rana_sadam【参考方案2】:对于获取实际图像的预定义路径的捕获图像使用
Intent cameraIntent = new Intent(
android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
this.startActivityForResult(cameraIntent, 101);
在捕获图像之后,您可以在 cameraIntent 中设置的路径上获取捕获图像。如果您不想设置预定义路径,请检查 Intent 数据。
if (resultCode == android.app.Activity.RESULT_OK && requestCode == 101)
try
path_mm = "Onsuccess_resultcode";
generateNoteOnSD("photo34.txt", path_mm);
Bitmap photo = null;
if (data == null)
//get Bitmap here.
else
Uri u1 = data.getData();
//get uri and find actual path on that uri.
catch(Exception ex)
【讨论】:
【参考方案3】:首先也许你应该看看这一行:
if(degrees != 0 && bitmap != null)
如果此行为假,则返回“null”,并且监视器会给出该错误。
【讨论】:
以上是关于如何从 Android 上的相机获取位图?的主要内容,如果未能解决你的问题,请参考以下文章