37

According to the documentation, setRotation(90) should rotate the captured JPEG picture (takePicture in landscape mode.

This works fine on a HTC phone, but does not work on Samsung Google Nexus S and Samsung Galaxy S3. Is this a bug?

I know that I can use the matrix transform rotation, but wish the OS can do this more efficiently, and don't want to risk over-rotating on some other devices.

edit

Setting camera.setDisplayOrientation(90); made the preview to be in portrait mode, however it did not have any affect on the picture taken.

Further, Besides setRotation, I have also tried to set the picture size - where I flip h with w: parameters.setPictureSize(1200, 1600);. This also did not have any affect.

solution

Apparently Samsung phones set the EXIF orientation tag, rather than rotating individual pixels. As ariefbayu suggested, reading the Bitmap using BitmapFactory does not support this tag. His code sample is the solution, and this solution is also compatible with using inSampleSize.

tofi9
  • 5,775
  • 4
  • 29
  • 50
  • Check out this answer as it might help: http://stackoverflow.com/questions/3841122/android-camera-preview-is-sideways/5110406 – John J Smith Jun 13 '12 at 22:16
  • @thinksteep: no - i don't see any error via the android console. – tofi9 Jun 13 '12 at 22:34
  • @JohnJSmith: the answer concerns preview on a surface. My question is regarding taking a picture – tofi9 Jun 13 '12 at 22:36
  • I think this may also have affected the actual pictures taken as well, but it was a while ago and it was on an HTC. – John J Smith Jun 13 '12 at 22:42
  • @JohnJSmith: Setting camera.setDisplayOrientation(90); made the preview to be in portrait mode, however it did not have any affect on the picture taken. – tofi9 Jun 13 '12 at 23:08
  • I think you are talking about the effect of Exif orientation tag. – ariefbayu Jun 13 '12 at 23:14
  • @ariefbayu: Yes - I think it is related. I read about it on the documentation for setRotation. From what I understood there is that jpeg has a way to "mark" the image as rotated, rather than rotating the individual pixels. And that some hardware might decide to rotate the pixels, while other hardware might decide to just set this Exif orientation tag. Do you think Samsung DOES set this exif tag, but the Android Bitmap does not support this tag? I use the following code to read the image back (to check that the orientation was correct): Bitmap bitmap = BitmapFactory.decodeFile(url); – tofi9 Jun 13 '12 at 23:28
  • as far as I understand, from playing with Bitmap and camera. Bitmap class doesn't support Exif tag. But, I might be wrong. Need to read the documentation first (which, I don't have the time, right now). – ariefbayu Jun 13 '12 at 23:31
  • check this out http://stackoverflow.com/a/26141254/1118886 – Sheraz Ahmad Khilji Oct 01 '14 at 12:34

2 Answers2

34

I try to answer this in relation to the Exif tag. This is what I did:

Bitmap realImage = BitmapFactory.decodeStream(stream);

ExifInterface exif=new ExifInterface(getRealPathFromURI(imagePath));

Log.d("EXIF value", exif.getAttribute(ExifInterface.TAG_ORIENTATION));
if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("6")){

    realImage=ImageUtil.rotate(realImage, 90);
}else if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("8")){
    realImage=ImageUtil.rotate(realImage, 270);
}else if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("3")){
    realImage=ImageUtil.rotate(realImage, 180);
}

The ImageUtil.rotate():

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

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

    return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);
}
ariefbayu
  • 21,849
  • 12
  • 71
  • 92
  • Just done some more tests. Turns out that Samsung hardware does not rotate the pixels, and only sets the exif orientation tag to number 6. I will use your utility when reading the bitmap. The good thing about this solution is that I can still keep using the inSampleSize attribute to load only a thumbnail version, and to prevent OutOfMemoryExceptions – tofi9 Jun 13 '12 at 23:48
  • hi, I'm having the same problem, I'm trying to implement the answer but I don't understand where this code goes. What is the variable stream? There is nothing similar in my code! – lisovaccaro Jan 26 '13 at 23:33
  • Hi, it's working fine for me, is there any other way rather than creating new bitmap (Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);), it might fire OutOfMemoryException. – Bipin Vayalu Dec 26 '13 at 21:19
  • 1
    But where is ImageUtil class? Where can find I it? – sandeepmaaram Dec 04 '14 at 07:14
  • I dont understand where this code goes. Please explain your answer. – Ahmad Arslan Feb 17 '15 at 11:00
3

Liso22, the variable stream doesn't make a difference, just plug in your bitmap, however you got it (decodeFile etc). And if you're having problems with the 'ImageUtil.rotate(), just write the 'public static Bitmap rotate()' as a method with the same parameters and make 'real image' equal that. Anyways, this solution doesn't seem to be working for me, the exif tag returns 1 (normal) whether in portrait or landscape.

edid
  • 41
  • 2