私がやっていることは簡単なように思えますが、見つけることができるすべてのStackoverflowの回答を読み、見つけたすべての記事をGoogleで検索した後も、私は道に迷っています。
プレビューSurfaceViewを使用して、AndroidManifest.xmlでscreenOrientation = "landscape"に設定されているアクティビティから画像をキャプチャしています。
1.5を実行しているいくつかのMotorolaデバイスでアプリを試すまで、サンプルのカメラアプリのコードをたどり、問題がなかったと思いました。
OrientationEventListenerは正常に実行されています。リフレクションを使用して、回転がそのように設定されているかどうかを確認します。
final int latchedOrientation = roundOrientation(mLastOrientation + 90);
Parameters parameters = preview.camera.getParameters();
JPLog.d("Setting camera rotation = %d", latchedOrientation);
try {
// if >= 2.0
Method method = Camera.Parameters.class.getMethod("setRotation",
int.class);
if(method != null) {
method.invoke(parameters, latchedOrientation);
}
} catch(Throwable t) {
// if < 2.0
parameters.set("rotation", latchedOrientation);
}
preview.camera.setParameters(parameters);
NexusOne(OS 2.2)-うまく動作します。ラッチされたオリエンテーション= 0、画像はEXIFヘッダーの回転なしで問題ありません。
T-Mobile G1(OS 1.6)-また、うまく機能します。ラッチされた方向= 0、画像OK。
Motorola Backflip(OS 1.5)-画像を回転します。ラッチされた方向= 0、画像にはEXIF回転がありません。
Motorola CLIQ(OS 1.5)-画像を回転します。ラッチされた方向= 0、画像にはEXIF回転がありません。
これらのモトローラデバイスで何が起こっているのですか?私の問題はモトローラのカメラドライバーが画像を回転していないことだと思ったので、AndroidのSanselan EXIF読み取りクラスを見つけて、自分で回転する準備をしていました。面白いことに、EXIFヘッダーがありますしかし、回転要素はありません。
手動で回転を90度に設定した場合、画像はMotorolaデバイスで完璧に出力されますが、G1とNexusOneには90度回転した画像が含まれています(希望どおりではありません)。ここにないものがあるはずです。
これが1.5の問題かどうか疑問に思っています。
これは実際にはデバイス固有の問題であり、ほとんどがMotorolaデバイスに影響します。 Google開発者は、問題を回避するために、API 8にsetDisplayOrientationコールを含めました。主なバグは ここ で報告されています。
API 8にアクセスできない人のための2つの一般的なソリューションは次のとおりです。
onDrawをオーバーライドします
最上位のViewGroupでonDrawをオーバーライドし、キャンバスを90度回転して回転を補正します。タッチイベントも回転する必要があるため、ここでは注意が必要です。
横向きモードを使用
アクティビティを横向きモードにロックしますが、縦向きのようにアセットを描画します。つまり、レイアウトを行い、画像アセットを回転させて、縦長モードのように見えるようにして、ビューが正常に見えるようにします。メニューが横に開くため、残念ながらメニューの使用が困難になります。
また、ビューを回転させるためにアニメーションコントローラを使用する人を見たこともあります。ここで克服できなかった欠点は、回転したビューが画面いっぱいに拡大されないことです。実装例については、 answer by Georg を参照してください。
この問題が発生したため、この方法を使用して画像をキャプチャしました。 (カスタムカメラを作成せずに)
final Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(image));
startActivityForResult(intent, 0);
残りはonActivityResult(int requestCode、int resultCode、Intent data){}で行いました
しかし、元の画像(実際のSDカードの画像)は正しく、このようにフェッチするとビットマップが回転しました。ビットマップbmp = BitmapFactory.decodeStream(..
ソリューション:
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");
}
これが私のアクティビティでonActivityResult()を使用したコードです。返されるインテントは、タイプimage/*の画像を選択するためのものでした。私にはうまくいきます!
Uri imageUri = intent.getData();
String[] orientationColumn = {MediaStore.Images.Media.ORIENTATION};
Cursor cur = managedQuery(imageUri, orientationColumn, null, null, null);
int orientation = -1;
if (cur != null && cur.moveToFirst()) {
orientation = cur.getInt(cur.getColumnIndex(orientationColumn[0]));
}
Matrix matrix = new Matrix();
matrix.postRotate(orientation);
「ランドスケープモードを使用する」という提案だけが実際に機能するようです。これをマニフェストに含めるか、アクティビティonCreateのsetRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
の呼び出しを介して行うかは問題ないようです。