[Flutter] ImagePicker, GallerySaver #camera #gallery

2024. 1. 20. 08:50dev/flutter

728x90
반응형

you want select something images your gallery on device.

 

flutter pub add image_picker

 

 

import

import 'package:image_picker/image_picker.dart';

 

 

property

  XFile? imageFile;

 

 

select Image

  void onPickImage() async {
    final XFile? selectImage = await ImagePicker().pickImage(
      source: ImageSource.gallery,
    );
    
    setState(() {
      imageFile = selectImage;
    });
  }

 

 

seled Image show viewer

Positioned.fill - Fill on your Stack View.

InteractiveView - a Image possible zoom and move.

    if (imageFile != null) {
      // stack크기에 최대 크기 만큼 차지
      return Positioned.fill(
        // 위젯 확대 및 좌우 이동을 가능하게 하는 위젯
        child: InteractiveViewer(
          child: Image.file(File(imageFile!.path)),
        ),
      );
    }

 

 

2024-04-23-화 : image_picker고찰

XFile? photoFile = await imagePicker.pickImage(source: ImageSource.camera);

해서 찍은 사진은 다음 공간에 저장된다. (cache)

[_MyHomePageState:57] photoFile path:/data/user/0/com.donguran.demo_image_picker/cache/c72d2f2e-f372-4979-904e-7fcaa5efa4ba566265127040327541.jpg

      onPressed: () async {
        // [_MyHomePageState:57] photoFile path:/data/user/0/com.donguran.demo_image_picker/cache/c72d2f2e-f372-4979-904e-7fcaa5efa4ba566265127040327541.jpg
        final XFile? photoFile = await imagePicker.pickImage(source: ImageSource.camera);
        Log.i("photoFile:$photoFile");
        Log.i("photoFile name:${photoFile?.name}");
        Log.i("photoFile path:${photoFile?.path}");
        Log.i("photoFile mimeType:${photoFile?.mimeType}");
      },

 

결과 : jpg로 저장된다.

I/flutter (28560): [_MyHomePageState:58] photoFile name:cd6956b0-6b95-4044-b1bf-eb525adbe6fd1161739172547480629.jpg
I/flutter (28560): [_MyHomePageState:59] photoFile path:/data/user/0/com.donguran.demo_image_picker/cache/cd6956b0-6b95-4044-b1bf-eb525adbe6fd1161739172547480629.jpg
I/flutter (28560): [_MyHomePageState:60] photoFile mimeType:null

 

 

2024-04-23 : 이미지 저장

minSdkVersion: 21

 

ios권한

<key>NSPhotoLibraryUsageDescription</key>
<string>We need access to your photo library to select images.</string>
<key>NSCameraUsageDescription</key>
<string>We need access to your camera to take photos.</string>

 

그리고 이 권한을 지속적으로 사용하려면 권한을 요청해야한다

더보기

add

flutter pub add permission_handler

 

request

await Permission.photos.request().isGranted

근데 권한이 계속 요청되지 않았다.

ios/Profile에서 주석을 해제시킨다.

> 그래도 안된다.

platform :ios, '10.0'

 

 

import

flutter pub add gallery_saver

 

 

이미지 저장

url path

String url = "https://"
await GallerySaver.saveImage(url);

// or (url, albumName: 'Flutter')

 

file path

toDcim : true (전체카메라에 저장됨)

final tempDir = await getTemporaryDirectory();
final path = '${tempDir.path}/myfile.jpg'
await Dio().download(url, path);

await GallerySaver.saveImage(path);

 

 

 

save image

RepaintBoundary Widget can save child Widgets.

wrapped you want widget.

make GlobalKey.

GlobalKey imgKey = GlobalKey(); 

