Help us understand the problem. What is going on with this article?

【Flutter】カメラで撮影した画像を端末内で縮小する

はじめに

SNSなどのスマホアプリで、カメラで撮影した写真をクラウドのストレージサービスに格納するという仕組みはよくあると思います。
スマホのカメラは年々進化し、高画質な写真撮影が可能になりました。それに伴って写真1枚のファイルサイズが増大、それがストレージサービスの使用量増大に繋がり、結果サービス提供側のコスト増に繋がっています。また、利用者側(サービス授受側)では通信データ量が増大により、処理完了までの体感時間が遅くなる、通信上限に到達しやすくなるという問題が生じます。

上記サービス提供側、利用者両者の課題を解決するために、撮影した写真を端末内で縮小する機能が必要だと感じました。Flutterアプリでは「flutter_image_compress」を使用すると端末内で画像の縮小を簡単に実現できます。本記事ではその手順を紹介します。

flutter_image_compressで画像を縮小する

導入手順や仕様、サンプルはGithubに詳細が記載いるため、深い内容を知りたい方は合わせてGithubをご覧ください。ここでは、さっと試せるように、最短の動作確認方法を説明します。

flutter_image_compressの導入

Flutterを嗜まれている方であればおなじみのpub.devからコマンドで取得します。
pubspec.yamlに設定を追加して、flutter pub getを実行します。

pubspec.yaml(dependenciesにflutter_image_compressを追加)
dependencies:
  flutter_image_compress: ^0.6.3
flutter_image_compressのインストール
flutter pub get

flutter_image_compressの実装

実装例として、ImagePickerでカメラを起動し、撮影した画像を圧縮して端末に保存するというコードを紹介します。

flutter_image_compress実装例(全体)
import 'dart:io';
import 'package:image_picker/image_picker.dart';
import 'package:flutter_image_compress/flutter_image_compress.dart';   // ①

  ・・・

// ImagePickerでカメラを起動
File image = await ImagePicker.pickImage(source: ImageSource.camera);

// 画像が選択されなかった場合はスキップ
if (image == null) {
  return null;
}

// flutter_image_compressで指定サイズ/品質に圧縮
List<int> result = await FlutterImageCompress.compressWithFile(   // ②
  image.absolute.path,
  minWidth: 1536,
  minHeight: 1536,
  quality: 80,
);

// 端末の拡張ディスクに保存
String extStoPath = (await getExternalStorageDirectory()).path;
String saveFilePath =                                          
  extStoPath + 
  basenameWithoutExtension(image.absolute.path) + 
  '_compress' + 
  extension(image.absolute.path);
File saveFile = File(saveFilePath);
saveFile.writeAsBytesSync(result, flush: true, mode: FileMode.write); // ③

flutter_image_compressに関連する①~③の個所について解説します。

①の部分
import 'package:flutter_image_compress/flutter_image_compress.dart';   // ①

ここではflutter_image_compressモジュールを読み込みます。

②の部分
List<int> result = await FlutterImageCompress.compressWithFile(   // ②
  image.absolute.path,
  minWidth: 1536,
  minHeight: 1536,
  quality: 80,
);

compressWithFileメソッドで、カメラで撮影した画像を縮小しています。List<int> resultには、縮小後画像の画像情報が格納されます。resultのデータ長を取得することで、画像のデータ量を知ることができます。
compressWithFileメソッドでは、引数として与えられた条件で画像を縮小します。(縦横の最小値(minHeight/minWidth)、画像の品質(quality)です)。

いずれの引数も値を小さくすることで縮小後のファイルサイズは小さくなりますが、必要以上に縮小すると画像がつぶれてしまってうまく見えなくなってしまう恐れがあるため、縮小前後の画像を比較しながら適切な引数を設定しましょう。

③の部分
// 端末の拡張ディスクに保存
String extStoPath = (await getExternalStorageDirectory()).path;
String saveFilePath =                                          
  extStoPath + 
  basenameWithoutExtension(image.absolute.path) + 
  '_compress' + 
  extension(image.absolute.path);
File saveFile = File(saveFilePath);
saveFile.writeAsBytesSync(result, flush: true, mode: FileMode.write); // ③

flutter_image_compressで得た縮小後の画像データを、File#writeAsBytesSyncで端末に保存しています。
今回はgetExternalStorageDirectoryメソッドを使用して、端末のストレージに画像データを書き込んでいます。


下表が上記のコードを実行し、縮小前後のファイルサイズを計測したものです。
比較すると約1/10以下のファイルサイズになっています。縦横サイズの変更と合わせて画像(jpeg)の品質レベルを100->80に変更したことが効いているようです。

縮小前 縮小後
2,024,923 Byte
(約2MB)
188,530 Byte
(約190KB)

更にチューニングしたい場合は、画像とファイルサイズを見ながらcompressWithFileメソッドの引数をチューニングしましょう。パラメータの詳細はGithubの説明をご覧ください。

おわりに

flutter_image_compressを用いると、画像の縮小が簡単にできることが伝わったでしょうか。
flutter_image_compressをググってみたのですが、日本語記事が全くないのですよね…(12/3現在)。これから始められる方の一助になれば幸いです。

今回は紹介を割愛しましたが、flutter_image_compressには他にも様々な調整パラメータがあります。詳細はGithubで解説されていますので、興味のある方は色々試してみてください。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした