アプリ内で写真を撮りその画像を表示すると、写真の向きが上下逆さに表示されるという不具合を見つけました。
その際の解決法を紹介していきます。
起きた現象
↓↓「camera」というプラグインを使って、デバイスを横に90度回転して撮影します。
https://pub.dev/packages/camera
撮影した画像をアプリ内で表示すると、写真の向きが上下逆さに表示されていました。
手元のAndroidのPixel 7(OSバージョンはAndroid 13)でこの現象が起き、iPhone14Pro(iOSバージョンは16.5)では起きなかったです。
つまりOSや機種によって、起きたり起きなかったりするということで少し困りました?
原因
ほとんどの写真を保存する際は、Exifというファイルフォーマットで保存されます。
Wikipediaからの引用だとこのような感じです。
Exchangeable image file formatは、富士フイルムが開発し、当時の日本電子工業振興協会 で規格化された、写真用のメタデータを含む画像ファイルフォーマット。デジタルカメラの画像の保存に使われる。略称はExifで「エグジフ」。
つまり撮影した写真の他、写真の撮影日時や撮影した機種、ファイルサイズなど写真に関する情報も一緒に保存していますよ、ということです。
その中に撮影時のデバイスの回転情報も含みます。
この情報を元に、画像ビューアーは正しく画像を回転させ表示します。
しかし一部のデバイスでは、回転情報が正しく保存されないか、画像ビューアー側が正しく回転情報を解釈しない場合があるようです。
今回のケースでは、回転情報が正しく保存されていないことが原因で、画像が意図しない方向に回転していました。
正常に画像が表示されている時の、撮影時のデバイスの向きと正しい回転情報のペアはこちらでした。
- 回転なし: Rotated 90 CW - 右に90度回転: Rotated 180 - 左に90度回転: Horizontal (normal) - 上下反転: Rotated 90 CCW
しかし画像が回転して表示されるデバイスでは、以下のように回転情報が保存されていました。
- 回転なし: Rotated 90 CW - 右に90度回転: Horizontal (normal) → ここが違う - 左に90度回転: Rotated 180 → ここが違う - 上下反転: Rotated 90 CCW
上記のように、デバイスを「右に90度回転」と「左に90度回転」して撮影した時に、正常に表示される画像の回転情報と異なっています。
これが画像が反転する原因でした。
解決方法
画像を表示する際に、回転情報が正しくない場合は、アプリ内で正しい向きに回転させるようにしました。
↓↓画像を回転させる際に使用したパッケージは、「flutter_image_compress」というものです。
https://pub.dev/packages/flutter_image_compress
コードは以下のような感じで、回転情報が正しくない場合は、rotateパラメータに180を代入して画像を反転させました。
// カメラを横向きに撮影し、回転情報が正しくない場合、rotateパラメータに180を代入 if ( (nativeDeviceOrientation == NativeDeviceOrientation.landscapeRight && data['Image Orientation'].toString() != 'Rotated 180') || (nativeDeviceOrientation == NativeDeviceOrientation.landscapeLeft && data['Image Orientation'].toString() != 'Horizontal (normal)') ) { orientation = 180; } // 画像を回転させる final fixedImageBytes = await FlutterImageCompress.compressWithFile( file.path, rotate: orientation, );
その後、その回転させた画像を画像表示する処理に渡して、無事正常な向きで表示されるようになりました?
まとめ
本記事のまとめは以下の通りです。
- 画像が意図しない向きに回転するのは、Exifの回転情報が誤って保存されていたため。
- 画像を表示する時、間違った回転情報の場合は反転処理して表示するようにした。
最後までお読みいただき、ありがとうございました。