John Nguyen
John Nguyen

Reputation: 557

Android: Take Picture, then immediately do crop w/o needing to select from gallery

I have complete working code to take a picture, crop it, send email with image attachment.

Here is the flow of the code: Take a picture > Find and select the picture we just took from Gallery > Crop it > Email attachment.

I would like to find out how I can skip the whole "Find and select the picture we just took from Gallery" part out and just go straight into cropping immediately after taking the picture.

Is there an Intent that can do what I am requesting?

I've tried this tutorial but it still makes the user go into gallery and look for the picture they just took http://www.londatiga.net/featured-articles/how-to-select-and-crop-image-on-android/

EDIT I should also mention that I have a custom view when I am taking pictures so Im not sure if I can use Intent MediaStore.ACTION_IMAGE_CAPTURE

Here is the code that executes the cropping AND also makes you choose the image you just took by looking in the gallery.

        Intent crop_pic = new Intent(Intent.ACTION_PICK, uriTarget); // used to be ACTION_GET_CONTENT /ACTION_PICK
           crop_pic.putExtra("crop", "true");                           // this enables crop feature                                                        
           //crop_pic.putExtra("aspectX", 200);                         // this defines the aspect ration
           //crop_pic.putExtra("aspectY", 150);                     
           //crop_pic.putExtra("outputX", 500);                         // this defines the output bitmap size
           //crop_pic.putExtra("outputY", 500);     
           //crop_pic.putExtra("scale", true);
  try {    crop_pic.putExtra("return-data", false);                     // true to return a Bitmap, false to directly save the cropped iamge                            
           crop_pic.putExtra(MediaStore.EXTRA_OUTPUT, uriTarget);       // save output image in uri     
           //crop_pic.setDataAndType(uriTarget, "image/*");             // this will open all images in the Galery
           startActivityForResult(crop_pic, EMAIL_PIC);
           overridePendingTransition(R.anim.fadein, R.anim.fadeout);    
         } 
  catch    (ActivityNotFoundException e) {
           toast.showToastDialog(getApplicationContext(), e.toString());    
         }   
  LOGCAT.DEBUG(TAG, "Cropping Picture");

  }

Is there an Intent im not aware of that can just start cropping if I supply it with a uri Target?

Here is the full code:

 public class DigitalSignature extends Activity implements SurfaceHolder.Callback{

            Camera    camera;
     SurfaceHolder    surfaceHolder;
           boolean    previewing = false;

               Uri    uriTarget;
          String[]    recipients = new String[]{"[email protected]", "",}; 
         final int    CROP_PIC = 1, EMAIL_PIC = 2, RETURN_ACTIVITY = 3, FINISH = 4, INDEX_GALLERY = 5;  

     final  String    TAG = "Digital Signature";

     ToastBuilder     toast = new ToastBuilder(this);
     ProjectDebug     LOGCAT = new ProjectDebug();  
 ProgressDialogManager    pDialog = new ProgressDialogManager();




@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

                DigitalSignature.this.requestWindowFeature(Window.FEATURE_NO_TITLE);         
                DigitalSignature.this.setContentView(R.layout.digitalsignature);
                DigitalSignature.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);   

                DigitalSignature.this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);            
                DigitalSignature.this.getWindow().setFormat(PixelFormat.TRANSLUCENT); // Used to be TRANSPARENT



                SurfaceView     surfaceView = (SurfaceView)findViewById(R.id.camerapreview);
                                surfaceHolder = surfaceView.getHolder();
                                surfaceHolder.addCallback(DigitalSignature.this);
                                surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

                LayoutInflater  controlInflater = LayoutInflater.from(getApplicationContext());
                View            viewControl = controlInflater.inflate(R.layout.control, null);
                LayoutParams    layoutParamsControl = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);

                DigitalSignature.this.addContentView(viewControl, layoutParamsControl); // Applying Filters and Parameters


                TextView        alignsig = (TextView)findViewById(R.id.alignsig);
                                alignsig.setText("Please take picture of the signature for" + "\n" + "Job Number " + DIGIJOB);

                Button          buttonTakePicture = (Button)findViewById(R.id.takepicture);
                                buttonTakePicture.setOnClickListener(new Button.OnClickListener(){



        @Override
        public void onClick(View arg0) {    
            LOGCAT.DEBUG(TAG, "Taking Picture");


                    // Sets camera monochrome filter ( Black and Whiite )
                    Camera.Parameters parameters = camera.getParameters();        
                    parameters.setColorEffect(android.hardware.Camera.Parameters.EFFECT_MONO);
                    camera.setParameters(parameters);        
                    camera.startPreview(); 


                    // Initiate Camera Focus
                    camera.autoFocus(mAutoFocusCallback);

                    // Creates Directory to save image in gallery
                    uriTarget = getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, new ContentValues());   

                    //Notify the MediaScanner that a new file has been added and should be indexed so it shows up in the MediaStore.
                    Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
                    intent.setData(uriTarget);
                    sendBroadcast(intent);

                    }
             });
        }






