how to implement an image cropping in flutter using crop_your_image package ?

Spread the love

how to implement an image cropping in flutter using crop your image package
how to implement an image cropping in flutter using crop your image package

Introduction:

Implementing image cropping in Flutter allows users to select a specific area of an image. The crop_your_image package provides a simple way to integrate image cropping functionality into your app. This tutorial will guide you through implementing image cropping using the crop_your_image package.

Content:

Step 1: Add the dependency:

Include the crop_your_image package in your pubspec.yaml file:


dependencies:
  crop_your_image: ^1.0.1

Run flutter pub get to install the package.

Step 2: Import the package:

Import the crop_your_image package in your Dart file:


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

Step 3: Create a CropImageScreen widget:

Define a stateful widget and implement the CropYourImage widget to provide image cropping functionality:


class CropImageScreen extends StatefulWidget {
  @override
  _CropImageScreenState createState() => _CropImageScreenState();
}

class _CropImageScreenState extends State<CropImageScreen> {
  GlobalKey<CropYourImageState> cropKey = GlobalKey<CropYourImageState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Crop Image Example'),
        actions: [
          IconButton(
            icon: Icon(Icons.crop),
            onPressed: () async {
              final croppedImage = await cropKey.currentState!.cropImage();
              // Use the croppedImage as needed
            },
          ),
        ],
      ),
      body: Center(
        child: CropYourImage(
          image: AssetImage('path_to_your_image.jpg'),
          key: cropKey,
          aspectRatio: CropAspectRatio(ratioX: 1.0, ratioY: 1.0),
          borderRadius: BorderRadius.circular(10.0),
        ),
      ),
    );
  }
}

In this example, the CropYourImage widget is created with an image to be cropped, an aspect ratio, and a border radius for the cropped image. The cropImage method is called when the crop button is pressed to retrieve the cropped image.

Step 4: Run the app:

Run your Flutter app to see the image cropping screen. You should be able to select an area of the image to crop.

 

Sample Code:


// ignore_for_file: sort_child_properties_last

import 'dart:typed_data';
import 'package:http/http.dart' as http;
import 'package:crop_your_image/crop_your_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show rootBundle;

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          centerTitle: true,
          elevation: 2,
          title: Text(
            "Crop Your Image",
            style: TextStyle(fontSize: 22, color: Colors.black, fontWeight: FontWeight.w500),
          ),
          backgroundColor: Colors.blue[200],
        ),
        // appBar: AppBar(
        //   title: Text('Crop Your Image Demo'),
        // ),
        body: CropSample(),
      ),
    );
  }
}

class CropSample extends StatefulWidget {
  @override
  _CropSampleState createState() => _CropSampleState();
}

class _CropSampleState extends State<CropSample> {
  static const _images = const [
    'https://media.istockphoto.com/id/1464634920/photo/woman-sits-by-lake-in-glacier-national-park.jpg?s=2048x2048&w=is&k=20&c=oM5rATfC-TeSZAXN9TuL5iuT6wi3ubsZlgqd3XLdZsY=',
    'https://images.freeimages.com/variants/DVg6TTGcRiJSdhEbY212DbAu/f4a36f6589a0e50e702740b15352bc00e4bfaf6f58bd4db850e167794d05993d?fmt=webp&h=350',
    'https://media.istockphoto.com/id/666066516/photo/rock-band-performs-on-stage-guitarist-bass-guitar-and-drums.jpg?s=2048x2048&w=is&k=20&c=NqfTXWJrlbyL79ug5qmrRJCRop8A96XDK-tfqQ6MUU4=',
    'https://images.freeimages.com/images/large-previews/aed/three-bees-on-sunflower-1337029.jpg?fmt=webp&w=500',
  ];

  final _cropController = CropController();
  final _imageDataList = <Uint8List>[];

  var _loadingImage = false;
  var _currentImage = 0;
  set currentImage(int value) {
    setState(() {
      _currentImage = value;
    });
    _cropController.image = _imageDataList[_currentImage];
  }

  var _isSumbnail = false;
  var _isCropping = false;
  var _isCircleUi = false;
  Uint8List? _croppedData;
  var _statusText = '';

  @override
  void initState() {
    _loadAllImages();
    super.initState();
  }

  Future<void> _loadAllImages() async {
    setState(() {
      _loadingImage = true;
    });
    for (final assetName in _images) {
      _imageDataList.add(await _load(assetName));
    }
    setState(() {
      _loadingImage = false;
    });
  }

  Future<Uint8List> _load(String imageUrl) async {
    final response = await http.get(Uri.parse(imageUrl));
    if (response.statusCode == 200) {
      return response.bodyBytes;
    } else {
      throw Exception('Failed to load image: $imageUrl');
    }
  }
  // Future<Uint8List> _load(String assetName) async {
  //   final assetData = await rootBundle.load(assetName);
  //   return assetData.buffer.asUint8List();
  // }

