I want to rotate and save my Captured Image using Android Native Camera to sdcard. As native cameras is in landscape by default. But the I don't want to use bitmap. Is it possible to do so ? please help. I am new to android development.
As my image is rotated by 90 degrees I need to rotate it using Bitmap before saving.
But on some devices bmp is coming null.
Camera Activity Layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<FrameLayout
android:id="#+id/camera_preview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</RelativeLayout>
ManifestFile
<activity
android:name="com.example.androiddms.CameraActivity"
android:configChanges="keyboardHidden|orientation"
android:label="#string/title_activity_camera"
android:screenOrientation="landscape"
android:theme="#android:style/Theme.NoTitleBar.Fullscreen" >
</activity>
Camera Activity.java
FileOutputStream fos = new FileOutputStream(pictureFile);
Bitmap bmp = BitmapFactory.decodeByteArray(data, 0, data.length);
Matrix matrix = new Matrix();
matrix.postRotate(90);
bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);
bmp.compress(Bitmap.CompressFormat.JPEG, 100,fos);
You should call onActivityResult after taking picture from camera and show your captured picture on ImageView. Bitmap takes memory but you should handle it. Follow the following steps below hopefully solve your Problem
STEP 1: open camera Intent and capture image from it:
private static final int REQUEST_CAMERA = 0;
Bitmap bmp;
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, REQUEST_CAMERA);
STEP 2: override onActivityResult Method
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == RESULT_OK)
{
if(requestCode == REQUEST_CAMERA)
{
Uri uri = (Uri) data.getData();
try
{
bmp = decodeUri(uri);
your_image_view.setImageBitmap(bmp);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
}
}
}
STEP 3: copy below method and paste it in your Activity
private Bitmap decodeUri(Uri selectedImage) throws FileNotFoundException
{
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(
getContentResolver().openInputStream(selectedImage), null, o);
final int REQUIRED_SIZE = 70;
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 1;
while (true)
{
if (width_tmp / 2 < REQUIRED_SIZE || height_tmp / 2 < REQUIRED_SIZE)
{
break;
}
width_tmp /= 2;
height_tmp /= 2;
scale *= 2;
}
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
return BitmapFactory.decodeStream(
getContentResolver().openInputStream(selectedImage), null, o2);
}
and you are done after following these steps you will be able to capture image from camera and set it to your imageview without having memory error. Hope this will help you.
Related
I am trying to create an app that lets users click a button and select an image.
I used the second answer from this question to prompt the user for an image: How to pick an image from gallery (SD Card) for my app?
But sometimes if I choose an image that appears to be oriented correctly in the gallery, when I display it it will have a wrong orientation (I read that this usually happens with pictures taken by camera because they save their rotation in their ExifInterface)
So this code runs when the user chooses an image:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) {
super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
switch(requestCode) {
case SELECT_PHOTO:
if(resultCode == RESULT_OK){
Uri si = imageReturnedIntent.getData();
InputStream imageStream = null;
try {
imageStream = getContentResolver().openInputStream(si);
Bitmap image = Utils.decodeUri(this, si);
addPerson(selectedName, selectedDate, image);
imageStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
addPerson() adds the person to the list and calls saveData() which is here:
try {
FileOutputStream out = new FileOutputStream(new File(folder, person.getName() + ".png"));
person.getImage().compress(Bitmap.CompressFormat.PNG, 100, out);
} catch (IOException e) {
e.printStackTrace();
};
And on onCreate() I run this code to load the items:
Bitmap notRotated = BitmapFactory.decodeFile(file.getPath());
Matrix matrix = new Matrix();
ExifInterface exif = new ExifInterface(file.getPath());
int rotation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
int rotationInDegrees = Utils.exifToDegrees(rotation);
if(rotation != 0f)
matrix.preRotate(rotationInDegrees);
image = Bitmap.createBitmap(notRotated, 0, 0, notRotated.getWidth(), notRotated.getHeight(), matrix, true);
notRotated.recycle();
But when I run the above code it just ends up with black images and when I debug it says rotation is always 0 although there are obviously images with different rotation.
How can I fix this problem?
EDIT:
Here's my code to downsample my bitmaps to prevent OutOfMemoryExceptions:
public static Bitmap decodeUri(Context context, Uri selectedImage) throws FileNotFoundException {
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(context.getContentResolver().openInputStream(selectedImage), null, o);
// The new size we want to scale to
final int REQUIRED_SIZE = 140;
// Find the correct scale value. It should be the power of 2.
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 1;
while (true) {
if (width_tmp / 2 < REQUIRED_SIZE
|| height_tmp / 2 < REQUIRED_SIZE) {
break;
}
width_tmp /= 2;
height_tmp /= 2;
scale *= 2;
}
// Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
return BitmapFactory.decodeStream(context.getContentResolver().openInputStream(selectedImage), null, o2);
}
Could me downsampling affect the rotation?
Okay so thanks to #CommonsWare for the help. Some errors in my code that he pointed out were saving the bitmaps in PNG format, not rotating them before saving and using ExifInterface in a wrong way. I changed the saving format to JPEG and used this example of an ExifInterface use (with a custom ExifInterface).
I've seen several questions regarding this topic, but none that address my problem.
I dynamically create ImageViews and allow the user to take/add photos of items for an inventory. The following code exists to generate the Bitmap and populate the ImageView:
protected void addPhotosToView(ArrayList<String> uris) {
for (String uriString : uris) {
try {
Uri uri = Uri.parse(uriString);
File imageFile = new File(uri.getPath());
int orientation = resolveBitmapOrientation(imageFile);
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);
bitmap = applyOrientation(bitmap, orientation);
ImageView image = new ImageView(ItemActivity.this);
int h = 100; // height in pixels
int w = 100; // width in pixels
Bitmap scaled = Bitmap.createScaledBitmap(bitmap, h, w, true);
image.setImageBitmap(scaled);
LinearLayout photoLayout = (LinearLayout) findViewById(R.id.itemPhotoLayout);
photoLayout.addView(image);
addClickListener(image, uri);
} catch (Exception e) {
e.printStackTrace();
}
}
}
But once the image is added or taken, some images appear with the wrong orientation. Some of the photos stored in the phone in portrait are displayed in portrait, while others appear to be in landscape. Landscape photos are equally arbitrary.
This does not appear to be happening on all devices (the device that I'm seeing this on is a Samsung S4)
As you can see in the code, I have tried getting/applying orientation changes using Exif tags, but I'm always getting 0 for the orientation with this device and have not seen any answers for questions that ask for a solution when orientation is always 0.
I'm looking to ship this software soon and need some sort of workaround or solution, so I'm willing to accept some other way of going from Uris/strings to a dynamic, horizontally scrollable list of properly oriented images if this can't be resolved any other way.
you need to decode the bitmap that's all try this tutorial you can download the source.
that application dose exactly what you want maybe it will help you i hope because it worked fine with my application
Please use this method to show/decode your bitmap. It is taken from another SO post I cant remember which and is modified for my use. This method returns bitmap according to the exif orientation data if present on the image:
public Bitmap decodeFile(String path) {// you can provide file path here
int orientation;
try {
if (path == null) {
return null;
}
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
// Find the correct scale value. It should be the power of 2.
final int REQUIRED_SIZE = 70;
// final int REQUIRED_SIZE = 20;
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 0;
while (true) {
if (width_tmp / 2 < REQUIRED_SIZE
|| height_tmp / 2 < REQUIRED_SIZE)
break;
width_tmp /= 2;
height_tmp /= 2;
scale++;
}
// decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
Bitmap bm = BitmapFactory.decodeFile(path, o2);
Bitmap bitmap = bm;
ExifInterface exif = new ExifInterface(path);
orientation = exif
.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
Matrix m = new Matrix();
if ((orientation == ExifInterface.ORIENTATION_ROTATE_180)) {
m.postRotate(180);
bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),
bm.getHeight(), m, true);
photo(bitmap, path);
return bitmap;
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
m.postRotate(90);
bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),
bm.getHeight(), m, true);
photo(bitmap, path);
return bitmap;
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
m.postRotate(270);
bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),
bm.getHeight(), m, true);
photo(bitmap, path);
return bitmap;
}
return bitmap;
} catch (Exception e) {
return null;
}
}
In my android application when I capture image from camera, I want to re-size it's dimensions. I am successful to re-size, when I take image from gallery. But when I capture from camera, I failed. Please help
if (requestCode == take_image && resultCode == RESULT_OK && null != data) {
thumbnail = (Bitmap) data.getExtras().get("data");
image2 = me1;
addattachmentsToListView(image2);
}
Here is the code to resize image from sdcard:
if (requestCode == UploadFile && resultCode == RESULT_OK && null != data) {
Uri selectedImage = data.getData();
try {
Bitmap image=(decodeUri(selectedImage));
addattachmentsToListView(image);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private Bitmap decodeUri(Uri selectedImage) throws FileNotFoundException {
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(
getContentResolver().openInputStream(selectedImage), null, o);
final int REQUIRED_SIZE = 200;
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 1;
while (true) {
if (width_tmp / 1.5 < REQUIRED_SIZE || height_tmp / 1.5 < REQUIRED_SIZE) {
break;
}
width_tmp /= 4;
height_tmp /= 4;
// width_tmp = 20;
// height_tmp = 20;
scale *= 2;
}
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
return BitmapFactory.decodeStream(
getContentResolver().openInputStream(selectedImage), null, o2);
}
In your public void onPreviewFrame(byte[] data, Camera camera), you could get a bitmap in this way:
Bitmap bmp = YUVtoBMP(data, ImageFormat.NV21, YOUR_CAMERA_SIZE);
public Bitmap YUVtoBMP(byte[] data, int format, Camera.Size size)
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
YuvImage yuvImage = new YuvImage(data, format, size.width, size.height, null);
yuvImage.compressToJpeg(new Rect(0, 0, size.width, size.height), 50, out);
byte[] imageBytes = out.toByteArray();
Options options = new Options();
options.inPreferQualityOverSpeed = false;
Bitmap image = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length, options);
return image;
}
In order to scale a bitmap, you can:
Bitmap scaled = Bitmap.createScaledBitmap(bmp, NEW_WIDTH, NEW_HEIGHT, true);
This is just a hint: start from this and try to look for optimization if any.
Photo is rotating 90 degree while capturing from camera in samsung mobile rest of other mobiles its working fine. Please help me for this.
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, IMAGE_CAPTURE);
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
try
{
if (requestCode == IMAGE_CAPTURE) {
if (resultCode == RESULT_OK){
Uri contentUri = data.getData();
if(contentUri!=null)
{
String[] proj = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
imageUri = Uri.parse(cursor.getString(column_index));
}
tempBitmap = (Bitmap) data.getExtras().get("data");
mainImageView.setImageBitmap(tempBitmap);
isCaptureFromCamera = true;
}
}
This happens to be a bug in earlier versions of Android.
I solved this issue just getting the orientation angle and rotate the bitmap accordingly.
public Bitmap decodeFile(String path) {//you can provide file path here
int orientation;
try {
if (path == null) {
return null;
}
// decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
// Find the correct scale value. It should be the power of 2.
final int REQUIRED_SIZE = 70;
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 0;
while (true) {
if (width_tmp / 2 < REQUIRED_SIZE
|| height_tmp / 2 < REQUIRED_SIZE)
break;
width_tmp /= 2;
height_tmp /= 2;
scale++;
}
// decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
Bitmap bm = BitmapFactory.decodeFile(path, o2);
Bitmap bitmap = bm;
ExifInterface exif = new ExifInterface(path);
orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
Log.e("ExifInteface .........", "rotation ="+orientation);
//exif.setAttribute(ExifInterface.ORIENTATION_ROTATE_90, 90);
Log.e("orientation", "" + orientation);
Matrix m = new Matrix();
if ((orientation == ExifInterface.ORIENTATION_ROTATE_180)) {
m.postRotate(180);
//m.postScale((float) bm.getWidth(), (float) bm.getHeight());
// if(m.preRotate(90)){
Log.e("in orientation", "" + orientation);
bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),bm.getHeight(), m, true);
return bitmap;
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
m.postRotate(90);
Log.e("in orientation", "" + orientation);
bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),bm.getHeight(), m, true);
return bitmap;
}
else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
m.postRotate(270);
Log.e("in orientation", "" + orientation);
bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),bm.getHeight(), m, true);
return bitmap;
}
return bitmap;
} catch (Exception e) {
return null;
}
}
Also query the MediaStore.Images.Media.ORIENTATION value to get the rotation angle. Then you can rotate the image by yourself or whatever.
What I am doing :
first check the orientation of image taken by camera using its meta data information , and If we found this in portrait then we have to rotate the image by 90 and display otherwise only display.
For getting the Information about orientation of image we can use ExifInterface.
That's It!
I am trying to take an image of specified dimensions and saving it in a desired location on the SD card. I am using intent.putExtra to take the image via the default camera application.
Here goes the code
public void onClick(View v) {
//Setting up the URI for the desired location
imageFile = "bmp"+v.getId()+".png";
File f = new File (folder,imageFile);
imageUri = Uri.fromFile(f);
//Setting the desired size parameters
private Camera mCamera;
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(width, height);
mCamera.setParameters(parameters);
//Passing intent.PutExtras to defaul camera activity
Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
i.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(i,CAMERA_PIC_REQUEST);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == RESULT_OK){
return;
}
The camera activiy force closes after taking an image.
Is it possible to modify the size of the images taken by the default camera activity in this way??
Or A separate camera application is necessary??
If your image is saved as a file, create a bitmap from that file and decrease its size using this method and pass this bitmap to your Activity:
public static Bitmap decodeFile(File file, int requiredSize) {
try {
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(file), null, o);
// The new size we want to scale to
// Find the correct scale value. It should be the power of 2.
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 1;
while (true) {
if (width_tmp / 2 < requiredSize
|| height_tmp / 2 < requiredSize)
break;
width_tmp /= 2;
height_tmp /= 2;
scale *= 2;
}
// Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
return BitmapFactory.decodeStream(new FileInputStream(file), null,
o2);
} catch (FileNotFoundException e) {
}
return null;
}