Camera Image Orientation

Why does an image captured using camera intent gets rotated on some devices on Android?

Most phone cameras are landscape, meaning if you take the photo in portrait, the resulting photos will be rotated 90 degrees. In this case, the camera software should populate the Exif data with the orientation that the photo should be viewed in.

Note that the below solution depends on the camera software/device manufacturer populating the Exif data, so it will work in most cases, but it is not a 100% reliable solution.

ExifInterface ei = new ExifInterface(photoPath);
int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_UNDEFINED);

Bitmap rotatedBitmap = null;
switch(orientation) {

case ExifInterface.ORIENTATION_ROTATE_90:
rotatedBitmap = rotateImage(bitmap, 90);
break;

case ExifInterface.ORIENTATION_ROTATE_180:
rotatedBitmap = rotateImage(bitmap, 180);
break;

case ExifInterface.ORIENTATION_ROTATE_270:
rotatedBitmap = rotateImage(bitmap, 270);
break;

case ExifInterface.ORIENTATION_NORMAL:
default:
rotatedBitmap = bitmap;
}

Here is the rotateImage method:

public static Bitmap rotateImage(Bitmap source, float angle) {
Matrix matrix = new Matrix();
matrix.postRotate(angle);
return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(),
matrix, true);
}

how to set camera Image orientation?

just include this code

public void rotateImage(String file) throws IOException{

BitmapFactory.Options bounds = new BitmapFactory.Options();
bounds.inJustDecodeBounds = true;
BitmapFactory.decodeFile(file, bounds);

BitmapFactory.Options opts = new BitmapFactory.Options();
Bitmap bm = BitmapFactory.decodeFile(file, opts);

int rotationAngle = getCameraPhotoOrientation(getActivity(), Uri.fromFile(file1), file1.toString());

Matrix matrix = new Matrix();
matrix.postRotate(rotationAngle, (float) bm.getWidth() / 2, (float) bm.getHeight() / 2);
Bitmap rotatedBitmap = Bitmap.createBitmap(bm, 0, 0, bounds.outWidth, bounds.outHeight, matrix, true);
FileOutputStream fos=new FileOutputStream(file);
rotatedBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
}

public static int getCameraPhotoOrientation(Context context, Uri imageUri, String imagePath){
int rotate = 0;
try {
context.getContentResolver().notifyChange(imageUri, null);
File imageFile = new File(imagePath);
ExifInterface exif = new ExifInterface(imageFile.getAbsolutePath());
int orientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_UNDEFINED);
switch (orientation) {
case ExifInterface.ORIENTATION_NORMAL:
rotate = 0;
case ExifInterface.ORIENTATION_ROTATE_270:
rotate = 270;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotate = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_90:
rotate = 90;
break;
}
} catch (Exception e) {
e.printStackTrace();
}
return rotate;
}

Camera2 control image orientation

Emulator is a very bad starting point to work with Camera2 API. Essentially, it has LEGACY Camera2 support, with some quirks.

This said, Jpeg orientation is a very delicate topic on Android camera. The official docs explain that rotation request may apply to the image itself, or to EXIF flag only, but some devices (which Huawai did you test?) don't comply at all.

Also note that BitmapFactory.decodeByteArray() ignores the EXIF flag, since the very beginning.

How to fix wrong rotation of photo from camera in flutter?

You can use package https://pub.dev/packages/flutter_exif_rotation

Support iOS and Android

In some devices the exif data shows picture in landscape mode when they're actually in portrait.

This plugin fixes the orientation for pictures taken with those devices.

For Android

Add this in your AndroidManifest.xml

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

code snippet

image = await FlutterExifRotation.rotateImage(path: image.path);

//Note : iOS not implemented
image = await FlutterExifRotation.rotateAndSaveImage(path: image.path);

Controlling the camera to take pictures in portrait doesn't rotate the final images

The problem is when I saved the image I didn't do well.

@Override
public void onPictureTaken(byte[] data, Camera camera) {

String timeStamp = new SimpleDateFormat( "yyyyMMdd_HHmmss").format( new Date( ));
output_file_name = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) + File.separator + timeStamp + ".jpeg";

File pictureFile = new File(output_file_name);
if (pictureFile.exists()) {
pictureFile.delete();
}

try {
FileOutputStream fos = new FileOutputStream(pictureFile);

Bitmap realImage = BitmapFactory.decodeByteArray(data, 0, data.length);

ExifInterface exif=new ExifInterface(pictureFile.toString());

Log.d("EXIF value", exif.getAttribute(ExifInterface.TAG_ORIENTATION));
if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("6")){
realImage= rotate(realImage, 90);
} else if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("8")){
realImage= rotate(realImage, 270);
} else if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("3")){
realImage= rotate(realImage, 180);
} else if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("0")){
realImage= rotate(realImage, 90);
}

boolean bo = realImage.compress(Bitmap.CompressFormat.JPEG, 100, fos);

fos.close();

((ImageView) findViewById(R.id.imageview)).setImageBitmap(realImage);

Log.d("Info", bo + "");

} catch (FileNotFoundException e) {
Log.d("Info", "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d("TAG", "Error accessing file: " + e.getMessage());
}
}

public static Bitmap rotate(Bitmap bitmap, int degree) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();

Matrix mtx = new Matrix();
// mtx.postRotate(degree);
mtx.setRotate(degree);

return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);
}

Image Orientation on Camera API

You can get rotation of captured bitmap using ExifInterface and create another bitmap with fixed rotation - here you can find example of usage.
Moreover, I recommend to use inBitmap option for reusing existing bitmap into created rotated one.

Camera1 and Camera2 APIs are kinda tricky ones.It is useful to know how they work inside but there are plenty of ready solutions. I can recommend the following ones:

  • https://camerakit.io - has fixes for rotation issues inside but
    currently in beta, supports Camera2 features.

  • https://github.com/RedApparat/Fotoapparat - based on Camera1.

  • https://github.com/natario1/CameraView - based on Camera1, can

    capture video.

Image Gets rotated captured from camera

You can't rotate your canvas after drawBitmap. You have to first rotate it and then use drawBitmap i.e

        float rotation=0;
try {
ExifInterface exifInterface=new ExifInterface(selectedPhoto);
int orientation=exifInterface.getAttributeInt(TAG_ORIENTATION, ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90: {
rotation=-90f;
break;
}
case ExifInterface.ORIENTATION_ROTATE_180: {
rotation=-180f;
break;
}
case ExifInterface.ORIENTATION_ROTATE_270: {
rotation=90f;
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
canvas.save();
canvas.rotate(rotation);

//canvas is rotated now use drawBitmap
canvas.drawBitmap(image, 0, 0, null);
canvas.restore();


Related Topics



Leave a reply



Submit