Callback to manipulate photo before it is saved to file - android

I'd like to take photo and compress its size before saving it to file.
According to what I understand from android developer guide, I can only save the photo to file first and then compress it.
File photoFile = //aquire file path to the saved photo...
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoFile));
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
...
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.i("addNewActivity","onActivityResult");
if (requestCode == REQUEST_TAKE_PHOTO && resultCode == RESULT_OK) {
Bitmap bm = BitmapFactory.decodeFile(photoFile.getAbsolutePath());
//...compress the photo and re-save it again to the file.
}
}
Is it the best practice for this flow? Can't I get in callback the byte[] of the image and manipulate it before it is being saved to file?

Related

Android Camera Photo Thumbnail Orientation

We have been using a bunch of code that uses the camera with the desired end result, but I want to get to the bottom of this with clean code. I'm simply following the Android docs here verbatim, and getting a rotated thumbnail. Below is the code, please find the working project in this branch of my Bitbucket repository.
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
Bundle extras = data.getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
ImageView view = (ImageView) findViewById(R.id.imageView);
view.setImageBitmap(imageBitmap);
}
}
I know that this is just the thumbnail. But it seems the thumbnail is completely useless, unless you get the full file and read the exif info from that.
I know that StackOverflow says "get the exif rotation from the full image file and rotate the actual bitmap before recompressing it into another jpg file". But isn't this a little too much unnecessary computation? What good is the thumbnail if it's useless by itself without getting the orientation from the full file?
Am I missing something?

Storing image after camera click in my app stores blur image

I am asking user to click image from my app and then that image gets stored in local storage and from there to the server ,but the problem is the image which is stored is blurred.
public void saveImage(Bitmap bitmap, int i)
{
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG,100, bytes);
File directory = new File(Environment.getExternalStorageDirectory()+"my_directory");
if(!directory.exists())
{
directory.mkdirs();
}
File f = new File(Environment.getExternalStorageDirectory()+"my_directory");
try{
f.createNewFile();
//write the bytes in file
FileOutputStream fo = new FileOutputStream(f);
fo.write(bytes.toByteArray());
fo.close();
}catch(IOException ioe){
ioe.printStackTrace();
}
}
This is the code i am using to save image and this is the OnActivityResult from where the bitmap is generated.
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 0)
{
if(data!=null)
{
Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
iv_upload.setImageBitmap(thumbnail);
saveImage(thumbnail,(int)System.currentTimeMillis());
}
}
}
Is there any reason for compressing the image as done in your code?
The Android Camera application encodes the photo in the return Intent delivered to onActivityResult() as a small Bitmap in the extras, under the key "data". The following code retrieves this image and displays it in an ImageView.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
Bundle extras = data.getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
mImageView.setImageBitmap(imageBitmap);
}
}
Have you made these changes in Manifest File, Please check
<manifest ...>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
...
</manifest>
You are compressiong your original image here:
bitmap.compress(Bitmap.CompressFormat.JPEG,100, bytes);
Quality Accepts 0 - 100
0 = MAX Compression (Least Quality which is suitable for Small images)
100 = Least Compression (MAX Quality which is suitable for Big images)
So try to change the value of 100 and check the quality.

What is the difference between these two ways of taking photos in Android?

