Captured image is rotated 90 degress - android

I've written an app to capture an image. The problem is that the image is rotated 90 degrees after the capture. I've setted the
camera.setDisplayOrientation(NINTY_DEGREES);
But this only affects the previewing of the SurfaceView. The real problem is that the bytes I get from the camera is flipped. Why does this happend? Is there a setting I can set to flip it before capture?
I my activity subcribes to an event, when the image is captured. This is how I register when the byte[] is filled:
camera.takePicture(null, null, new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
if (null != callback)
callback.onJpegPictureTaken(data, camera);
}
});
In my Activity
public class History extends BaseWindow implements OnClickListener, CaptureImageCallback
and the relevant method:
#Override
public void onJpegPictureTaken(byte[] data, Camera camera) {
Intent i = new Intent(this, ImageEditing.class);
i.putExtra("image", data);
startActivity(i);
}
You can see the parameter data which contains the image data, this byte array is rotated 90 degress. I could of course rotate the ImageView 90 degress, but since I will work with other systems, such as a homemade webservice, I would need to apply this hot fix to every external system. How can I correct this rotation?
Thanks!

You can get the "Angle" of your captured image and rotate as per angle.
ExifInterface exif = new ExifInterface(imagePath);
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,ExifInterface.ORIENTATION_NORMAL);
int angle = 0;
if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
angle = 90;
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) {
angle = 180;
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
angle = 270;
}
Log.d("Tag", "Angle: " + angle);
Matrix mat = new Matrix();
mat.postRotate(angle);
if (angle != 0)
Bitmap bitmap2 = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),bitmap.getHeight(), mat, true);

As name indicates setDisplayOrientation() is for display only. Doc says:
This does not affect the order of byte array passed in
onPreviewFrame(byte[], Camera), JPEG pictures, or recorded videos
So if you want to save rotated image, you need to rotate it yourself prior saving.

Related

Photo taken from iphone gets rotated 90 degrees on Android phone

Scenario :
The photo rotated 90 degrees when the picture was taken from the iPhone camera and uploaded on the server and trying to load the same photo on android device.
What I found so far is Meta information(EXIF data) is ignored by the Android system before downloading the image. When photo uploaded from iPhone, the EXIF information of that particular photo is something like this: orientation 6 Rotated 90 CCW, but when it comes to android this value becomes: orientation 0(UNDEFINED)
I tried a couple of approaches but did not work, let me know if anyone faced similar issue or any solution or work around for this, Thanks in advance.
Sample snippet code :
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inSampleSize = 4;
resultBitmap = decodeStream(inputStream, null, bmOptions);
ExifInterface exif = new ExifInterface(inputStream);
String orientString = exif.getAttribute(ExifInterface.TAG_ORIENTATION);
int orientation = orientString != null ? Integer.parseInt(orientString) : ExifInterface.ORIENTATION_NORMAL;
int rotationAngle = 0;
if (orientation == ExifInterface.ORIENTATION_ROTATE_90) rotationAngle = 90;
else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) rotationAngle = 180;
else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) rotationAngle = 270;
Matrix matrix = new Matrix();
matrix.setRotate(rotationAngle);
Bitmap rotated = Bitmap.createBitmap(resultBitmap,0,0,resultBitmap.getWidth(),resultBitmap.getHeight(),matrix,true);
if(rotated != null){
resultBitmap = rotated;
}
enter code here

How to know the orientation of picture taken by the Camera? [duplicate]