return RepaintBoundary(
        key: imgKey,
        child: Positioned.fill(
          // 위젯 확대 및 좌우 이동을 가능하게 하는 위젯
          child: InteractiveViewer(
            child: Stack(
              fit: StackFit.expand,
              children: [

 

import

import 'dart:ui' as ui;
import 'dart:typed_data';
import 'package:flutter/services.dart';

import 'package:image_gallery_saver/image_gallery_saver.dart';

 

 

onSaveImage Function

  void onSaveImage() async {
    RenderRepaintBoundary boundary = imgKey.currentContext!
        .findRenderObject() as RenderRepaintBoundary;

    ui.Image image = await boundary.toImage();
    ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.png);
    Uint8List pngBytes = byteData!.buffer.asUint8List();

    await ImageGallerySaver.saveImage(pngBytes, quality: 100);
    ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("저장되었습니다"),));
  }

 


 

tapped something image

class _EmoticonStickerState extends State<EmoticonSticker> {
  // 확대/축소 비율
  double scale = 1;
  double hTransform = 0;  // 가로 움직임
  double vTransform = 0;  // 세로 움직임
  double actualScale = 1; // 위젯의 초기 크기 기준 확대/축소 비율

  @override
  Widget build(BuildContext context) {
    return Transform(
      transform: Matrix4.identity()
      ..translate(hTransform, vTransform)
      ..scale(scale, scale),
      child: Container(
        decoration: widget.isSelected? 
        BoxDecoration(
          borderRadius: BorderRadius.circular(4.0),
          border: Border.all(
            color: Colors.blue,
            width: 1.0,
          )
        )
            :
        BoxDecoration(
          border: Border.all(
            color: Colors.transparent,
            width: 1.0,
          )
        ),
        child: GestureDetector(
          onTap: () {
            widget.onTransform();
          },
          onScaleUpdate: (details) {
            widget.onTransform();
            setState(() {
              scale = details.scale * actualScale;
      
              vTransform += details.focalPointDelta.dy;   // 세로 이동 거리 계산
              hTransform += details.focalPointDelta.dx;   // 가로 이동 거리 계산
            });
          },
          onScaleEnd: (details) {
            actualScale = scale;
          },
          child: Image.asset(widget.imgPath),
        ),
      ),
    );
  }
}

 


2024-05-30-목 : 이미지 편집 Cropped

OCR이랑 같이 사용할 경우 문제가 생기므로 다음과 같이 버전을 설정한다.

  image_picker: ^1.1.1
  flutter_tesseract_ocr: ^0.4.24
  image_cropper: ^5.0.1

 

add

flutter pub add image_cropper

 

 

android

- 해당 이미지가 Android Activity로 이동하게 되기 때문에 Manifest에 등록해주어야 한다.

<activity
    android:name="com.yalantis.ucrop.UCropActivity"
    android:screenOrientation="portrait"
    android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>

 

iOS

- 해당 없음 

 

내가 원하는 기능은 이미지를 받아와서 원하는 크기로 Cropped하는 것이다.

 

이미지 받기 (image_picker 사용)

  final XFile? pickedImage =  await ImagePicker().pickImage(source: ImageSource.gallery);
  if (pickedImage != null) {

 

받은 이미지를 CroppedFile객체에 넣는다.

- 편집을 직접 수동적으로 크기를 조절하고 싶은 경우 uiSettings파라메터를 조작한다.

- AndroidSettings(lockAspectRatio: false)를 해주어야 직접 수동으로 사진 편집크기를 조절할 수 있다.

  if (pickedImage != null) {
    CroppedFile? croppedImage = await ImageCropper().cropImage(sourcePath: pickedImage.path,
      cropStyle: CropStyle.rectangle,
      aspectRatioPresets: [
        CropAspectRatioPreset.square
      ],
      uiSettings: [
        AndroidUiSettings(
          lockAspectRatio: false
        ),
      ]
    );

 

각 pickImage와 croppedImage path이다.

pickedImage.path:/data/user/0/com.example.demo_ocr/cache/bc054044-276d-41f2-aa53-8841b898798c/1000001019.jpg
croppedImage.path:/data/user/0/com.example.demo_ocr/cache/image_cropper_1717032792703.jpg

728x90
반응형