web-dev-qa-db-ja.com

カメラから回転した写真(SAMSUNGデバイス)

私はこの会社が嫌いです。それらすべてのデバイスには多くのバグがあります。 Ok質問:愚かな問題を修正しようとしています(私が知っているように、5年以上存在します)カメラから撮影した写真-90度回転しました。2つのデバイスがあります:

  Nexus 5p and Samsung j2  
  Nexus - work perfect. Everything fine. 
  Samsung - photo rotated

例えば ​​:

Photo size - nexus : Portrate : width 1000, height 1900.  Landscape :
width 1900 , height 1000

サムスンのデバイスで見てみましょう:

Photo size  - Portrate: width 1900(?????) height - 1000(????)
rotate to landscape : width 1900 height 1000

いくつかのテストの後:サムスンデバイスで横向きモードで写真を作成する場合-すべてが大丈夫です。写真が回転していません

PORTRATEで写真を作成する場合-写真は90度回転します。 (しかし、風景のように写真のサイズ(その可能性)?

誰もがこの愚かなバグを修正する方法を知っていますか?たぶん、カメラの向きを検出する方法を教えてもらえますか?写真にIntentActivityを使用しています:

String _path = Environment.getExternalStorageDirectory()
                                    + File.separator + "camera_img.jpg";
                            File file = new File(_path);
                            Uri outputFileUri = Uri.fromFile(file);
                            Intent intent = new Intent(
                                    Android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
                            intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
                            startActivityForResult(intent, CAMERA_REQUEST);

何か助けはありますか?サムスンのデバイスが回転する場合は、チェッカーも追加します。ただし、回転は、Portrateモードで写真を作成する場合にのみ有効です。風景の中ではすべてがうまくいきます。だから私はどういうわけかどの方向の写真が作成されたかを検出する必要があります。誰もが知っていますか?

6
Peter

PD 29.08.2018こんにちは、私はこの方法がAndroid 8+に基づくsamsungデバイスでは機能しないことを検出しました。私はsamsungs8を持っていません(たとえば)なぜこれが再び機能しないのか理解できません。誰かがこれが機能しない理由をテストして確認できる場合は、これを一緒に修正してみましょう。

私は修正する方法を見つけました:まあ、それは本当に愚かで私にとって非常に難しいです

最初のステップは活動結果を取得します

 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == CAMERA_REQUEST && resultCode == Activity.RESULT_OK) {

            String _path = Environment.getExternalStorageDirectory() + File.separator + "TakenFromCamera.jpg";
            String p1 = Environment.getExternalStorageDirectory().toString();
            String fName = "/TakenFromCamera.jpg";
            final int rotation = getImageOrientation(_path);
            File file = resaveBitmap(p1, fName, rotation);
            Bitmap mBitmap = BitmapFactory.decodeFile(_path);

mainは、ファイルを変更する前に:getImageOrientationを実行します。

1)getImageOrientation(パスによる)
2)ファイルを再保存します(サーバーに送信する必要がある場合、プレビューのみが必要な場合は、この手順をスキップできます)
3)ファイルから正しいビットマップを取得する

手順1と3のみを十分にプレビューし、この関数を使用するには、ビットマップを回転するだけです。

private Bitmap checkRotationFromCamera(Bitmap bitmap, String pathToFile, int rotate) {
        Matrix matrix = new Matrix();
        matrix.postRotate(rotate);
        Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
        return rotatedBitmap;
    }

getImageOrientation

public static int getImageOrientation(String imagePath) {
    int rotate = 0;
    try {
        ExifInterface exif = new ExifInterface(imagePath);
        int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
        switch (orientation) {
            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 (IOException e) {
        e.printStackTrace();
    }
    return rotate;
}

必要に応じてResaveBitmap

private File resaveBitmap(String path, String filename, int rotation) { //help for fix landscape photos
        String extStorageDirectory = path;
        OutputStream outStream = null;
        File file = new File(filename);
        if (file.exists()) {
            file.delete();
            file = new File(extStorageDirectory, filename);
        }
        try {
            // make a new bitmap from your file
            Bitmap bitmap = BitmapFactory.decodeFile(path + filename);
            bitmap = checkRotationFromCamera(bitmap, path + filename, rotation);
            bitmap = Bitmap.createScaledBitmap(bitmap, (int) ((float) bitmap.getWidth() * 0.3f), (int) ((float) bitmap.getHeight() * 0.3f), false);
            bitmap = Utils.getCircleImage(bitmap);
            outStream = new FileOutputStream(path + filename);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
            outStream.flush();
            outStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return file;
    }

それはすべて:)そしてすべてがうまくいく

4
Peter

画像を回転させたいが、バイト配列しかない場合は、次のように使用できます。

private byte[] rotationFromCamera(byte[] data) {
    int rotation = Exif.getOrientation(data);
    if(rotation == 0) return data;
    Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, null);
    Matrix matrix = new Matrix();
    matrix.postRotate(rotation);
    Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    rotatedBitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
    return stream.toByteArray();
}

そしてこれからのこのexifutil answer

画像が大きい場合、これは少し遅くなります。

1
fede1608

これを見つけました ここ 、私のために動作しますサムスンS8。

static final String[] CONTENT_ORIENTATION = new String[] {
            MediaStore.Images.ImageColumns.ORIENTATION
    };


public static int getExifOrientation(Context context, Uri uri) {
    ContentResolver contentResolver = context.getContentResolver();
    Cursor cursor = null;
    try {
        String id = DocumentsContract.getDocumentId(uri);
        id = id.split(":")[1];
        cursor = contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                CONTENT_ORIENTATION, MediaStore.Images.Media._ID + " = ?", new String[] { id }, null);
        if (cursor == null || !cursor.moveToFirst()) {
            return 0;
        }
        return cursor.getInt(0);
    } catch (RuntimeException ignored) {
        // If the orientation column doesn't exist, assume no rotation.
        return 0;
    } finally {
        if (cursor != null) {
            cursor.close();
        }
    }
}

これは、Gallery Intent.ACTION_GET_CONTENTから画像を取得したときに機能します。

MediaStore.ACTION_IMAGE_CAPTUREでテストしたところ、0が返されました。しかし、何か問題が発生している可能性があります。

1
paakjis

カメラAPIを使用して自分で写真を撮っていますか?その場合は、Camera1 API:でオリエンテーションを取得できます。

CameraInfo cameraInfo = new CameraInfo();
int sensorOrientation = cameraInfo.orientation;

Camera2 API:

CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
CameraCharacteristics characteristics = mCameraCharacteristics;
int sensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
0
Quentin Menini