코딩 일기장/Flutter

[Flutter] Camera에서 실시간으로 이미지 받아오기

minWachya 2023. 5. 28. 16:04
반응형

카메라에서 보이는 이미지를 실시간으로 캡쳐해보려고 한다..

결과화면

결과 화면은 다음과 같다.

앱을 실행하면 카메라 화면이 보인다.

카메라 화면

아래 플로팅 버튼을 누르면 해당 카메라의 화면이 캡쳐되고, 이 캡쳐된 이미지를 보여주는 화면으로 이동한다.

캡쳐 이미지 확인하는 화면

 

공식 문서

https://docs.flutter.dev/cookbook/plugins/picture-using-camera#3-create-and-initialize-the-cameracontroller

 

Take a picture using the camera

How to use a camera plugin on mobile.

docs.flutter.dev


1. 의존성 추가

- file_path, path 라이브러리는 추가하지 않았다.

dependencies:
//...
  camera: ^0.10.5+2

 

+ 안드로이드: minSdkVersion을 21 이상으로 수정

+ iOS: ios/Runner/Info.plis 파일 아래 아래 코드 추가

<key>NSCameraUsageDescription</key>
<string>Explanation on why the camera access is needed.</string>
<key>NSMicrophoneUsageDescription</key>
<string>Explanation on why the microphone access is needed.</string>

 

2. 코드 작성

import 'dart:io';

import 'package:flutter/material.dart';
import 'package:camera/camera.dart';

// --------------------------------
Future<void> main() async {
  // 비동기 데이터 다룸으로 아래 코드 추가
  // 다음에 호출되는 함수 모두 실행 끝날 때까지 기다림
  WidgetsFlutterBinding.ensureInitialized();

  // 기기에서 사용 가능한 카메라 목록 불러오기
  final cameras = await availableCameras();

  // 사용 가능한 카메라 중 첫 번째 카메라 사용
  final firstCamera = cameras.first;

  runApp(
    MaterialApp(
      theme: ThemeData.dark(),
      home: MyApp(
        camera: firstCamera,
      ),
    ),
  );
}

// --------------------------------
// 카메라 화면
class MyApp extends StatefulWidget {
  const MyApp({
    super.key,
    required this.camera,
  });

  final CameraDescription camera;

  @override
  MyAppState createState() => MyAppState();
}

class MyAppState extends State<MyApp> {
  late CameraController _controller;
  late Future<void> _initializeControllerFuture;

  @override
  void initState() {
    super.initState();
    // 카메라 관리하는 컨트롤러 생성
    _controller = CameraController(
      widget.camera,
      ResolutionPreset.medium,
    );
    _initializeControllerFuture = _controller.initialize();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('카메라 화면')),
      body: Column(
        children: [
          FutureBuilder<void>(
            future: _initializeControllerFuture,
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.done) {
                // 미리보기
                return CameraPreview(_controller);
              } else {
                return const Center(child: CircularProgressIndicator());
              }
            },
          ),
        ],
      ),
      // 버튼 누를 시 카메라 화면의 캡쳐본을 보여주는 화면으로 이동
      floatingActionButton: FloatingActionButton(
        onPressed: () async {
          try {
            await _initializeControllerFuture;
            // 현재 카메라 화면 캡쳐
            final image = await _controller.takePicture();

            if (!mounted) return;

            // 사진 보여주기
            await Navigator.of(context).push(
              MaterialPageRoute(
                builder: (context) => DisplayPictureScreen(
                  imagePath: image.path,
                ),
              ),
            );
          } catch (e) {
            print(e);
          }
        },
        child: const Icon(Icons.camera_alt),
      ),
    );
  }
}

// --------------------------------
// 찍은 사진 보여주는 위젯
class DisplayPictureScreen extends StatelessWidget {
  final String imagePath;

  const DisplayPictureScreen({super.key, required this.imagePath});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('캡쳐 화면')),
      body: Image.file(File(imagePath)),
    );
  }
}

 

이미지의 저장 경로는 아래와 같다.

/data/user/0/com.example.test_camera_controller/cache/CAP6511869317126097536.jpg

 

 

반응형