Open In App

Photo Editing Application in Flutter

Last Updated : 09 Apr, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

With the introduction of the powerful image_editor_plus package, editing images directly within your Flutter app has become significantly more accessible. In this article, we’ll dive deep into building a user-friendly image editor app. Users will have the ability to select an image from their camera or gallery, allowing for versatility based on their preferences. Once an image is chosen, they can utilize the built-in UI to explore a range of editing features, such as cropping, adjusting brightness, applying filters, and more. Finally, users will be able to preview and save their edited images, providing a complete and satisfying experience from start to finish.

Steps to Create a Photo-Editing Application in Flutter

Step 1 : Create a New Flutter Application

Create a new Flutter application using the command Prompt. To create a new app, write the below command and run it.

flutter create app_name

To know more about it refer this article: Creating a Simple Application in Flutter

Step 2 : Adding the Dependency

Packages Used: We’re using the following Flutter packages:

Package

Purpose

image_picker

To pick images from the camera or gallery

image_editor_plus

Provides a full-featured editor UI

path_provider

To save edited images in a temporary folder

permission_handler

Handles runtime permissions

To add the dependency to the pubspec.yaml file, add image_picker, image_editor_plus, path_provider, and permission_handler as a dependency in the dependencies part of the pubspec.yaml file, as shown below:

Dart
dependencies:
    flutter:
        sdk: flutter
    image_editor_plus: ^1.0.6
    image_picker: ^1.1.2
    path_provider: ^2.1.5
    permission_handler: ^11.4.0


Now run the below command in the terminal.

flutter pub get

Or

Run the below command in the terminal.

flutter pub add image_picker image_editor_plus path_provider permission_handler


Step 3 : Import dependencies

To use libraries, import all of them in the main.dart file,

import 'package:image_picker/image_picker.dart';
import 'package:image_editor_plus/image_editor_plus.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';


Step 4 : Working With main.dart

Add the boilerplate code below in main.dart to create a basic structure with an AppBar and body using a Scaffold.

Dart
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:image_editor_plus/image_editor_plus.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';

// Entry point of the application
void main() {
    runApp(const MyApp());
}

// Root widget of the application
class MyApp extends StatelessWidget {
    const MyApp({super.key});
    
    @override
    Widget build(BuildContext context) {
        return MaterialApp(
            home: PhotoEditorApp(),
            
            // Disable debug banner
            debugShowCheckedModeBanner: false, 
        );
    }
}

// Stateful widget for the photo editor app
class PhotoEditorApp extends StatefulWidget {
    const PhotoEditorApp({Key? key}) : super(key: key);
    
    @override
    State<PhotoEditorApp> createState() => _PhotoEditorAppState();
}

class _PhotoEditorAppState extends State<PhotoEditorApp> {
  
    @override
    Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(
                title: const Text("Image Editor Plus"), 
                backgroundColor: Colors.green, 
                foregroundColor: Colors.white, 
            ),
            body: Center(
                child: // Code Here
            ),
        );
    }
}


Step 5 : Initialize variables

Intialize required variables.

Dart
// Holds the edited image file
File? _editedImage; 


Step 6 : Create methods

Create a method to pick an image from the specified source and edit it using the image_picker and image_editor_plus packages.

Dart
// Function to pick an image from the specified source and edit it
Future<void> _pickAndEditImage(ImageSource source) async {
    // Request necessary permissions
    await Permission.photos.request();
    await Permission.camera.request();
    await Permission.storage.request();
    
    // Pick an image using the ImagePicker
    final pickedFile = await ImagePicker().pickImage(source: source);
    
    // If no image is selected, return
    if (pickedFile == null) return;
    
    final imageFile = File(pickedFile.path);
    
    // Open the image editor
    final editedImage = await Navigator.push(
        context,
        MaterialPageRoute(
            builder: (context) => ImageEditor(image: imageFile.readAsBytesSync()),
        ),
    );
    
    // If an edited image is returned, save it to a temporary directory
    if (editedImage != null) {
        final tempDir = await getTemporaryDirectory();
        final filePath = '${tempDir.path}/edited_${DateTime.now().millisecondsSinceEpoch}.png';
        final file = File(filePath);
        await file.writeAsBytes(editedImage);
        
        // Update the state with the edited image
        setState(() {
            _editedImage = file;
        });
        
        // Show a success message
        ScaffoldMessenger.of(context).showSnackBar(
            const SnackBar(content: Text('Image Edited Successfully')),
        );
    }
}


Step 7 : Develop UI

– ElevatedButton : Used to select images from the camera and gallery.

Dart
// Button to edit an image from the camera
ElevatedButton.icon(
    style: ElevatedButton.styleFrom(
        
                // Button background color
                backgroundColor: Colors.green, 
                
                // Button text/icon color
                foregroundColor: Colors.white, 
           ),
           
    // Camera icon
    icon: const Icon(Icons.camera_alt), 
    
    // Button label
    label: const Text("Edit from Camera"), 
    onPressed: () => _pickAndEditImage(ImageSource.camera),
),


// Button to edit an image from the gallery
ElevatedButton.icon(
    style: ElevatedButton.styleFrom(
        
                // Button background color
                backgroundColor: Colors.green, 
                
                // Button text/icon color
                foregroundColor: Colors.white, 
           ),
           
    // Gallery icon
    icon: const Icon(Icons.photo_library), 
    
    // Button label
    label: const Text("Edit from Gallery"), 
    onPressed: () => _pickAndEditImage(ImageSource.gallery),
),


