AggieDev
AggieDev

Reputation: 5045

Save bitmap to Android storage without losing quality

Right now I have an Intent that opens the phone's camera app, allows the user to take a picture, then goes back to my app with the new image. With this, it returns a bitmap. In order to get the Uri of the picture so that I can set the ImageView to it, I believe I have to save it to storage first. The only problem is when my app opens it up, the image is of very bad quality. At the part where I have to compress, I am keeping the quality at 100 so I am not sure what it is I am doing wrong.

Here is how I am starting the camera Intent:

Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
    startActivityForResult(takePictureIntent, TAKE_PICTURE_INTENT_CODE);
}

And here is how I am handling it:

//get result of image choosing
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
    super.onActivityResult(requestCode, resultCode, data);

    switch(requestCode) {

        case TAKE_PICTURE_INTENT_CODE:
            if(resultCode == RESULT_OK){
                Bundle extras = data.getExtras();
                Bitmap imageBitmap = (Bitmap) extras.get("data");
                try {
                    switchToCropFrag(createImageFileFromCamera(imageBitmap));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }else if (resultCode != RESULT_CANCELED){
                Toast.makeText(this, "Failed to get image, please try again.", Toast.LENGTH_LONG).show();
            } else {    //user cancelled image picking
        }
    }
}

private Uri createImageFileFromCamera(Bitmap imageBitmap) throws IOException {
        ContextWrapper cw = new ContextWrapper(getApplicationContext());
        File directory = cw.getDir("temp", Context.MODE_PRIVATE);
        // Create imageDir
        File path = new File(directory, "temp.png");

        FileOutputStream fos = null;
        try {

            fos = new FileOutputStream(path);

            // Use the compress method on the BitMap object to write image to the OutputStream
            imageBitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
            fos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return Uri.fromFile(path);
    }

For switchToCropFrag, it simply sets the image using Picasso. The image quality is fine when I have the user instead choose a photo from their phone that's already in their Gallery.

Upvotes: 0

Views: 2417

Answers (1)

CommonsWare
CommonsWare

Reputation: 1006924

With this, it returns a bitmap

It returns a thumbnail. Quoting the documentation:

If the EXTRA_OUTPUT is not present, then a small sized image is returned as a Bitmap object in the extra field

You seem to think that it is returning a regular-sized image, and it is not.

In order to get the Uri of the picture so that I can set the ImageView to it, I believe I have to save it to storage first.

If this is your ImageView in your activity, you do not need a Uri. Call setImageBitmap().

Upvotes: 2

Related Questions