ExifInterface doesn't show rotation of cam captured image - android

I capture image from my cam and create bitmap and pass the path to ExifInterface to determine the rotation, since the cam captured image is rotated 90 degrees all the time. But this below code always shows value 0 which corresponds to ORIENTATION_UNDEFINED rotation type.
It is any other way to determine rotation or I am doing something wrong here ?
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File photoFile = null;
try {
photoFile = Utils.createImageFile(getContext());
String authorities = context.getPackageName() + ".fileprovider";
uriForFile = FileProvider.getUriForFile(context, authorities, photoFile);
} catch (IOException e) {
e.printStackTrace();
}
Log.d(TAG, "handleCaptureImage: " + uriForFile);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uriForFile);
startActivityForResult(intent, CAPTURE_IMAGE);
if (requestCode == CAPTURE_IMAGE) {
Bitmap bitmap = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(), uriForFile);
saveBitmap(bitmap);
}
public static File saveBitmap(Bitmap bitmap) {
File file = null;
String imageFileName = "JPEG_" + new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()) + ".jpg";
String path = App.getAppContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES).getAbsolutePath() + imageFileName;
if (bitmap != null) {
file = new File(path);
try {
FileOutputStream outputStream = null;
try {
outputStream = new FileOutputStream(path);
//this bitmap is rotated when I observe in debug mode.
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
ExifInterface exifInterface = new ExifInterface(path);
//still always returns 0 I expect 6 which is for 90 degrees
Log.d(TAG, "saveBitmap: "+exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL));
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (outputStream != null) {
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
return file;
}

I capture image from my cam
I am going to guess that this is from ACTION_IMAGE_CAPTURE, given that your code references a requestCode.
In that case, what you have:
Reads in the image from a file
Saves the image again to another file, wiping out the EXIF headers along the way
You don't need any of that.
You know where the image is, as you (presumably) supplied a location via EXTRA_OUTPUT in your ACTION_IMAGE_CAPTURE request. So, use ExifInterface to read from that location. Get rid of the bitmap stuff, in particular writing the bitmap back out. A JPEG file may have EXIF headers. A Bitmap does not, and a JPEG file created from a Bitmap does not (unless you add them yourself).

Related

Hide camera images from user gallery

Hi I am trying to make the images captured from my app inaccessible to the user. First I tried to save these images to internal storage which didnt work. Then I tried to hide them using "." infront of the folder name.I am not sure what the correct way to do this is. I also tried creating a file called .nomedia to bypass media scanner. I am very confused about the proper way to do this. Here's my code:
public String getImageUri(Context inContext, Bitmap inImage) {
/* *//* ByteArrayOutputStream bytes = new ByteArrayOutputStream();
inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), inImage, ".title", null);
return Uri.parse(path);*//*
*/
File file = new File(Environment.getExternalStorageDirectory()
+ File.separator + "/.myFolder");
file.mkdirs();
File mFile = new File(Environment.getExternalStorageDirectory()
+ File.separator + "/.nomedia");
mFile.mkdirs();
FileOutputStream fOut = null;
try {
fOut = new FileOutputStream(file);
inImage.compress(Bitmap.CompressFormat.JPEG, 85, fOut);
fOut.flush();
fOut.close();
uri = MediaStore.Images.Media.insertImage(getContentResolver(), file.getAbsolutePath(), file.getName(), file.getName());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return uri;
}
If I use file.mkdirs() I get filenotfoundexception. If i remove that line I get no errors but my uri is empty.
Does the above function return the file path as well? I need the file path and the uri later on. Any help is appreciated.
I guess you don't have to add another extension or something else just save them in external cache dir of your app and gallery app won't able to read your private directory until unless you notify about them.
so store your camera images here and no gallery app can detect it.
context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
sample code
public static File createPictureFile(Context context) throws IOException {
Locale locale = Locale.getDefault();
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", locale).format(new Date());
String fileName = "JPEG_" + timeStamp + "_";
// Store in normal camera directory
File storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
return File.createTempFile(fileName, ".jpg", storageDir);
}
Save your image to internal storage instead. Other applications like MediaScanner or Gallery do not have permission to read from your own application memory. Sample code:
private String saveToInternalStorage(Bitmap bitmapImage){
ContextWrapper cw = new ContextWrapper(getApplicationContext());
// path to /data/data/yourapp/app_data/imageDir
File directory = cw.getDir("imageDir", Context.MODE_PRIVATE);
// Create imageDir
File mypath=new File(directory,"profile.jpg");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(mypath);
// Use the compress method on the BitMap object to write image to the OutputStream
bitmapImage.compress(Bitmap.CompressFormat.PNG, 100, fos);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return directory.getAbsolutePath();
}
Save the image with different extension.
For example: .jpg can be saved as .ttj.
Try this code. Set where you want to save the photo. Once you receive response on onActivityResult(), in the desired URI, you will get the photo.
public void captureImageFromCamera() {
fileUri = FileUtils.getInstance().getOutputMediaFile(null);
if(fileUri == null){
Utilities.displayToastMessage(ApplicationNekt.getContext(),
context.getString(R.string.unable_to_access_image));
return;
}
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
startActivityForResult(intent, TAKE_PICTURE);
}
Following function will give you desired path. Change it based on your project need.
public Uri getOutputMediaFile(String imageNameWithExtension) {
if (imageNameWithExtension == null)
imageNameWithExtension = "image_" + System.currentTimeMillis() + ".jpg";
String extPicDir = getExtDirPicturesPath();
if (!Utilities.isNullOrEmpty(extPicDir)) {
File mediaFile = new File(extPicDir, imageNameWithExtension);
return Uri.fromFile(mediaFile);
} else {
Log.d("tag", "getOutputMediaFile." +
"Empty external path received.");
return null;
}
}
public String getExtDirPicturesPath() {
File file = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
if (file != null)
return file.getPath();
else
Log.d("", "getExtDirPicturesPath failed. Storage state: "
+ Environment.getExternalStorageState());
return null;
}
To get the resultant photo.
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != Activity.RESULT_OK)
return;
switch (requestCode) {
case TAKE_PICTURE:
//fileuri variable has the path to your image.
break;
}

take and save picture with specified size (in KB-s)

in my app I take a picture and save it in specified way. My phone is Nexus 4 and the camera is very strong and every picture is about 2.31MB how can I save picture for example in 60KB?
Can I do it with code? and how?
File newdir = new File(dir);
if(!newdir.exists()){
newdir.mkdirs();
}
picturesCount++;
String file = dir+picturesCount+".jpg";
imagePath = file;
File newfile = new File(file);
try {
newfile.createNewFile();
} catch (IOException e) {}
Uri outputFileUri = Uri.fromFile(newfile);
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(cameraIntent, TAKE_PHOTO_CODE);
When you are using camera and picture is taken, you can perform the task in the method below to reduce the quality of the image and type like JPEG or PNG (PNG takes more space than JPEG) so just play with the value (60 current out of 100) and see the difference in size.
#Override
public void onPictureTaken(byte[] data, Camera camera) {
InputStream in = new ByteArrayInputStream(data);
BitmapFactory.Options options = new BitmapFactory.Options();
Bitmap preview_bitmap = BitmapFactory.decodeStream(in, null, options);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
preview_bitmap.compress(Bitmap.CompressFormat.JPEG, 60, stream);
byte[] byteArray = stream.toByteArray();
FileOutputStream outStream = null;
try {
outStream = new FileOutputStream(new File(
Environment.getExternalStorageDirectory(), "Image1.jpg"));
outStream.write(byteArray);
outStream.close();
} catch (FileNotFoundException e) {
Log.d("CAMERA", e.getMessage());
} catch (IOException e) {
Log.d("CAMERA", e.getMessage());
}
}

Picture taken on portrait mode is saved rotated counter clockwise?

I'm building a camera app, I'm requesting the camera instance this way and the preview is shown in the right angle:
c = Camera.open();
c.setDisplayOrientation(90);
However after the user takes a photo and loading it into an imageView it's rotated 90 degrees counter clockwise. This is how I save the photo:
#Override
public void onPictureTaken(byte[] data, Camera camera) {
try {
String filePath = folderPath + generateFileName();
FileOutputStream outStream = new FileOutputStream( filePath );
outStream.write(data);
outStream.close();
// Put into imageView
File file = new File(filePath);
if(file.exists()){
Bitmap myBitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
last_photo.setImageBitmap(myBitmap);
}
} catch (FileNotFoundException e) {
} catch (IOException e) {
} finally {
}
}
How can I save the image without it being rotated?
I think you want to use setRotation() instead, or in addition to, setDisplayOrientation(). That method is described here

Saving picture to app directory returns null in onActivityResult

I am saving an image to the application directory by using the following with my intent (Got it from the android dev site):
private File createImageFile() throws IOException {
String timeStamp = new SimpleDateFormat("yyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = getActivity().getApplicationContext().getFilesDir();
File image = File.createTempFile(imageFileName, ".jpg", storageDir);
return image;
}
And then in the onClick:
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException e) {
Toast.makeText(getActivity().getApplicationContext(), "File not created", Toast.LENGTH_LONG).show();
}
if (photoFile != null){
Intent camIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
camIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
getActivity().startActivityForResult(camIntent, 0);
}
Up to here it works perfectly fine. I checked in the app dir using my file manager and the pictures get saved and they cannot be seen by other apps, as it should be. The problem is that when I try to display it in my ImageView I get a NullPointerException. This is the problem code:
private void setCameraPicture(int picture_count, Intent data) {
// TODO Auto-generated method stub
Bitmap bm = null;
try {
Uri selectedImage = data.getData();
Toast.makeText(getApplicationContext(), "picture = " + selectedImage, Toast.LENGTH_LONG).show();
String camPictureString = getRealPathFromURI(selectedImage);
File f = new File(camPictureString);
ExifInterface ei = new ExifInterface(camPictureString);
int rotation = 0;
int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
rotation = 90;
bm = rotateCameraImage(rotation, f);
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) {
rotation = 180;
bm = rotateCameraImage(rotation, f);
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
rotation = 270;
bm = rotateCameraImage(rotation, f);
} else {
bm = rotateCameraImage(rotation, f);
}
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), "IOException", Toast.LENGTH_LONG).show();
} catch (NullPointerException e) {
// TODO: handle exception
Toast.makeText(getApplicationContext(), "NullPointerException", Toast.LENGTH_LONG).show();
}
}
The line Uri selectedImage = data.getData(); returns null. Am I doing this wrong? I call the setCameraPicture() from my onActivityResult() and pass the Intent data in as a parameter.
This code works fine if I don't save to the application directory. Do any of you have any suggestions? Any help will be appreciated. Thank you in advance
getData() returns null because you've specified a custom file to save the Image in (Media.EXTRA_OUTPUT). The data is stored in the path that you've specified, and not returned in your onActivityResult(). This makes sense because there is no reason to return it if the data is already stored somewhere. Just simply retrieve the Bitmap image from the path.

