[Flutter] 이미지를 불러와서 자르고 압축하고 업로드까지


이슈

Flutter 앱에서 기기의 이미지를 서버로 업로드하고자 한다. 이때 이미지를 일정한 규격에 맞게 crop하고 싶다. 또한 서버 저장소의 용량을 아끼고자 이미지 품질의 큰 손해 없이 압축을 통해 용량을 줄이고 싶다. 이를 어떻게 가장 쉽고 효율적으로 수행할 수 있을까?


해결

라이브러리

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import 'package:dio/dio.dart';
import 'package:image_picker/image_picker.dart';
import 'package:image_cropper/image_cropper.dart';

// 이미지 불러오기
Future<void> loadImage() async {
    final ImagePicker _picker = ImagePicker();

    final XFile? image = await _picker.pickImage(source: ImageSource.gallery);
    if(image != null) cropImage(image.path!);
}

// 이미지 자르기
Future<void> cropImage(String imagePath) async {
    const MAX_WIDTH = 1920;
    const MAX_HEIGHT = 1080;
    const COMPRESS_QUALITY = 75;

    File? croppedImage = await ImageCropper.cropImage(
        sourcePath: imagePath, // 이미지 경로
        maxWidth: MAX_WIDTH, // 이미지 최대 너비
        maxHeight: MAX_HEIGHT, // 이미지 최대 높이
        compressQuality: COMPRESS_QUALITY // 이미지 압축 품질

        // . . .
        // 기타 property 설정
        // . . .

    );
    
    if(croppedImage != null) uploadImage(croppedImage.path!);
}

// 이미지 업로드
Future<void> uploadImage(String imagePath) async {
    var dio = Dio();
    var formData = FormData.fromMap({
        'image' : await MultipartFile.fromFile(imagePath)
    });

    final response = await dio.post('/image/upload', data: formData);
}

고찰

image_picker

가장 대표적인 flutter 이미지 선택 라이브러리이다. 대표라고 불릴 만큼 많은 기능들을 지원하고 있는데, 사실 위 코드에서는 이미지 사이즈 조정압축image_cropper 라이브러리를 통해 진행했지만 image_picker 또한 maxWidth, maxHeight, imageQuality 속성을 통해 사이즈 조정과 압축이 가능하다! 따라서 이미지를 자를 일이 없다면 image_picker만 사용해도 무관하다.

image_cropper

마찬가지로 가장 대표적인 flutter 이미지 크롭 라이브러리이다. 라이브러리 자체는 cropper 라는 명칭을 달고 있지만 이미지의 회전 및 스케일 조정까지 가능하다. 또한 작동 플랫폼에 따라 해당 플랫폼의 네이티브 라이브러리를 사용하기 때문에 성능이 준수하고 UI가 다르다. AndroiduCrop에, iOSTOCropViewController에 기반한다. 더 자세한 내용은 공식 문서 참조. 또한 마찬가지로 image_picker와 같이 이미지 사이즈 조정압축을 지원한다. 따라서 image_cropper까지 사용하게 되는 상황이라면 이와 같은 처리는 위 코드와 같이 image_cropper에서 진행해주면 된다.

dio

이미 아래와 같은 블로그 포스팅으로 자세히 다뤄보았다.

0%