– Image.file() : Display the edited image if available.

Dart
// Display the edited image if available
if (_editedImage != null) Image.file(_editedImage!, height: 300),


– Column :  It is used to arrange its child widgets like Image.file() and two ElevatedButtons vertically in a single column.

Dart
Column(
    
    // Center the content
    mainAxisAlignment: MainAxisAlignment.center, 
    children: [
        
        // Display the edited image if available
        if (_editedImage != null) Image.file(_editedImage!, height: 300),
        
        // Add spacing
        const SizedBox(height: 30), 
        
        // Button to edit an image from the camera
        ElevatedButton.icon(
            style: ElevatedButton.styleFrom(
                    backgroundColor: Colors.green, 
                    foregroundColor: Colors.white, 
                   ),
                   
            // Camera icon
            icon: const Icon(Icons.camera_alt), 
            
            // Button label
            label: const Text("Edit from Camera"), 
            onPressed: () => _pickAndEditImage(ImageSource.camera),
        ),
        
        // Add spacing
        const SizedBox(height: 10), 
        
        // Button to edit an image from the gallery
        ElevatedButton.icon(
            style: ElevatedButton.styleFrom(
                    backgroundColor: Colors.green, 
                    foregroundColor: Colors.white, 
                   ),
                   
            // Gallery icon
            icon: const Icon(Icons.photo_library), 
            
            // Button label
            label: const Text("Edit from Gallery"), 
            onPressed: () => _pickAndEditImage(ImageSource.gallery),
        ),
    ],
),


Complete Source Code

main.dart:

Dart
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:image_editor_plus/image_editor_plus.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';

// Entry point of the application
void main() {
    runApp(const MyApp());
}

// Root widget of the application
class MyApp extends StatelessWidget {
    const MyApp({super.key});
    
    @override
    Widget build(BuildContext context) {
        return MaterialApp(
            home: PhotoEditorApp(),
            
            // Disable debug banner
            debugShowCheckedModeBanner: false, 
        );
    }
}

// Stateful widget for the photo editor app
class PhotoEditorApp extends StatefulWidget {
    const PhotoEditorApp({Key? key}) : super(key: key);
    
    @override
    State<PhotoEditorApp> createState() => _PhotoEditorAppState();
}

class _PhotoEditorAppState extends State<PhotoEditorApp> {
    
    // Holds the edited image file
    File? _editedImage; 
    
    // Function to pick an image from
    // the specified source and edit it
    Future<void> _pickAndEditImage(ImageSource source) async {
        
        // Request necessary permissions
        await Permission.photos.request();
        await Permission.camera.request();
        await Permission.storage.request();
        
        // Pick an image using the ImagePicker
        final pickedFile = await ImagePicker().pickImage(source: source);
        
        // If no image is selected, return
        if (pickedFile == null) return;
        
        final imageFile = File(pickedFile.path);
        
        // Open the image editor
        final editedImage = await Navigator.push(
            context,
            MaterialPageRoute(
                builder: (context) => ImageEditor(image: imageFile.readAsBytesSync()),
            ),
        );
        
        // If an edited image is returned, save it to a temporary directory
        if (editedImage != null) {
            final tempDir = await getTemporaryDirectory();
            final filePath = '${tempDir.path}/edited_${DateTime.now().millisecondsSinceEpoch}.png';
            final file = File(filePath);
            await file.writeAsBytes(editedImage);
            
            // Update the state with the edited image
            setState(() {
                _editedImage = file;
            });
            
            // Show a success message
            ScaffoldMessenger.of(context).showSnackBar(
                const SnackBar(content: Text('Image Edited Successfully')),
            );
        }
    }
    
    @override
    Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(
                
                // App bar title
                title: const Text("Image Editor Plus"),
                
                // App bar background color
                backgroundColor: Colors.green, 
                
                // App bar text color
                foregroundColor: Colors.white, 
            ),
            body: Center(
                child: Column(
                    
                    // Center the content
                    mainAxisAlignment: MainAxisAlignment.center, 
                    children: [
                        
                        // Display the edited image if available
                        if (_editedImage != null) Image.file(_editedImage!, height: 300),
                        
                        // Add spacing
                        const SizedBox(height: 30), 
                        
                        // Button to edit an image from the camera
                        ElevatedButton.icon(
                            style: ElevatedButton.styleFrom(
                                        
                                        // Button background color
                                        backgroundColor: Colors.green, 
                                        
                                        // Button text/icon color
                                        foregroundColor: Colors.white, 
                                  ),
                                  
                            // Camera icon
                            icon: const Icon(Icons.camera_alt), 
                            
                            // Button label
                            label: const Text("Edit from Camera"), 
                            onPressed: () => _pickAndEditImage(ImageSource.camera),
                        ),
                        
                        // Add spacing
                        const SizedBox(height: 10), 
                        
                        // Button to edit an image from the gallery
                        ElevatedButton.icon(
                            style: ElevatedButton.styleFrom(
                                
                                    // Button background color
                                    backgroundColor: Colors.green, 
                                    
                                    // Button text/icon color
                                    foregroundColor: Colors.white, 
                                  ),
                                  
                            // Gallery icon
                            icon: const Icon(Icons.photo_library), 
                            
                            // Button label
                            label: const Text("Edit from Gallery"), 
                            onPressed: () => _pickAndEditImage(ImageSource.gallery),
                        ),
                    ],
                ),
            ),
        );
    }
}


Output:




Next Article
Article Tags :

Similar Reads