How can i get bitmap from camera on android?

2019-06-07 05:53发布

问题:

CODE:

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);
        }
    }

It's for rotate image

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;
    } 

I made a code that get picture from camera.

But that picture which has came from camera has incorrect direction.

So i searched to rotate that image.

but above code do not works.

Where is problem? How can i fix it?

Android monitor says

java.lang.RuntimeException: Failure delivering result ResultInfo{who=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

EDIT full 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 ResultInfo{who=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) 

回答1:

Here is what I have written, you can try it.

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

            }
        }
    }
}

Below is the class ImagePicker that have series of methods to do your work

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;
    }
}

The ImagePicker Class have all the methods of handling compression as well as rotation of image.

Hope it will help



回答2:

firstly maybe you should check out this line:

if(degrees != 0 && bitmap != null)

if this line false, "null" returned, and monitor will give that errors.



回答3:

For Get Actual Image predefined path of Captured Image using

Intent cameraIntent = new Intent(
                android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
this.startActivityForResult(cameraIntent, 101); 

After Captured Image you can get Captured Image on path which is set in cameraIntent. If you don't Want to set predefined path then check Intent data.

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)
                     {}}