[flutter] photo_view 패키지를 이용한 이미지 픽셀 추가/제거하기

Flutter는 이미지 표시와 관련된 작업을 위해 다양한 패키지를 제공합니다. 그 중 하나인 photo_view 패키지는 이미지를 자유롭게 확대/축소하고 움직일 수 있는 기능을 제공합니다. 이번 블로그 포스트에서는 photo_view 패키지를 이용하여 이미지에 픽셀을 추가하거나 제거하는 방법을 알아보겠습니다.

1. photo_view 패키지 추가하기

먼저, photo_view 패키지를 사용하기 위해 프로젝트에 패키지를 추가해야 합니다. pubspec.yaml 파일을 열고, dependencies 섹션에 아래와 같이 photo_view 패키지를 추가합니다.

dependencies:
  flutter:
    sdk: flutter
  photo_view: ^0.11.1

패키지를 추가한 후, 터미널에서 flutter packages get 명령어를 실행하여 패키지를 다운로드 받습니다.

2. 이미지 픽셀 추가/제거하는 기능 구현하기

photo_view 패키지에서는 ImageProvider 클래스를 이용하여 이미지를 로드하고 표시합니다. 따라서 이미지의 픽셀을 추가하거나 제거하기 위해서는 이 클래스를 확장해서 새로운 이미지 효과를 구현해야 합니다.

아래는 CustomImageProvider 클래스를 생성하여 이미지 픽셀을 추가하고 제거하는 기능을 구현한 예제입니다.

import 'package:flutter/widgets.dart';
import 'package:photo_view/photo_view.dart';

class CustomImageProvider extends ImageProvider<CustomImageProvider> {
  final String imageUrl; // 이미지 URL
  final int pixelSize; // 픽셀 크기

  CustomImageProvider(this.imageUrl, this.pixelSize);

  @override
  Future<CustomImageProvider> obtainKey(ImageConfiguration configuration) {
    return SynchronousFuture<CustomImageProvider>(this);
  }

  @override
  ImageStreamCompleter load(CustomImageProvider key, DecoderCallback decode) {
    return MultiFrameImageStreamCompleter(
      codec: _loadAsync(key),
      scale: 1.0,
      informationCollector: () => <DiagnosticsNode>[],
    );
  }

  Future<Codec> _loadAsync(CustomImageProvider key) async {
    // 이미지 로드
    final Uint8List? bytes = await NetworkAssetBundle(Uri.parse(key.imageUrl)).load(key.imageUrl);
    if (bytes == null) throw Exception('Failed to load image: $imageUrl');

    // 이미지 픽셀 추가/제거
    final Image image = decode(bytes);
    final PictureRecorder recorder = PictureRecorder();
    final Canvas canvas = Canvas(recorder);
    canvas.drawImage(image, Offset.zero, Paint());
    for (int x = 0; x < image.width; x += key.pixelSize) {
      for (int y = 0; y < image.height; y += key.pixelSize) {
        final color = image.getPixel(x, y);
        final rect = Rect.fromLTWH(x.toDouble(), y.toDouble(), key.pixelSize.toDouble(), key.pixelSize.toDouble());
        canvas.drawRect(rect, Paint()..color = color);
      }
    }

    // 새로운 이미지로 반환
    final Picture picture = recorder.endRecording();
    final ImageProvider provider = picture.toImage(image.width, image.height).getByteData();
    final Codec codec = await provider!.toCodec();

    return codec;
  }
}

위의 예제에서는 CustomImageProvider 클래스를 ImageProvider 클래스를 상속받아 구현합니다. imageUrlpixelSize는 생성자를 통해 전달됩니다. load 메서드에서는 이미지를 로드하고, _loadAsync 메서드에서는 이미지 픽셀을 추가/제거하여 새로운 이미지로 반환합니다.

3. photo_view를 이용하여 이미지 표시하기

이제 CustomImageProvider 클래스를 이용하여 이미지를 표시해보겠습니다. 아래는 photo_view 패키지를 사용하여 이미지를 확대/축소하고 움직일 수 있는 예제 코드입니다.

import 'package:flutter/material.dart';
import 'package:photo_view/photo_view.dart';
import 'custom_image_provider.dart';

class ImagePage extends StatelessWidget {
  final String imageUrl;

  ImagePage(this.imageUrl);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Image Page'),
      ),
      body: Center(
        child: PhotoView(
          imageProvider: CustomImageProvider(imageUrl, 5), // 이미지 픽셀 크기는 5
          initialScale: PhotoViewComputedScale.contained * 0.8, // 초기 확대/축소 비율
        ),
      ),
    );
  }
}

위의 예제 코드에서 CustomImageProvider를 이용하여 PhotoView 위젯을 생성합니다. imageProvider 파라미터에는 CustomImageProvider의 인스턴스를 전달하고, initialScale 파라미터로 초기 확대/축소 비율을 설정합니다.

결론

이번 포스트에서는 photo_view 패키지를 이용하여 이미지에 픽셀을 추가하거나 제거하는 방법을 알아보았습니다. CustomImageProvider를 활용하여 이미지 효과를 개별적으로 구현할 수 있습니다. Flutter의 photo_view 패키지는 다양한 이미지 효과를 쉽게 구현할 수 있도록 도와줍니다.

더 자세한 내용은 photo_view 패키지 문서를 참고하시기 바랍니다.