Camera.AutoFocusCallback mAutoFocusCallback = new Camera.AutoFocusCallback() {

    @Override
    public void onAutoFocus(boolean success, Camera camera) {

        camera.takePicture(myShutterCallback, myPictureCallback_RAW, myPictureCallback_JPG);
    }
    };


ShutterCallback myShutterCallback = new ShutterCallback(){

    @Override
    public void onShutter() {

    }};


PictureCallback myPictureCallback_RAW = new PictureCallback(){

    @Override
    public void onPictureTaken(byte[] arg0, Camera arg1) {

    }};


PictureCallback myPictureCallback_JPG = new PictureCallback(){

    @Override
    public void onPictureTaken(byte[] arg0, Camera arg1) {
        //bmp = BitmapFactory.decodeByteArray(arg0, 0, arg0.length);    

        cropPic();

   OutputStream imageFileOS;
        try {   
                imageFileOS = getContentResolver().openOutputStream(uriTarget); 
                imageFileOS.write(arg0);
                imageFileOS.flush();
                imageFileOS.close();

                toast.showToastDialog(getApplicationContext(), "Image saved: " + uriTarget.toString());                             
            } 


      catch     (IOException e) {
                toast.showToastDialog(getApplicationContext(), e.toString());   
            }       

            // camera.startPreview(); // No need to start preview, we are saving
            }};                       // picture and no longer initiating camera






   protected void onActivityResult(int requestCode, int resultCode, Intent data) {

     switch     (requestCode) {

        case      CROP_PIC:
                    cropPic();
                    LOGCAT.DEBUG(TAG, "cropPic Case");      
       break;


        case      EMAIL_PIC:
                    emailPic();
                    LOGCAT.DEBUG(TAG, "emailPic Case");         
        break;                                                                  


        case      RETURN_ACTIVITY:  
                    returnActivity();
                    LOGCAT.DEBUG(TAG, "returnActivity Case");           
        break; 
            }       
    }



  private void cropPic() {  


    Intent crop_pic = new Intent(Intent.ACTION_PICK, uriTarget); // used to be ACTION_GET_CONTENT /ACTION_PICK
           crop_pic.putExtra("crop", "true");                           // this enables crop feature                                                        
           //crop_pic.putExtra("aspectX", 200);                         // this defines the aspect ration
           //crop_pic.putExtra("aspectY", 150);                     
           //crop_pic.putExtra("outputX", 500);                         // this defines the output bitmap size
           //crop_pic.putExtra("outputY", 500);     
           //crop_pic.putExtra("scale", true);
  try {    crop_pic.putExtra("return-data", false);                     // true to return a Bitmap, false to directly save the cropped iamge                            
           crop_pic.putExtra(MediaStore.EXTRA_OUTPUT, uriTarget);       // save output image in uri     
           //crop_pic.setDataAndType(uriTarget, "image/*");             // this will open all images in the Galery
           startActivityForResult(crop_pic, EMAIL_PIC);
           overridePendingTransition(R.anim.fadein, R.anim.fadeout);    
         } 
  catch    (ActivityNotFoundException e) {
           toast.showToastDialog(getApplicationContext(), e.toString());    
         }   
  LOGCAT.DEBUG(TAG, "Cropping Picture");

  }



  private void emailPic(){

     // new email_pic().execute();     

        GMailSender m = new GMailSender("[email protected]", "testtest");

        String[] toArr = { "[email protected]" };
        m.setTo(toArr);
        m.setFrom("[email protected]");
        m.setSubject("This is an email sent using my Mail JavaMail wrapper from an Android device.");
        m.setBody("Email body.");

        try { 
          m.addAttachment(getRealPathFromURI(uriTarget)); 

          if(m.send()) { 
            Toast.makeText(DigitalSignature.this, "Email was sent successfully.", Toast.LENGTH_LONG).show(); 
          } else { 
            Toast.makeText(DigitalSignature.this, "Email was not sent.", Toast.LENGTH_LONG).show(); 
          } 

        } catch(Exception e) {
          //Toast.makeText(MailApp.this, "There was a problem sending the email.", Toast.LENGTH_LONG).show(); 
          Log.e("MailApp", "Could not send email", e); 
        } 


      // OLD METHOD OF SENDING EMAIL
    /*  Intent email_pic = new Intent(Intent.ACTION_SEND);      // Commence choose photo action         
        email_pic.putExtra(Intent.EXTRA_EMAIL, recipients);     // Inserts Digital Signature address automatically in recipient
        email_pic.putExtra(Intent.EXTRA_SUBJECT, DIGIJOB);      // Inserts Track Number automatically in subject
        email_pic.putExtra(Intent.EXTRA_STREAM, uriTarget);     // Attaches image to Gmail
        email_pic.setType("image/jpeg");                        // Converts image to jpeg
        startActivityForResult(email_pic, RETURN_ACTIVITY); 
        overridePendingTransition(R.anim.fadein, R.anim.fadeout);   */
        JOB = "job";                                            // Reset job variable from track no (1736) to "job" so                                                                          
        LOGCAT.DEBUG(TAG, "Emailing Picture");                      // when you go back into Jobs Activity, it can parse data.

      returnActivity();

  }






  private void returnActivity() {
      Intent email_pic = new Intent(DigitalSignature.this, AgentPortalActivity.class);
      startActivityForResult(email_pic, FINISH);
      overridePendingTransition(R.anim.fadein, R.anim.fadeout);      
      LOGCAT.DEBUG(TAG, "Returning Activity");
  }





  private String getRealPathFromURI(Uri uriTarget) {

                String[] projection = { MediaStore.Images.Media.DATA };
                @SuppressWarnings("deprecation")
                Cursor cursor = managedQuery(uriTarget, projection, null, null, null);
                int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                                    cursor.moveToFirst();     

            LOGCAT.DEBUG("getRealPathFromURI", cursor.getString(column_index));
            return cursor.getString(column_index);

}



