私は、ポートレート写真を撮ることを主な目的とするAndroid API 16から21のカメラアプリケーションを開発しています。複数のデバイス (Nexus 4、Nexus 5、HTC...) で写真を撮ることができ、それらを正しい方向に向けることができます (つまり、私のプレビューはサイズと方向の両方で撮影した写真と同じです)。
ただし、他のいくつかのデバイスでアプリケーションをテストしましたが、そのうちのいくつかは多くの問題を引き起こしています: Samsung Galaxy S3/S4/S5.
これら 3 つのデバイスでは、プレビューは正しく表示されますが、メソッドによって返される画像onPictureTaken(final byte[] jpeg, Camera camera)
は常に横向きになります。
これはbyte[] jpeg
、ディスクに保存する直前に ImageView から作成され、ユーザーに表示されるビットマップです。
そして、ディスクに保存された画像は次のとおりです。
ご覧のとおり、画像はプレビューで完全に引き伸ばされており、ディスクに保存すると誤って回転しています。
これが私の CameraPreview クラスです (カメラのパラメーターとは関係がないため、他のメソッドを難読化しました)。
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback
{
private SurfaceHolder surfaceHolder;
private Camera camera;
// Removed unnecessary code
public void surfaceCreated(SurfaceHolder holder)
{
camera.setPreviewDisplay(holder);
setCameraParameters();
camera.startPreview();
}
private void setCameraParameters()
{
Camera.Parameters parameters = camera.getParameters();
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_BACK, info);
DisplayMetrics metrics = new DisplayMetrics();
WindowManager windowManager = (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE);
windowManager.getDefaultDisplay().getMetrics(metrics);
int rotation = windowManager.getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation)
{
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
int rotate = (info.orientation - degrees + 360) % 360;
parameters.setRotation(rotate);
// Save Parameters
camera.setDisplayOrientation(90);
camera.setParameters(parameters);
}
}
この正確なコードが、Samsung 以外のデバイスで機能するのはなぜですか?
次の SO 投稿で回答を見つけようとしましたが、これまでのところ何も役に立ちませんでした: this one and this other one。
編集
Joey Chong の回答を実装しても、何も変わりません。
public void onPictureTaken(final byte[] data, Camera camera)
{
try
{
File pictureFile = new File(...);
Bitmap realImage = BitmapFactory.decodeByteArray(data, 0, data.length);
FileOutputStream fos = new FileOutputStream(pictureFile);
realImage.compress(Bitmap.CompressFormat.JPEG, 100, fos);
int orientation = -1;
ExifInterface exif = new ExifInterface(pictureFile.toString());
int exifOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
switch (exifOrientation)
{
case ExifInterface.ORIENTATION_ROTATE_270:
orientation = 270;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
orientation = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_90:
orientation = 90;
break;
case ExifInterface.ORIENTATION_NORMAL:
orientation = 0;
break;
default:
break;
}
fos.close();
}
動作中のデバイスで取得した EXIF 結果は次のとおりです。
- 方向: 0
S4 の結果は次のとおりです。
- 方向: 0