memory_image_cropper 1.0.2
memory_image_cropper: ^1.0.2 copied to clipboard
A Flutter plugin for cropping images entirely in memory without creating files on disk. Supports Android and iOS. No temporary files created - fully compliant for sensitive data handling.
Memory Image Cropper #
A Flutter plugin for cropping images entirely in memory without creating files on disk. Designed for compliance-sensitive applications where writing image data to storage is not permitted.
Features #
✅ No files created on disk - All operations are performed in memory
✅ Pure Dart implementation - Cropping uses Flutter's Canvas API
✅ Android & iOS support
✅ Multiple crop shapes - Rectangle, Circle, Square, Custom Ratio
✅ Customizable UI - Colors, grid, borders, toolbar
✅ Gesture support - Pan, zoom, resize crop area
✅ Rotation support - 90° left/right rotation
✅ Returns Uint8List - Ready for upload or display
Installation #
Add to your pubspec.yaml:
dependencies:
memory_image_cropper:
path: ./memory_image_cropper # or publish to pub.dev
Usage #
Basic Usage (Dialog) #
import 'package:memory_image_cropper/memory_image_cropper.dart';
// Your image bytes (from camera, gallery, network, etc.)
Uint8List imageBytes = await getImageBytes();
// Show crop dialog
CropResult? result = await MemoryImageCropperPlugin.cropImage(
context,
imageBytes: imageBytes,
shape: CropShape.rectangle,
title: 'Crop Image',
toolbarColor: Color(0xFF97144D),
);
if (result != null) {
// Use cropped bytes directly - NO FILE CREATED!
Uint8List croppedBytes = result.bytes;
// Display
Image.memory(croppedBytes);
// Or upload directly
await uploadToServer(croppedBytes);
}
Full Screen Cropper #
CropResult? result = await MemoryImageCropperPlugin.cropImageFullScreen(
context,
imageBytes: imageBytes,
shape: CropShape.circle,
aspectRatio: CropAspectRatio.square,
maxWidth: 1024,
maxHeight: 1024,
);
Using the Widget Directly #
final controller = CropperController();
// Load image
await controller.loadImage(imageBytes);
// In your widget tree
MemoryImageCropper(
imageBytes: imageBytes,
controller: controller,
shape: CropShape.rectangle,
aspectRatio: CropAspectRatio.ratio16x9,
showGrid: true,
borderColor: Colors.white,
overlayColor: Colors.black54,
)
// Crop when ready
CropResult? result = await controller.cropImage(
maxWidth: 1024,
maxHeight: 1024,
);
Controller Methods #
final controller = CropperController();
// Load image
await controller.loadImage(imageBytes);
// Rotation
controller.rotateLeft(); // Rotate 90° counter-clockwise
controller.rotateRight(); // Rotate 90° clockwise
// Zoom
controller.zoomIn();
controller.zoomOut();
// Reset all transformations
controller.reset();
// Get cropped image
CropResult? result = await controller.cropImage();
Crop Shapes #
CropShape.rectangle // Free form rectangle
CropShape.circle // Circular crop (1:1 aspect)
CropShape.square // Square crop (1:1 aspect)
CropShape.ratio // Custom aspect ratio
Aspect Ratios #
CropAspectRatio.square // 1:1
CropAspectRatio.ratio16x9 // 16:9
CropAspectRatio.ratio9x16 // 9:16
CropAspectRatio.ratio4x3 // 4:3
CropAspectRatio.ratio3x4 // 3:4
CropAspectRatio.ratio3x2 // 3:2
CropAspectRatio.ratio2x3 // 2:3
// Custom
CropAspectRatio(width: 5, height: 4)
CropResult #
class CropResult {
final Uint8List bytes; // Cropped image bytes (PNG format)
final int width; // Width in pixels
final int height; // Height in pixels
bool get isValid; // Check if result is valid
int get sizeInBytes; // Size in bytes
double get sizeInKB; // Size in KB
double get sizeInMB; // Size in MB
}
Customization Options #
MemoryImageCropperPlugin.cropImage(
context,
imageBytes: imageBytes,
// Shape
shape: CropShape.rectangle,
aspectRatio: CropAspectRatio.ratio16x9,
// UI Colors
toolbarColor: Color(0xFF97144D),
toolbarWidgetColor: Colors.white,
backgroundColor: Colors.black,
overlayColor: Color(0x80000000),
// Grid
showGrid: true,
// Output size limits
maxWidth: 1024,
maxHeight: 1024,
// Dialog behavior
barrierDismissible: false,
title: 'Crop Image',
);
Integration with Your Existing Code #
Replace your UCrop implementation:
// OLD (UCrop - creates files)
File? croppedFile = await cropImageFile(sourceFile);
Uint8List bytes = await croppedFile.readAsBytes();
// NEW (MemoryImageCropper - no files)
Uint8List sourceBytes = await sourceFile.readAsBytes();
CropResult? result = await MemoryImageCropperPlugin.cropImage(
context,
imageBytes: sourceBytes,
);
Uint8List croppedBytes = result!.bytes;
For Your Gold Loan App #
// In your captureOrnamentPhoto method:
Future<Uint8List?> captureAndCropOrnament() async {
// Capture image (returns bytes, not file)
final XFile? photo = await picker.pickImage(source: ImageSource.camera);
if (photo == null) return null;
final Uint8List imageBytes = await photo.readAsBytes();
// Crop in memory (NO FILE CREATED)
final CropResult? result = await MemoryImageCropperPlugin.cropImage(
context,
imageBytes: imageBytes,
shape: CropShape.rectangle,
toolbarColor: const Color(0xFF97144D),
maxWidth: 1024,
maxHeight: 1024,
);
if (result == null) return null;
// Return bytes directly for upload
return result.bytes;
}
Compliance Benefits #
| Feature | UCrop | MemoryImageCropper |
|---|---|---|
| Creates temp files | ✅ Yes | ❌ No |
| Writes to disk | ✅ Yes | ❌ No |
| Data in memory only | ❌ No | ✅ Yes |
| Work profile safe | ❌ Issues | ✅ Safe |
| Compliance friendly | ❌ No | ✅ Yes |
License #
MIT License
Author #
Created for compliance-sensitive Flutter applications.