Android camera integration-preview and file storage resulting errors

I am trying to integrate camera access to my android application.My requirements are making a preview of the photo taken and store the same on the SD card.But making a preview and storing on the sd card are working fine separately.But when i integrate both into a single application it doesnt work.And i am using the standard code given in the developer site for my storage on SD card.
here is my code
public void pickImage(View View) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE); // create a file to save the image
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); // set the image file name
startActivityForResult(intent, REQUEST_CODE);
}
private static Uri getOutputMediaFileUri(int type){
return Uri.fromFile(getOutputMediaFile(type));
}
private static File getOutputMediaFile(int type){
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this.
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "Sparikko");
// This location works best if you want the created images to be shared
// between applications and persist after your app has been uninstalled.
// Create the storage directory if it does not exist
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
Log.d("Sparikko", "failed to create directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE){
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_"+ timeStamp + ".jpg");
} else {
return null;
}
return mediaFile;
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK)
try {
// We need to recyle unused bitmaps
if (bitmap != null) {
bitmap.recycle();
}
InputStream stream = getContentResolver().openInputStream(data.getData());
bitmap = BitmapFactory.decodeStream(stream);
stream.close();
imageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
super.onActivityResult(requestCode, resultCode, data);
}
I am getting a application is stopped unexpectedly error.And i used logcat to find where i could find the program control where the error happens.And i found that the error happens in InputStream stream = getContentResolver().openInputStream(data.getData()); line in the onActivityResult() function.Both funcationality works fine seperately bt giving error when combined.
after taking picture from camera you need to downscale bitmap to set on ImageView to show preview. refer below method:
private void showAttachedImagePreview(String imagePath)
{
Bitmap bitmap = null;
//= BitmapFactory.decodeFile(imagePath);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 1;
try
{
bitmap = BitmapFactory.decodeFile(imagePath, options);
}
catch (OutOfMemoryError e)
{
e.printStackTrace();
bitmap=null;
try
{
options.inSampleSize = 2;
bitmap = BitmapFactory.decodeFile(imagePath, options);
}
catch (OutOfMemoryError e1)
{
e1.printStackTrace();
bitmap=null;
try
{
options.inSampleSize = 3;
bitmap = BitmapFactory.decodeFile(imagePath, options);
}
catch (OutOfMemoryError e2)
{
e2.printStackTrace();
bitmap=null;
try
{
options.inSampleSize = 4;
bitmap = BitmapFactory.decodeFile(imagePath, options);
}
catch (OutOfMemoryError e3)
{
e3.printStackTrace();
bitmap=null;
}
}
}
}
if(bitmap!=null)
{
commentAttachedImagePreview.setVisibility(ImageView.VISIBLE);
commentAttachedImagePreview.setImageBitmap(bitmap);
commentAttachedImageName.setVisibility(TextView.VISIBLE);
commentAttachedImageName.setText(new File(imagePath).getName());
deleteAttachedImage.setVisibility(ImageView.VISIBLE);
}
try
{
File file = new File(AppManager.getInstance().DATA_DIRECTORY, "tausif_tmp.png");
FileOutputStream outStream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 50, outStream);
outStream.flush();
outStream.close();
filePath = file.getPath();
}
catch(Exception ex)
{
ex.printStackTrace();
}
}

Categories

Resources