This question already has answers here:
How to detect when the device switch from portrait to landscape mode? [duplicate]
(4 answers)
Closed 4 years ago.
I am making an application in which I have to take a picture every one second in a service without launching the camera preview.
I wrote the following code in service and able to take picture.
if (cameraId < 0) {
Log.d(TAG, "No camera found");
}
else
{
camera = Camera.open(cameraId);
camera.startPreview();
}
camera.takePicture(null, null, bitmapHandler);
In the bitmapHandler class I get the capture image data in
#Override
public void onPictureTaken(byte[] data, Camera camera) {
.
.
.
}
when I take the picture in portrait mode, the resultant image is rotated by 90 degree clockwise.
when I take the picture in landscape mode, the resultant image is proper.
when I take the picture in reverse-landscape mode, the resultant image is rotated by 180 degree
when I take the picture in reverse-portrait mode, the resultant image is rotated by 270 degree
What i did to get proper image so that I can feed that image to my neural network.
What I tried : I am rotating the bitmap by 90 when image was taken in portrait mode, but still not able to find in which mode the image was captured.
Does the Camera API have any way to know or control the rotation angle ?
I was using the function fixImageOrientation, parameters are image itself and path to the image file (as second parameter, I was passing the path where camera activity stores temporary image file)
public static Bitmap rotateImage(Bitmap bmp, float angle)
{
Matrix matrix = new Matrix();
matrix.postRotate(angle);
System.out.println("Rotating image " + Float.toString(angle) + " degrees, rotateImage()");
return Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);
}
public static Bitmap fixImageOrientation(Bitmap bmp, String path)
{
ExifInterface ei;
boolean changed = true;
try {
ei = new ExifInterface(path);
int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED);
if (orientation == ExifInterface.ORIENTATION_ROTATE_90)
bmp = rotateImage(bmp, 90);
else if (orientation == ExifInterface.ORIENTATION_ROTATE_180)
bmp = rotateImage(bmp, 180);
else if (orientation == ExifInterface.ORIENTATION_ROTATE_270)
bmp = rotateImage(bmp, 270);
else
changed = false;
} catch (IOException e){
System.out.println("IOException, image probably has no exif data, fixImageOrientation()");
e.printStackTrace();
}
if (changed)
{
System.out.println("Image orientation fixed, fixImageOrientation()");
}
else
{
System.out.println("Image orientation did not change, fixImageOrientation()");
}
return bmp;
}

Camera API captured image saving in landscape automatically

I am using blow post to work with camera API, and flip camera to back/front.
Fliping the Front Camera to Back Camera in Button Click using android
In samsung device by default it open the camera preview in landscape but
camera.setDisplayOrientation(90);
by this code i am able to open camera preview in portrait. but while i am saving the image it is saving it in landscape Automatically.
by using this approch
Matrix matrix = new Matrix();
matrix.postRotate(90);
Bitmap bitmap = BitmapFactory.decodeFile(pictureFile.getAbsolutePath());
Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0,
bitmap.getWidth(), bitmap.getHeight(), matrix, true);
Bitmap scaledBitmap = Bitmap.createScaledBitmap(rotatedBitmap,
curntViewWidth, curntViewHeight, true);
processing speed is slow down. Do any one have any other way by which camera preview,capture and save image orientation will be same ..
Do we have any library to open camera and set image in specific size like this app
https://play.google.com/store/apps/details?id=com.tinypiece.android.mlc
From the docs of Camera.Parameters#setRotation():
If applications want to rotate the picture to match the orientation of
what users see, apps should use OrientationEventListener and
Camera.CameraInfo
public void onOrientationChanged(int orientation) {
if (orientation == ORIENTATION_UNKNOWN) return;
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
orientation = (orientation + 45) / 90 * 90;
int rotation = 0;
if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
rotation = (info.orientation - orientation + 360) % 360;
} else { // back-facing camera
rotation = (info.orientation + orientation) % 360;
}
mParameters.setRotation(rotation);
}
OrientationEventListeneris an abstract class that contains the onOrientationChanged(). This method will receive orientation changes from the system. This is one possible implementation:
OrientationEventListener listener = new OrientationEventListener(this,
SensorManager.SENSOR_DELAY_NORMAL) {
#Override
public void onOrientationChanged(int i) {
//Code from above goes here.
}
};
listener.enable();

Camera capture image not showing in Imageview in my portrait view for 7 inch tablet

