Let's say I have a rectangular, portrait image:
I'd like to crop it, such that it's rendered like this:
How can I do this in Flutter?
(I don't need to resize the image.)
(Image from https://flic.kr/p/nwXTDb)
Let's say I have a rectangular, portrait image:
I'd like to crop it, such that it's rendered like this:
How can I do this in Flutter?
(I don't need to resize the image.)
(Image from https://flic.kr/p/nwXTDb)
I would probably use a BoxDecoration
with a DecorationImage
. You can use the alignment
and fit
properties to determine how your image is cropped. You can use an AspectRatio
widget if you don't want to hard code a height on the Container
.
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(
home: new MyHomePage(),
));
}
class MyHomePage extends StatelessWidget {
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Image Crop Example"),
),
body: new Center(
child: new AspectRatio(
aspectRatio: 487 / 451,
child: new Container(
decoration: new BoxDecoration(
image: new DecorationImage(
fit: BoxFit.fitWidth,
alignment: FractionalOffset.topCenter,
image: new NetworkImage('https://i.stack.imgur.com/lkd0a.png'),
)
),
),
),
),
);
}
}
You can also directly use the Image class with BoxFit and do something like:
new Image.asset(
stringToImageLocation,
fit: BoxFit.cover,
)
Provide a fit
factor to your Image
widget and then wrap it in AspectRatio
.
AspectRatio(
aspectRatio: 1.5,
child: Image.asset(
'your_image_asset',
fit: BoxFit.cover,
),
)
Take a look to brendan-duncan/image, it's platform-independent library to manipulate images in Dart.
You can use the function:
Image copyCrop(Image src, int x, int y, int w, int h);
Worked for me using just these 2 properties:
CachedNetworkImage(
fit: BoxFit.cover,// OR BoxFit.fitWidth
alignment: FractionalOffset.topCenter,
....
)
There is a new package called ImageCropper
. I would recommend everyone to use this instead as it has many features and makes everything easier. It allows you to crop the image to any or specified aspect ratio you want and can even compress the image. Here is the link to the package: https://pub.dev/packages/image_cropper
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:image_cropper/image_cropper.dart';
class MyPage extends StatefulWidget {
@override
_MyPageState createState() => _MyPageState();
}
class _MyPageState extends State<MyPage> {
/// Variables
File imageFile;
/// Widget
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Color(0XFF307777),
title: Text("Image Cropper"),
),
body: Container(
child: imageFile == null
? Container(
alignment: Alignment.center,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
color: Color(0XFF307777),
onPressed: () {
_getFromGallery();
},
child: Text(
"PICK FROM GALLERY",
style: TextStyle(color: Colors.white),
),
),
],
),
)
: Container(
child: Image.file(
imageFile,
fit: BoxFit.cover,
),
)));
}
/// Get from gallery
_getFromGallery() async {
PickedFile pickedFile = await ImagePicker().getImage(
source: ImageSource.gallery,
maxWidth: 1800,
maxHeight: 1800,
);
_cropImage(pickedFile.path);
}
/// Crop Image
_cropImage(filePath) async {
File croppedImage = await ImageCropper.cropImage(
sourcePath: filePath,
maxWidth: 1080,
maxHeight: 1080,
);
if (croppedImage != null) {
imageFile = croppedImage;
setState(() {});
}
}
}
Here I crop file to square.
I use image library.
import 'dart:io';
import 'package:image/image.dart' as img;
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
class CropperService {
static const _side = 1800;
Future<File> cropImageFile(File file, [int? side]) async {
final image = await img.decodeImageFile(file.path);
if (image == null) throw Exception('Unable to decode image');
final croppedImage = img.copyResizeCropSquare(image, size: _side);
final croppedFile = await _convertImageToFile(croppedImage, file.path);
return croppedFile;
}
Future<File> _convertImageToFile(img.Image image, String path) async {
final newPath = await _croppedFilePath(path);
final jpegBytes = img.encodeJpg(image);
final convertedFile = await File(newPath).writeAsBytes(jpegBytes);
await File(path).delete();
return convertedFile;
}
Future<String> _croppedFilePath(String path) async {
final tempDir = await getTemporaryDirectory();
return join(
tempDir.path,
'${basenameWithoutExtension(path)}_compressed.jpg',
);
}
}
Selected image from gallery and we can crop it using image_cropper dependency in flutter.
Dependency : image_cropper: ^1.4.1
Code when we select image from gallery:
Future<void> pickFromGallery() async {
try {
final picker = ImagePicker();
final pickedImage = await picker.pickImage(source: ImageSource.gallery);
if (pickedImage == null) return;
final croppedImage = await ImageCropper().cropImage(
sourcePath: pickedImage.path,
aspectRatioPresets: [
CropAspectRatioPreset.square,
CropAspectRatioPreset.ratio3x2,
CropAspectRatioPreset.original,
CropAspectRatioPreset.ratio4x3,
CropAspectRatioPreset.ratio16x9
],
androidUiSettings: AndroidUiSettings(
toolbarTitle: 'Crop Image',
toolbarColor: Colors.deepOrange,
toolbarWidgetColor: Colors.white,
initAspectRatio: CropAspectRatioPreset.original,
lockAspectRatio: false,
),
iosUiSettings: IOSUiSettings(
title: 'Crop Image',
aspectRatioLockEnabled: false,
),
);
if (croppedImage == null) return;
final croppedFile = File(croppedImage.path);
setState(() {
this.image = croppedFile;
});
print("Image path: ${croppedFile.path}");
} on PlatformException catch (e) {
print("Failed to pick or crop image: $e");
}
}
and please sure to add activity to AndroidManifest.xml file.
<activity
android:name="com.yalantis.ucrop.UCropActivity"
android:screenOrientation="portrait"
android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
The output be like :
You can crop your image in various size.