Photo Editing Application in Flutter
Last Updated :
09 Apr, 2025
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:
Similar Reads
Flutter Tutorial This Flutter Tutorial is specifically designed for beginners and experienced professionals. It covers both the basics and advanced concepts of the Flutter framework.Flutter is Googleâs mobile SDK that builds native Android and iOS apps from a single codebase. It was developed in December 2017. When
7 min read
Top 50 Flutter Interview Questions and Answers for 2025 Flutter is an open-source, cross-platform application development framework. It was developed by Google in 2017. It is used to build applications for Android, iOS, Linux, Mac, Windows, and the web. Flutter uses the Dart programming language. It provides a simple, powerful, efficient, and easy-to-und
15+ min read
What is Widgets in Flutter? Flutter is Google's UI toolkit for crafting beautiful, natively compiled iOS and Android apps from a single code base. To build any application we start with widgets - The building block of Flutter applications. Widgets describe what their view should look like given their current configuration and
5 min read
Flutter | An introduction to the open source SDK by Google Flutter is Googleâs Mobile SDK to build native iOS and Android, Desktop (Windows, Linux, macOS), and Web apps from a single codebase. When building applications with Flutter, everything is Widgets â the blocks with which the flutter apps are built. They are structural elements that ship with a bunch
5 min read
Flutter - Architecture Application Flutter architecture application mainly consists of: WidgetsGesturesConcept of StateLayersWidgetsWidgets are the primary component of any flutter application. It acts as a UI for the user to interact with the application. Any flutter application is itself a widget that is made up of a combination of
3 min read
Flutter - Changing App Icon Flutter SDK is an open-source software development kit for building beautiful UI which is natively compiled. When we create a Flutter Project, it comes with the default Flutter icon. In order to get the app published in stores like Google Play Store, Apple App Store, etc the default icon can be chan
3 min read
Flutter - AppBar Widget AppBar is usually the topmost component of the app (or sometimes the bottom-most), it contains the toolbar and some other common action buttons. As all the components in a Flutter application are a widget or a combination of widgets. So AppBar is also a built-in class or widget in Flutter which give
7 min read
Scaffold class in Flutter with Examples The Scaffold is a class in flutter that provides many widgets or we can say APIs. The Scaffold will expand or occupy the whole available space in device screen .The class Hierarchy is as follows:Object â³ Diagnosticable â³ Diagnosticable Tree â³ Widget â³ StateFul Widget â³ ScaffoldThe constructor of the
8 min read
Container class in Flutter Container class in flutter is a convenience widget that combines common painting, positioning, and sizing of widgets. A Container class can be used to store one or more widgets and position them on the screen according to our convenience. Basically, a container is like a box to store contents. A bas
8 min read
Flutter - Stateful vs Stateless Widgets The state of an app can very simply be defined as anything that exists in the memory of the app while the app is running. This includes all the widgets that maintain the UI of the app including the buttons, text fonts, icons, animations, etc. So now that we know what are these states let's dive dire
6 min read