I want to show image Capture through camera in image View in My 7 inch tablet 3.2. When i am capturing image and control returns to my activity image not displaying in Image View.
But same thing working properly on Smartphones.
I also tried with android:configChanges="keyboardHidden|orientation" in manifest for that activity but still problem exist.
If i am capturing Image by keeping tablet in landscape it working fine and displaying image.
I call Camera intent as below
I am running my app on 7 inch Samsung tablet GT-P6200 of version 3.2.
Camera Intent I called as below
Intent cameraIntent = new Intent();
cameraIntent.setAction(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, PICTURE_FROM_CAMERA);
Please help me out of this issue
My activity Result method
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == PICTURE_FROM_CAMERA) {
Bitmap bitmap = (Bitmap) data.getExtras().get("data");
photoView.setImageBitmap(bitmap);
}
}
}
Try rotating the device to Landscape as MediaStore capture only works in Landscape mode.
This is a Common issue in Some tab, for this issue you may try this following code. it works for me.
try {
File f = new File(SD_CARD_IMAGE_PATH);
ExifInterface exif = new ExifInterface(f.getPath());
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
int angle = 0;
if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
angle = 90;
}
else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) {
angle = 180;
}
else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
angle = 270;
}
Matrix mat = new Matrix();
mat.postRotate(angle);
Bitmap bmp = BitmapFactory.decodeStream(new FileInputStream(f), null, null);
Bitmap correctBmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), mat, true);
}
catch (IOException e) {
Log.w("TAG", "-- Error in setting image");
}
catch(OutOfMemoryError oom) {
Log.w("TAG", "-- OOM Error in setting image");
}
But should I use in else form?

Android get Orientation of a camera Bitmap? And rotate back -90 degrees

I have this code:
//choosed a picture
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == ImageHelper.SELECT_PICTURE) {
String picture = "";
Uri selectedImageUri = data.getData();
//OI FILE Manager
String filemanagerstring = selectedImageUri.getPath();
//MEDIA GALLERY
String selectedImagePath = ImageHelper.getPath(mycontext, selectedImageUri);
picture=(selectedImagePath!=null)?selectedImagePath:filemanagerstring;
...
This is only a picture chooser, from gallery. This is nice, but when I open this picture on an ImageView, the images when took on "PORTRAIT MODE" with the camera look nice, but the images that took "LANDSCAPE MODE" with the camera, opening in -90 degrees.
How can i rotate those pictures back?
Bitmap output = Bitmap.createBitmap(newwidth, newheight, Config.ARGB_8888);
Canvas canvas = new Canvas(output);
I tried this:
Log.e("w h", bitmap.getWidth()+" "+bitmap.getHeight());
if (bitmap.getWidth()<bitmap.getHeight()) canvas.rotate(-90);
But this is not working, all image size is: *2560 1920 pixel (PORTRAIT, and LANDSCAPE mode all)
What can I do to rotate back the LANDSCAPE pictures?
If a photo is taken with a digital camera or smartphone, rotation is often stored in the photo's Exif data, as part of the image file. You can read an image's Exif meta-data using the Android ExifInterface.
First, create the ExifInterface:
ExifInterface exif = new ExifInterface(uri.getPath());
Next, find the current rotation:
int rotation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
Convert exif rotation to degrees:
int rotationInDegrees = exifToDegrees(rotation);
where
private static int exifToDegrees(int exifOrientation) {
if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_90) { return 90; }
else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_180) { return 180; }
else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_270) { return 270; }
return 0;
}
Then use the image's actual rotation as a reference point to rotate the image using a Matrix.
Matrix matrix = new Matrix();
if (rotation != 0) {matrix.preRotate(rotationInDegrees);}
You create the new rotated image with the Bitmap.createBitmap method that take a Matrix as a parameter:
Bitmap.createBitmap(Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter)
where Matrix m holds the new rotation:
Bitmap adjustedBitmap = Bitmap.createBitmap(sourceBitmap, 0, 0, width, height, matrix, true);
See this tutorial for a useful source code example:
Read Exif information in a JPEG file.
if you are Using Jetpack CameraX, inside onImageCaptured method you can access rotation degree provided by EXIF data from the imageProxy like this:
image.imageInfo.rotationDegrees
then while setting your image you can rotate your image according to this degree
Last answer was technically perfect, but I tried hard to create a system to manage pictures, rotate, resize, cache and load into ImageViews and I can tell it is a hell. Even when all it was done it crashes sometimes cause OutOfMemory in some devices.
My point is do not reinvent the wheel, it has a perfect design. Google itself encourage you to use Glide. It works in one line, super easy to use, lightweight in size and functions number, it manage EXIF by default, and it use memory like a charm.. It is simply black magic coded ;)
I'm not sure if Picasso also manages EXIF, but there is a quick intro to both of them:
https://inthecheesefactory.com/blog/get-to-know-glide-recommended-by-google/en
My Advice: do not waste your time and use them. You can solve your problem in one line:
Glide.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);

Categories

Resources