I want to understand what is going on in these two scenarios. I am using code directly from the official docs at http://developer.android.com/training/camera/photobasics.html
Assume that all the necessary read/write permissions are present in the Manifest file.
Scenario 1:
static final int REQUEST_IMAGE_CAPTURE = 1;
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
Bundle extras = data.getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
mImageView.setImageBitmap(imageBitmap);
}
}
This code appears to work for me, but I don't know what it's doing exactly. It basically starts up the camera and lets me take a picture, and then in onActivityResult, I can get the thumbnail this way bu pulling it from the intent.
Scenario 2:
String mCurrentPhotoPath;
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = "file:" + image.getAbsolutePath();
return image;
}
static final int REQUEST_TAKE_PHOTO = 1;
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
...
}
// Continue only if the File was successfully created
if (photoFile != null) {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoFile));
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
Bundle extras = data.getExtras(); //data is null here!!!
Bitmap imageBitmap = (Bitmap) extras.get("data");
mImageView.setImageBitmap(imageBitmap);
}
}
This scenario, on the other hand, is supposed to let me get the full file, but it doesn't work and throws an error for me because the Intent variable is null, so I don't have access to anything.
My questions:
When you take a picture using the Android camera, does it typically create two files -- a thumbnail and a full file?
In scenario 1, these file(s) are not being written to internal or external storage, but just the RAM, right? The thumbnail is saved in the Intent, but does this imply that the full file is lost / unattainable?
In scenario 2, the Intent is null because I had used takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile)); for some reason. How do I know where this file is? Do I even really need mPhotoPath or should I be keeping access to File photoFile, which I've lost by the time I reach the onActivityResult method? What is the proper practice for keeping hold of this file? Making it a member variable?
The image creation function in this example uses getExternalStoragePublicDirectory -- is this different from saving in internal storage? I had assumed there were many ways to save a file: Internal storage, RAM, SD Card, storage device connected to the phone (such as an external HDD), the Cloud, etc. How do I know what is what?
It will either return a thumbnail in the Intent (if you don't specify a filename) or save the file to the filename you specified in the original Intent extras. I don't believe there is a way to do both. If you want to save the full image and then make a thumbnail, you'll have to create the thumbnail yourself. See here for details on the Intent: http://developer.android.com/reference/android/provider/MediaStore.html#ACTION_IMAGE_CAPTURE
The file is being saved to the photoFile Uri that you specified in the Intent here: takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
You should store the Uri somewhere, probably as a member variable, so you can access it later. That is the Uri that the image will be saved to if a picture is successfully taken.
This is going to be the Android user's default Photos folder in this case. getExternalStoragePublicDirectory will be on whatever media is used for shared data - probably an SD card or internal SD storage.

save the photos from camera to android internal storage

I successfully save the pictures from android camera
to using the following root paths
Environment.getExternalStorageDirectory()
and
context.getExternalFilesDir(null)
but I cannot save using the following root path
context.getFilesDir()
Do you know if it is possible to save the pictures taken from android camera to the android internal storage which have context.getFilesDir() as root folder?
I use the following code to start the camera:
Intent takePictureIntent = new
Intent(MediaStore.ACTION_IMAGE_CAPTURE);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(picFile));
startActivityForResult(takePictureIntent, REQUEST_TAKE_PICTURE);
//and this code I used to get the camera output
#Override
public void onActivityResult(int requestCode, int resultCode,
Intent data) {
if ((requestCode == REQUEST_TAKE_PICTURE) && (resultCode ==
Activity.RESULT_OK)
) {
Toast.makeText(this, "Can get the image.",
Toast.LENGTH_LONG).show();
//Bitmap photo = (Bitmap) data.getExtras().get("data");
// System.out.println("photo "+photo.getWidth());
// final ImageView imageView = (ImageView) findViewById(R.id.imageView1);
// imageView.setImageBitmap(photo);
} else if ((requestCode == REQUEST_TAKE_PICTURE) && (resultCode == Activity.RESULT_CANCELED)) {
Toast.makeText(this, "Cannot get the image.", Toast.LENGTH_LONG).show();
}
}
You cannot use getFilesDir(), because you are launching a third-party camera app to take the picture, and it cannot write to your app's internal storage.

Bitmap of size zero saved from Camera App on cancel

I was following the android tutorial as follows from this official link
I wish to save the full Image. The problem is when the user enters the camera app takes a photo but decides to cancel it, android still saves the image with size zero. Any way to avoid this?
The code is as follows
static final int REQUEST_TAKE_PHOTO = 1;
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
...
}
// Continue only if the File was successfully created
if (photoFile != null) {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoFile));
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
Ok solved it using the name of the newly created file. When we create name of file we simply save the path of the file in a String variable say "Current Path"
And add the following code-
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == Activity.RESULT_CANCELED && requestCode == 0)
{
File file = new File(currentPath);
boolean delete = file.delete();
Log.i("delete",String.valueOf(delete));
}
}
I think you are doing something wrong in your code. You should post your code to get the proper assistance.
as far as I understand . You should override the onbackpressed function. you should close/release camera here. In this case I think the camera would not take and save picture.

Categories

Resources