flutterで画像を加工する

## はじめに

flutterにおいて画像を回転させて表示する記事はいくつか見かけますが、画像そのものを回転させて保存する記事はあまりなく、実装に手間取ったのでまとめます。


## 画像を回転させて表示したい場合

画像を回転させて表示させたい場合は以下のwidgetを使うのが良さそうです。

```
RotatedBox(
  quarterTurns: 回転角度, 
  child: Image.file(画像ファイルパス)
) 
```

## 画像を加工する
使用するPackage : [image](https://pub.dev/packages/image)

上記のパッケージは画像加工の大半を担うパッケージです。android、iOSともに問題なく動作します。

ただ、flutter標準のImageクラスと被っていしまうため以下のようにimportする必要があります。

```
import 'package:image/image.dart' as hogehoge;
```
また、使うには、一度画像を`Image`クラスから`hogehoge.Image`クラスに変換する必要があります。

```
hogehoge.decodeImage(File(Path).readAsBytesSync());
```

あとは以下のように加工ができます。

```
// リサイズ
hogehoge.Image image = copyResize(image, width: 120);
// 回転
hogehoge.Image image = copyRotate(image, 90);
```

また、画像の明度や色も変更できるので上記リンクをご参照ください。



## 画像を圧縮する

使用するPackage : [flutter_image_compress](https://pub.dev/packages/flutter_image_compress)

画像圧縮には上記のパッケージが良いと思います。
使い方は以下のようです。

```
Future<File> testCompressAndGetFile(File file, String targetPath) async {
    var result = await FlutterImageCompress.compressAndGetFile(
        file.absolute.path, targetPath,
        quality: 80,
        rotate: 180,
      );
    print(file.lengthSync());
    print(result.lengthSync());

    return result;
  }
```
rotationで回転角度を設定し、qualityで圧縮できます。
コードの`file.absolute.path` と`targetPath`を一致させれば端末内で上書き保存できます。

こちらもandroid、iOSどちらでも問題なく動きます。

## 画像のexif情報を取得する
exif情報とは以下のようなものです。
>Exchangeable image file format（エクスチェンジャブル・イメージ・ファイル・フォーマット）は、富士フイルムが開発し、当時の日本電子工業振興協会 (JEIDA)で規格化された、写真用のメタデータを含む画像ファイルフォーマット。デジタルカメラの画像の保存に使われる。略称はExifで「エグジフ」（もしくは「イグジフ」）。

以下のような情報を取得できます。
- 撮影日時
- 位置情報
- 撮影方向
- 撮影機器のメーカー名
- 画像全体の解像度
......

こちらも先ほど紹介した[image](https://pub.dev/packages/image)というパッケージで取得できます。

```
Image.from(Image other)
    : width = other.width,
      height = other.height,
      xOffset = other.xOffset,
      yOffset = other.yOffset,
      duration = other.duration,
      disposeMethod = other.disposeMethod,
      blendMethod = other.blendMethod,
      channels = other.channels,
      data = Uint32List.fromList(other.data),
      exif = ExifData.from(other.exif),
      iccProfile = other.iccProfile;
```

### 参照
- exifに関して : [wikipedia](https://ja.wikipedia.org/wiki/Exchangeable_image_file_format)






## 画像を圧縮・リサイズする
使用するPackage : [flutter_native_image](https://pub.dev/packages/flutter_native_image)

使い方は以下のようです。

```
ImageProperties properties = await FlutterNativeImage.getImageProperties(file.path);
File compressedFile = await FlutterNativeImage.compressImage(
  file.path,
  quality: 80, 
  targetWidth: 600, 
  targetHeight: 300
);
```
qualityで圧縮、targetWidth・targetHeightでリサイズができます。

ただこちらはandroidではうまく動作しますがiOSではうまく動作しないこともありそうなのでマルチプラットフォームを検討している際は注意が必要？です(2019/12/05 時点)。


以下、flutterで使えそうな小技をいくつか紹介します。

## 実行時間を計測する
```
var stopwatch = Stopwatch()..start();
// 計測したい処理
stopwatch.stop();
print('時間${stopwatch.elapsedMicroseconds } ms');
```
elapsedMicrosecondsを変更することで様々な単位の時間を計測できます。
### 参照
[公式ドキュメント](https://api.dartlang.org/stable/2.6.1/dart-core/Stopwatch-class.html)

## 画像ファイルを保存・上書きする
```
final imageFile = File(path);
await imageFile.writeAsBytes(await 画像ファイル.readAsBytes());
```
### 参照
[Flutterで画像をローカルに保存して画面に表示](http://karmactonics.hatenablog.com/entry/2018/09/02/223139)


## 終わりに
現時点で使えそうなflutterプラグインをいくつか紹介しました。
何か間違えがあればご指摘ください!
次回は簡単なアプリを作って紹介したいと考えています！