  @override
  Widget build(BuildContext context) {
    return Container(
      width: double.infinity,
      height: double.infinity,
      child: Center(
        child: Visibility(
          visible: !_loadingImage && !_isCropping,
          child: Column(
            children: [
              if (_imageDataList.length >= 4)
                Padding(
                  padding: const EdgeInsets.all(16),
                  child: Row(
                    children: [
                      _buildSumbnail(_imageDataList[0]),
                      const SizedBox(width: 16),
                      _buildSumbnail(_imageDataList[1]),
                      const SizedBox(width: 16),
                      _buildSumbnail(_imageDataList[2]),
                      const SizedBox(width: 16),
                      _buildSumbnail(_imageDataList[3]),
                    ],
                  ),
                ),
              Expanded(
                child: Visibility(
                  visible: _croppedData == null,
                  child: Stack(
                    children: [
                      if (_imageDataList.isNotEmpty) ...[
                        Crop(
                          willUpdateScale: (newScale) => newScale < 5,
                          controller: _cropController,
                          image: _imageDataList[_currentImage],
                          onCropped: (croppedData) {
                            setState(() {
                              _croppedData = croppedData;
                              _isCropping = false;
                            });
                          },
                          withCircleUi: _isCircleUi,
                          onStatusChanged: (status) => setState(() {
                            _statusText = <CropStatus, String>{
                                  CropStatus.nothing: 'Crop has no image data',
                                  CropStatus.loading: 'Crop is now loading given image',
                                  CropStatus.ready: 'Crop is now ready!',
                                  CropStatus.cropping: 'Crop is now cropping image',
                                }[status] ??
                                '';
                          }),
                          initialSize: 0.5,
                          maskColor: _isSumbnail ? Colors.white : null,
                          cornerDotBuilder: (size, edgeAlignment) => const SizedBox.shrink(),
                          interactive: true,
                          fixCropRect: true,
                          radius: 20,
                          initialRectBuilder: (viewportRect, imageRect) {
                            return Rect.fromLTRB(
                              viewportRect.left + 24,
                              viewportRect.top + 24,
                              viewportRect.right - 24,
                              viewportRect.bottom - 24,
                            );
                          },
                        ),
                        IgnorePointer(
                          child: Padding(
                            padding: const EdgeInsets.all(24),
                            child: Container(
                              decoration: BoxDecoration(
                                border: Border.all(width: 4, color: Colors.white),
                                borderRadius: BorderRadius.circular(20),
                              ),
                            ),
                          ),
                        ),
                      ],
                      Positioned(
                        right: 16,
                        bottom: 16,
                        child: GestureDetector(
                          onTapDown: (_) => setState(() => _isSumbnail = true),
                          onTapUp: (_) => setState(() => _isSumbnail = false),
                          child: CircleAvatar(
                            backgroundColor: _isSumbnail ? Colors.blue.shade50 : Colors.blue,
                            child: Center(
                              child: Icon(Icons.crop_free_rounded),
                            ),
                          ),
                        ),
                      ),
                    ],
                  ),
                  replacement: Center(
                    child: _croppedData == null ? SizedBox.shrink() : Image.memory(_croppedData!),
                  ),
                ),
              ),
              if (_croppedData == null)
                Padding(
                  padding: const EdgeInsets.all(16),
                  child: Column(
                    children: [
                      Row(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          IconButton(
                            icon: Icon(Icons.crop_7_5),
                            onPressed: () {
                              _isCircleUi = false;
                              _cropController.aspectRatio = 16 / 4;
                            },
                          ),
                          IconButton(
                            icon: Icon(Icons.crop_16_9),
                            onPressed: () {
                              _isCircleUi = false;
                              _cropController.aspectRatio = 16 / 9;
                            },
                          ),
                          IconButton(
                            icon: Icon(Icons.crop_5_4),
                            onPressed: () {
                              _isCircleUi = false;
                              _cropController.aspectRatio = 4 / 3;
                            },
                          ),
                          IconButton(
                            icon: Icon(Icons.crop_square),
                            onPressed: () {
                              _isCircleUi = false;
                              _cropController
                                ..withCircleUi = false
                                ..aspectRatio = 1;
                            },
                          ),
                          IconButton(
                              icon: Icon(Icons.circle),
                              onPressed: () {
                                _isCircleUi = true;
                                _cropController.withCircleUi = true;
                              }),
                        ],
                      ),
                      const SizedBox(height: 16),
                      Container(
                        width: double.infinity,
                        child: ElevatedButton(
                          onPressed: () {
                            setState(() {
                              _isCropping = true;
                              print("hello");
                            });
                            _isCircleUi ? _cropController.cropCircle() : _cropController.crop();
                          },
                          child: Padding(
                            padding: const EdgeInsets.symmetric(vertical: 16),
                            child: Text('CROP IT!'),
                          ),
                        ),
                      ),
                      const SizedBox(height: 40),
                    ],
                  ),
                ),
              const SizedBox(height: 16),
              Text(_statusText),
              const SizedBox(height: 16),
            ],
          ),
          replacement: const CircularProgressIndicator(),
        ),
      ),
    );
  }

  Expanded _buildSumbnail(Uint8List data) {
    final index = _imageDataList.indexOf(data);
    return Expanded(
      child: InkWell(
        onTap: () {
          _croppedData = null;
          currentImage = index;
        },
        child: Container(
          height: 100,
          decoration: BoxDecoration(
            border: index == _currentImage
                ? Border.all(
                    width: 8,
                    color: Colors.blue,
                  )
                : null,
          ),
          child: Image.memory(
            data,
            fit: BoxFit.cover,
          ),
        ),
      ),
    );
  }
}

Output:

how to implement an image cropping in flutter using crop your image package
how to implement an image cropping in flutter using crop your image package

Conclusion:

By following these steps, you can easily implement image cropping in Flutter using the crop_your_image package. This allows you to add image editing functionality to your app, such as cropping profile pictures or resizing images.

 

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *