Flutter - Build an Image Compressor App
Last Updated :
04 May, 2025
Many applications accept images of small size, to reduce image size we use different online applications to compress images while maintaining their quality. In this article, we will create an image compressor app in Flutter that compresses images with the help of available libraries in Flutter.
Step-by-Step Implementation
Step 1: Create a new Flutter Application
Create a new Flutter application using the command Prompt. To create a new app, write the following 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
To add the dependency to the pubspec.yaml file, add image_picker, flutter_image_compress, and path_provider as dependencies in the dependencies part of the pubspec.yaml file, as shown below:
Dart
dependencies:
flutter:
sdk: flutter
image_picker: ^1.1.2
flutter_image_compress: ^2.3.0
path_provider: ^2.1.5
Now run the below command in the terminal.
flutter pub get
Or
Run the below command in the terminal.
flutter pub add flutter_image_compress image_picker path_provider
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:path_provider/path_provider.dart';
import 'package:flutter_image_compress/flutter_image_compress.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:path_provider/path_provider.dart';
import 'package:flutter_image_compress/flutter_image_compress.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: ImageCompressorApp(),
debugShowCheckedModeBanner: false,
);
}
}
// This is the main widget of the app.
class ImageCompressorApp extends StatefulWidget {
@override
_ImageCompressorAppState createState() => _ImageCompressorAppState();
}
// This is the state class for the main widget.
class _ImageCompressorAppState extends State<ImageCompressorApp> {
// This function builds the user interface.
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('GFG Image Compression'),
// Set app bar color.
backgroundColor: Colors.green,
// Set text color
foregroundColor: Colors.white,
),
body: SingleChildScrollView(
// Code Here
),
);
}
}
Step 5 : Initialize variables
Intialize required variables.
Dart
// Stores the original image.
File? _selectedImage;
// Stores the compressed image.
File? _compressedImage;
// Checks if compression is in progress.
bool _isCompressing = false;
// Stores error messages.
String? _error;
Step 6 : Create methods
Create methods to select an image from the gallery and compress it using the image_picker and flutter_image_compress packages.
Dart
// Function to pick an image from the gallery.
Future<void> pickImage() async {
try {
final picker = ImagePicker();
final pickedFile = await picker.pickImage(source: ImageSource.gallery);
if (pickedFile != null) {
setState(() {
// Store the selected image.
_selectedImage = File(pickedFile.path);
// Reset previous compressed image.
_compressedImage = null;
// Clear any previous error.
_error = null;
// Show that compression is starting.
_isCompressing = true;
});
// Compress the selected image.
await compressImage(_selectedImage!);
}
} catch (e) {
setState(() {
// Store error message.
_error = 'Error picking image: $e';
// Stop compressing state.
_isCompressing = false;
});
}
}
// Function to compress the selected image.
Future<void> compressImage(File image) async {
try {
// Get a temporary directory to store the compressed image.
final tempDir = await getTemporaryDirectory();
final targetPath = '${tempDir.path}/compressed_image.jpg';
// Compress the image and store it in the new location.
var result = await FlutterImageCompress.compressAndGetFile(
image.absolute.path,
targetPath,
// Set image quality (lower value = more compression).
quality: 85,
);
if (result != null) {
final compressedFile = File(result.path);
if (await compressedFile.exists()) {
final originalSize = await image.length();
final compressedSize = await compressedFile.length();
setState(() {
// Save the compressed image.
_compressedImage = compressedFile;
// Compression is done.
_isCompressing = false;
// Clear any error messages.
_error = null;
});
// Print the sizes of original and compressed images.
print('Original size: ${(originalSize / 1024).toStringAsFixed(2)} KB');
print('Compressed size: ${(compressedSize / 1024).toStringAsFixed(2)} KB');
} else {
throw Exception('Compressed file not found at path: $targetPath');
}
} else {
throw Exception('Compression returned null path');
}
} catch (e) {
setState(() {
// Store error message.
_error = 'Error compressing image: $e';
// Stop compressing state.
_isCompressing = false;
});
print('Error compressing image: $e');
}
}
Step 7 : Develop UI
- ElevatedButton : Used to select images from the gallery.
Dart
// Button to pick and compress an image.
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.green,
foregroundColor: Colors.white
),
onPressed: _isCompressing
? null
: pickImage, // Disable when compressing.
child: Text(_isCompressing
? 'Compressing...' // Show progress message.
: 'Pick and Compress Image'),
),
- Error Container : Display the error wrapped in a container for the user.
Dart
if (_error != null) ...[
// Show error message if any.
const SizedBox(height: 16),
Container(
padding: const EdgeInsets.all(8),
// Background color for error message.
color: Colors.red.shade100,
child: Text(
_error!,
// Red text color.
style: const TextStyle(color: Colors.red),
),
),
],
- Original & Compressed Image : Display both the original and compressed image files using the Image.file() widget.
Dart
if (_selectedImage != null) ...[
// Show original image.
const SizedBox(height: 16),
const Text(
'Original Image',
style:TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold
),
),
const SizedBox(height: 8),
Image.file(_selectedImage!),
],
if (_compressedImage != null) ...[
// Show compressed image.
const SizedBox(height: 16),
const Text(
'Compressed Image',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold
),
),
const SizedBox(height: 8),
Image.file(_compressedImage!),
]
- Show values : Display the original image size, compressed image size, and the percentage reduction using the code below.
Dart
// Show original and compressed image sizes.
FutureBuilder<List<int>>(
future: Future.wait([
_selectedImage!.length(),
_compressedImage!.length(),
]),
builder: (context, snapshot) {
if (snapshot.hasData) {
final originalSize = snapshot.data![0] / 1024;
final compressedSize = snapshot.data![1] / 1024;
final savings =((originalSize - compressedSize) / originalSize * 100);
return Padding(
padding: const EdgeInsets.only(top: 8),
child: Text(
'Original: ${originalSize.toStringAsFixed(2)} KB\n'
'Compressed: ${compressedSize.toStringAsFixed(2)} KB\n'
'Reduced by: ${savings.toStringAsFixed(1)}%',
style: const TextStyle(fontSize: 14),
),
);
}
// Return empty widget if no data.
return const SizedBox();
},
),
Complete Source Code
main.dart:
Dart
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:flutter_image_compress/flutter_image_compress.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path_provider/path_provider.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: ImageCompressorApp(),
debugShowCheckedModeBanner: false,
);
}
}
// This is the main widget of the app.
class ImageCompressorApp extends StatefulWidget {
@override
_ImageCompressorAppState createState() => _ImageCompressorAppState();
}
// This is the state class for the main widget.
class _ImageCompressorAppState extends State<ImageCompressorApp> {
// Stores the original image.
File? _selectedImage;
// Stores the compressed image.
File? _compressedImage;
// Checks if compression is in progress.
bool _isCompressing = false;
// Stores error messages.
String? _error;
// Function to pick an image from the gallery.
Future<void> pickImage() async {
try {
final picker = ImagePicker();
final pickedFile = await picker.pickImage(source: ImageSource.gallery);
if (pickedFile != null) {
setState(() {
// Store the selected image.
_selectedImage = File(pickedFile.path);
// Reset previous compressed image.
_compressedImage = null;
// Clear any previous error.
_error = null;
// Show that compression is starting.
_isCompressing = true;
});
// Compress the selected image.
await compressImage(_selectedImage!);
}
} catch (e) {
setState(() {
// Store error message.
_error = 'Error picking image: $e';
// Stop compressing state.
_isCompressing = false;
});
}
}
// Function to compress the selected image.
Future<void> compressImage(File image) async {
try {
// Get a temporary directory to store the compressed image.
final tempDir = await getTemporaryDirectory();
final targetPath = '${tempDir.path}/compressed_image.jpg';
// Compress the image and store it in the new location.
var result = await FlutterImageCompress.compressAndGetFile(
image.absolute.path,
targetPath,
// Set image quality (lower value = more compression).
quality: 85,
);
if (result != null) {
final compressedFile = File(result.path);
if (await compressedFile.exists()) {
final originalSize = await image.length();
final compressedSize = await compressedFile.length();
setState(() {
// Save the compressed image.
_compressedImage = compressedFile;
// Compression is done.
_isCompressing = false;
// Clear any error messages.
_error = null;
});
// Print the sizes of original and compressed images.
print(
'Original size: ${(originalSize / 1024).toStringAsFixed(2)} KB');
print(
'Compressed size: ${(compressedSize / 1024).toStringAsFixed(2)} KB');
} else {
throw Exception('Compressed file not found at path: $targetPath');
}
} else {
throw Exception('Compression returned null path');
}
} catch (e) {
setState(() {
// Store error message.
_error = 'Error compressing image: $e';
// Stop compressing state.
_isCompressing = false;
});
print('Error compressing image: $e');
}
}
// This function builds the user interface.
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('GFG Image Compression'),
// Set app bar color.
backgroundColor: Colors.green,
// Set text color
foregroundColor: Colors.white,
),
body: SingleChildScrollView(
// Add padding around the content.
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// Button to pick and compress an image.
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.green, foregroundColor: Colors.white),
onPressed: _isCompressing
? null
: pickImage, // Disable when compressing.
child: Text(_isCompressing
? 'Compressing...' // Show progress message.
: 'Pick and Compress Image'),
),
if (_error != null) ...[
// Show error message if any.
const SizedBox(height: 16),
Container(
padding: const EdgeInsets.all(8),
// Background color for error message.
color: Colors.red.shade100,
child: Text(
_error!,
// Red text color.
style: const TextStyle(color: Colors.red),
),
),
],
if (_selectedImage != null) ...[
// Show original image.
const SizedBox(height: 16),
const Text(
'Original Image',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
Image.file(_selectedImage!),
],
if (_compressedImage != null) ...[
// Show compressed image.
const SizedBox(height: 16),
const Text(
'Compressed Image',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
Image.file(_compressedImage!),
// Show original and compressed image sizes.
FutureBuilder<List<int>>(
future: Future.wait([
_selectedImage!.length(),
_compressedImage!.length(),
]),
builder: (context, snapshot) {
if (snapshot.hasData) {
final originalSize = snapshot.data![0] / 1024;
final compressedSize = snapshot.data![1] / 1024;
final savings =
((originalSize - compressedSize) / originalSize * 100);
return Padding(
padding: const EdgeInsets.only(top: 8),
child: Text(
'Original: ${originalSize.toStringAsFixed(2)} KB\n'
'Compressed: ${compressedSize.toStringAsFixed(2)} KB\n'
'Reduced by: ${savings.toStringAsFixed(1)}%',
style: const TextStyle(fontSize: 14),
),
);
}
// Return empty widget if no data.
return const SizedBox();
},
),
],
],
),
),
);
}
}
Output:
Similar Reads
Flutter - AnimatedBuilder Widget
The AnimatedBuilder widget in Flutter is a powerful utility widget that is used for creating complex animations by rebuilding a part of the widget tree in response to changes in an animation's value. It is especially useful when you want to animate properties of child widgets that cannot be directly
4 min read
Flutter - Blurred Decoration Image
In this article, we will implement how to Blur an image in flutter. A sample image is given below to get an idea about what we are going to do in this article. Â Step By Step Implementation Step 1: Create a New Project in Android Studio To set up Flutter Development on Android Studio please refer to
3 min read
Flutter - Magic 8 Ball App
We will be building a Magic 8-Ball app that will give you the answers to all fun, tricky questions (basically, it is a fun game app that will change its state of image using Textbutton in Stateful widgets). For this, we will use Stateless and Stateful Flutter widgets and a Textbutton. Steps to build
3 min read
Building eCommerce applications with Flutter
Flutter uses the Dart programming language and allows developers to build high-performance, visually attractive mobile applications for both iOS and Android platforms from a single codebase.Flutter is a powerful cross-platform development framework that enables building native-looking apps for both
8 min read
Flutter - Asset Image
Flutter is an open-source, cross-platform UI development kit developed by Google. It is gaining popularity these days, as the app made in Flutter can run on various devices regardless of their platform. It is majorly used to develop applications for Android and iOS, as a single app made in Flutter c
2 min read
Fitness App using Flutter
The Fitness app is an essential companion for fitness enthusiasts who want to keep track of their exercises. In this article, we will learn how to build a Fitness App using Flutter for mobile devices. The app features a list of common exercises, allowing users to start and record the time spent on e
10 min read
How to Build a Video Calling App in Flutter?
Video Calling has become a necessary feature in most real-time communication applications used around the world. Its primary application is to connect people from all around the world along with other obvious applications. Chat applications like Facebook, WhatsApp, and Instagram all have video calli
4 min read
Advanced Calculator App using Flutter
Flutter SDK is an open-source software development kit for building beautiful UI which is natively compiled. In this article, we are going to create an advanced calculator app by using some advanced packages available in Flutter. In this app, you get some functionality. In this app you have only one
8 min read
Flutter - SVG Image as Button
In this article, we will see how to make the SVG image a button in Flutter so that we can perform actions. A sample video is given below to get an idea about what we are going to do in this article. How to Use? You can use the Gesture Detector to add click functionality to any Widget in Flutter. Dar
2 min read
Mask Detection App in Flutter
Nowadays in the situation of Covid, it is very important to wear a Mask and protect yourself and others. So this App helps to detect whether the person has worn the Mask or Not. In this Application, the Mask detection is done with the help of TensorFlow Lite. Follow the steps to implement Mask Detec
7 min read