@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
        int height) {


    if    (previewing){
              camera.stopPreview();
              previewing = false;
          }

    if    (camera != null){

    try { camera.setPreviewDisplay(surfaceHolder);
          camera.startPreview();
          previewing = true;
          } 

    catch (IOException e) {
            toast.showToastDialog(getApplicationContext(), e.toString());   
          }
      }
  }




@Override
public void surfaceCreated(SurfaceHolder holder) {

    camera = Camera.open(); 
    //camera = Camera.open(0);  

    }




@Override
public void surfaceDestroyed(SurfaceHolder holder) {

    camera.stopPreview();
    camera.release();
    camera = null;
    previewing = false;
}
 }

Upvotes: 1

Views: 6959

Answers (2)

whizzle
whizzle

Reputation: 2063

You just need to use the MediaStore.ACTION_IMAGE_CAPTURE intent action. That will launch the camera. And in your onActivityResult you can get a the image that was just taken. Now you can crop it and send it and whatever else you'd like. Below is an example.

Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File pics = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File cameraPhotoFile = new File(pics, System.currentTimeMillis()+".jpg");
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(cameraPhotoFile));
startActivityForResult(cameraIntent, REQUEST_CODE_CAMERA);


@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode != Activity.RESULT_OK) return;
    if (requestCode == REQUEST_CODE_CAMERA) {
        MediaScannerConnection.scanFile(this,
                new String[]{cameraPhotoFile.getAbsolutePath()}, null, null);

// do something with the image located at cameraPhotoFile

I've included the MediaScannerConnection because the image will not show up in the gallery until it gets scanned. You can remove that if you want, but I like images that were taken to show up. The bitmap is now located in the "cameraPhotoFile." Use that file however you like.

Also, here are the docs from Google about this called Taking Photos Simply. It's pretty straight forward

Upvotes: 1

Rene M.
Rene M.

Reputation: 2690

The easiest solution i can think of is:

  1. Call the ACTION_IMAGE_CAPTURE Intent to take a picture with the Stock Camera
  2. onActivityResult you will get the content uri of the new picture over data.getData()
  3. Do it like vogella here http://blog.vogella.com/2011/09/13/android-how-to-get-an-image-via-an-intent/ and directly open an inputstream to the new picture

no need for the pick intent.

Upvotes: 0

Related Questions