class ImagesCropper {
static Future<File?> cropImage(XFile file) async {
final File? croppedImage = await ImageCropper.cropImage(
sourcePath: file.path,
aspectRatioPresets:
Platform.isAndroid ? crossAspectRatioAndroid : crossAspectRatioIos,
androidUiSettings: androidUiSettings,
iosUiSettings: iosUiSettings,
);
return croppedImage;
}
}
i put the full code here:
https://controlc.com/9590e7b1
and here's the error in debug console
debug console
Just change ImageCropper.cropImage to ImageCropper().cropImage. This will use a new instance of ImageCropper.
It looks like you are using the ImageCropper package. https://github.com/hnvn/flutter_image_cropper/blob/master/lib/src/cropper.dart#L61 There was an error because the method isn't static so you have to create a new instance of the class to access it
await ImageCropper().cropImage...
The full code correction is below
class ImagesCropper {
static Future<File?> cropImage(XFile file) async {
final File? croppedImage = await ImageCropper().cropImage(
sourcePath: file.path,
aspectRatioPresets:
Platform.isAndroid ? crossAspectRatioAndroid : crossAspectRatioIos,
androidUiSettings: androidUiSettings,
iosUiSettings: iosUiSettings,
);
return croppedImage;
}
}
Related
The following is the code i was trying to implement in. The future method pickImage i guess it is the one having the problem. I am extending the class with GetxController. The method is expected to pick and crop the selected image using the image cropper, and then set the cropped image to the imageFile variable if the cropping was successful.
import 'dart:io';
import 'package:pamoja/app/data/const.dart';
import 'package:pamoja/app/data/firebase/firebase_functions.dart';
import 'package:pamoja/app/data/global_widgets/indicator.dart';
import 'package:pamoja/app/models/advert_model.dart';
import 'package:pamoja/app/modules/my_adverts/controllers/my_adverts_controller.dart';
import 'package:pamoja/app/routes/app_pages.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:image_picker/image_picker.dart';
import 'package:image_cropper/image_cropper.dart';
class UploadBlogController extends GetxController {
TextEditingController title = TextEditingController();
TextEditingController description = TextEditingController();
TextEditingController location = TextEditingController();
TextEditingController category = TextEditingController();
TextEditingController price = TextEditingController();
TextEditingController phone = TextEditingController();
final FirebaseFunctions _functions = FirebaseFunctions();
File? imageFile;
Future<void> pickImage() async {
try {
ImagePicker _picker = ImagePicker();
await _picker.pickImage(source: ImageSource.gallery).then((value) async {
if (value != null) {
File? croppedFile = await ImageCropper().cropImage(
sourcePath: value.path,
aspectRatio: CropAspectRatio(ratioX: 1, ratioY: 1),
compressQuality: 100,
maxWidth: 700,
maxHeight: 700,
// saveCircleCroppedImage: true,
);
if (croppedFile != null) {
imageFile = croppedFile;
update();
}
}
});
} catch (e) {
showAlert("$e");
}
}
void createBlog() async {
if (title.text.isNotEmpty && description.text.isNotEmpty) {
if (imageFile != null && imageFile != "") {
Indicator.showLoading();
await _functions
.uploadBlog(
title.text,
description.text,
imageFile!,
price.text,
category.text,
location.text,
phone.text,
)
.then((value) {
Indicator.closeLoading();
showAlert("Your advert created sucessfully");
// Get.back();
Get.toNamed(Routes.HOME);
});
} else {
showAlert("Image is required");
}
} else {
showAlert("All fields are required");
}
}
void editBlog(BlogsModel model) async {
Indicator.showLoading();
if (title.text.isNotEmpty && description.text.isNotEmpty) {
if (imageFile == null) {
Map<String, dynamic> map = {
'title': title.text,
'description': description.text,
};
await _functions.editBlog(model.id, map).then((value) {
Get.toNamed(Routes.HOME);
showAlert("Your ads Updated Sucessfully");
});
} else {
String imageUrl = await _functions.uploadImage(imageFile!);
Map<String, dynamic> map = {
'title': title.text,
'description': description.text,
'img': imageUrl,
};
await _functions.editBlog(model.id, map).then((value) {
Get.toNamed(Routes.HOME);
showAlert("Your Advert Updated Sucessfully");
});
}
} else {
showAlert("All fields are required");
}
Indicator.closeLoading();
updateData();
}
void updateData() {
Get.back();
Get.toNamed(Routes.HOME);
if (Get.isRegistered<MyBlogsController>()) {
final controller = Get.find<MyBlogsController>();
controller.myBlogs = [];
Indicator.showLoading();
controller.getMyBlogData();
}
}
}
this i created reusable single-tone code for my entire app to pick media image or video. you can try or modify according your requirement.
// Dart imports:
import 'dart:io';
// Package imports:
import 'package:image_cropper/image_cropper.dart';
import 'package:image_picker/image_picker.dart';
// Project imports:
import 'package:app/utils/export_utils.dart';
class MediaPicker {
MediaPicker._();
static const supportedImageFormates = [".jpeg", ".png"];
static const supportedVedioFormates = [".mp4"];
static final picker = ImagePicker();
// Single image / video selection
static Future<File?> pickMedia({
required ImageSource source,
bool isVideo = false,
bool isEditing = false,
}) async {
try {
final pickMedia = !isVideo
? await picker.pickImage(source: source)
: await picker.pickVideo(source: source);
if (pickMedia != null) {
return isEditing
? await editImage(file: File(pickMedia.path))
: File(pickMedia.path);
} else {
return null;
}
} catch (ex) {
"Pick Media error: $ex".printLog();
return null;
}
}
static Future<File> editImage({required File file}) async {
final CroppedFile? croppedFile = await ImageCropper().cropImage(
sourcePath: file.path,
uiSettings: [
AndroidUiSettings(
toolbarTitle: 'Cropper',
toolbarColor: ColorConst.themePrimaryColor,
toolbarWidgetColor: ColorConst.white,
initAspectRatio: CropAspectRatioPreset.original,
lockAspectRatio: false,
),
IOSUiSettings(
title: 'Cropper',
),
],
);
if (croppedFile != null) {
return File(croppedFile.path);
} else {
return file;
}
}
}
Usage add call method on button tap with Future & async method
Future<void> btnPickImageTap() async {
final File? selectImageFile = await MediaPicker.pickMedia(
source: ImageSource.gallery,
isEditing: true, // Default false
);
}
source: ImageSource.camera - to pick image from camera.
isEditing: false - avoid image cropping functionality.
isVideo: to pick video from gallery / camera.
Make sure following permission added for both platforms
Andriod- AndroidManifest.xml
<uses-permission android:name="android.permission.CAMERA"/> //Camera
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> // Read Storage
iOS Runner/info.plist
<key>NSCameraUsageDescription</key>
<string>App require camera permission to update profile pic</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>App require gallery permission to update profile pic</string>
As package mentioned in image_cropper add bellow code in AndroidManifest.xml under <applcaiton> TAG
<activity
android:name="com.yalantis.ucrop.UCropActivity"
android:screenOrientation="portrait"
android:theme="#style/Theme.AppCompat.Light.NoActionBar"/>
I modified it following your instruction it worked. The following is a sample modification
Future<void> pickImage() async {
try {
ImagePicker _picker = ImagePicker();
await _picker.pickImage(source: ImageSource.gallery).then((value) async {
if (value != null) {
imageFile = File(value.path);
showAlert(imageFile.toString());
editImage(imageFile: imageFile);
// cropImage(imageFile);
} else {
showAlert("No image selected");
}
});
} catch (e) {
showAlert("$e");
}}
Future<void> editImage({required File? imageFile}) async {
final File? croppedFile = await ImageCropper().cropImage(
sourcePath: imageFile!.path,
androidUiSettings: AndroidUiSettings(
toolbarTitle: 'Advert Image',
toolbarColor: Colors.green.shade400,
toolbarWidgetColor: Colors.white,
initAspectRatio: CropAspectRatioPreset.original,
lockAspectRatio: false,
),
iosUiSettings: IOSUiSettings(
title: 'Cropper',
),
);
if (croppedFile != null) {
imageFile = File(croppedFile.path);
update();
} else {
// update();
}}
I have an implementation of imagePicker working with the mobile portion of my app, but i am currently trying to make it work on web too. Im getting an image with the following code:
ImagePicker _picker = ImagePicker();
final XFile? _image = await _picker.pickImage(
source: ImageSource.gallery,
imageQuality: 50,
);
if (_image == null) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('No image was selected.')));
}
if (_image != null) {
var f = await _image.readAsBytes();
StorageRepository()
.updateImage(user, _image, index);
}
Which leads to my confusion. My current storage method looks like this:
Future<void> uploadImageWeb(User user, XFile image, int? index) async {
try {
await storage
.ref('${user.id}/${image.name}')
.putFile(
File(image.path),
)
.then(
(p0) => FirestoreRepository().updateUserPictures(
user,
image.name,
index,
),
);
} catch (err) {
print(err);
}
}
Which obviously i cant use xfile, i have to use the Uint8List. But how do i read any data from that in a meaningful way to upload it to the storage bucket?
Thanks!
I sucessfully Get to pick multiple images from gallery and decided to try uploading to firebase and as well retrieving the image URL. after calling the upload it requested a pass a parameter which i did but it gives an error "The argument type 'List' can't be assigned to the parameter type 'Asset" when i try to specify the index of the parameter i passed it only Saves that image with that particular index.
i also tried a for loop but still it saves only one image and return its url.
How do i get to Upload all the images
Below is how i load the images.
Future<void> loadAssets() async {
List<Asset> resultList = <Asset>[];
resultList = await MultiImagePicker.pickImages(
maxImages: 300,
enableCamera: true,
selectedAssets: images,
cupertinoOptions: const CupertinoOptions(takePhotoIcon: "chat"),
materialOptions: const MaterialOptions(
actionBarColor: "#abcdef",
actionBarTitle: "Example App",
allViewTitle: "All Photos",
selectCircleStrokeColor: "#000000",
));
if (!mounted) return;
setState(() {
images = resultList;
});
}
then i upload the image using the following snippet
Future UploadImage(Asset asset) async {
String fileName = popop;
ByteData byteData = await asset.getByteData();
List<int> imageData = byteData.buffer.asUint8List();
Reference ref = FirebaseStorage.instance.ref().child(fileName);
UploadTask uploadTask = ref.putData(Uint8List.fromList(imageData));
TaskSnapshot snapshot= await uploadTask;
String url= await snapshot.ref.getDownloadURL();
if (kDebugMode) {
print(url);
}
/// After this Update user Profile or add url to collection
return url;
}
used the below code to call/upload a single image out of the list
RaisedButton(
child: const Text("Save Image"),
onPressed: () => UploadImage(images[0]),
),
How to i get to upload all images.
i even tried the for loop below
for(int i=o; i<images.length;i++){
UploadImages(images[i]);
}
But only uploaded a single image
You can iterate over your images like this for example:
final fileNames = <String>[];
for (final image in images) {
final fileName = await uploadImage(image);
fileNames.add(fileName);
}
Not sure whether you really need to call getDownloadUrl() (depends on your use case), but this method creates a public and long-lived url.
If you just want to store a reference in Cloud Firestore for example, you can get the name / fullPath of the respective file from your TaskSnapshot in the uploadImage function as follows:
Future<String> UploadImage(Asset asset) async {
String fileName = popop;
ByteData byteData = await asset.getByteData();
List<int> imageData = byteData.buffer.asUint8List();
Reference ref = FirebaseStorage.instance.ref().child(fileName);
UploadTask uploadTask = ref.putData(Uint8List.fromList(imageData));
TaskSnapshot snapshot= await uploadTask;
// Assuming you are interested in the fullPath use snapshot.ref.fullPath
// For the name use snapshot.ref.name instead
return snapshot.ref.fullPath
}
This question already has answers here:
error: Instance member 'cropImage' can't be accessed using static access
(2 answers)
Closed 12 months ago.
**i spent all night trying get cropped image, need some help **
image_cropper: ^1.5.0 # Used to Crop/Rotate Selected images from user's device
///Error
Error: Member not found: 'ImageCropper.cropImage'.
final croppedImage = await ImageCropper.cropImage(
///images_source
class ImageSourceSheet extends StatelessWidget {
// Constructor
ImageSourceSheet({required this.onImageSelected});
// Callback function to return image file
final Function(File?) onImageSelected;
// ImagePicker instance
final picker = ImagePicker();
Future<void> selectedImage(BuildContext context, File? image) async {
// init i18n
final i18n = AppLocalizations.of(context);
// Check file
if (image != null) {
final croppedImage = await ImageCropper.cropImage(
sourcePath: image.path,
aspectRatioPresets: [CropAspectRatioPreset.square],
maxWidth: 400,
maxHeight: 400,
androidUiSettings: AndroidUiSettings(
toolbarTitle: i18n.translate("edit_crop_image"),
toolbarColor: Theme.of(context).primaryColor,
toolbarWidgetColor: Colors.white,
));
onImageSelected(croppedImage);
}
}
You need to use ImageCropper().cropImage(...).
final croppedImage = await ImageCropper().cropImage(....)
You can check example code.
I managed to choose an image from gallery using the image picker and it is as follows
Future pickImage() async {
File _originalImage = await ImagePicker.pickImage(
source: ImageSource.camera);
if (_originalImage != null) {
File _croppedImage = await ImageCropper.cropImage(
sourcePath: _originalImage.path,
aspectRatioPresets: [
CropAspectRatioPreset.square,
CropAspectRatioPreset.ratio3x2,
CropAspectRatioPreset.original,
CropAspectRatioPreset.ratio4x3,
CropAspectRatioPreset.ratio16x9
],
androidUiSettings: AndroidUiSettings(
toolbarColor: BaengColors.blue,
toolbarTitle: 'Baeng Omang Cropper',
statusBarColor: BaengColors.blue[700],
initAspectRatio: CropAspectRatioPreset.original,
lockAspectRatio: false
)
);
this.setState(() {
_imagePicked = _croppedImage;
isLoaded = true;
getTextFromImage();
});
}
}
Tried to debug it several times and it was not showing any kind of bug nor problem, but the image cropping activity remains black(without) the image selected from the image picker.
Please help
Just add maxHeight And maxWidth in Image_Picker
File _originalImage = await ImagePicker.pickImage(source: ImageSource.camera,
imageQuality: 20,
maxHeight: 500,maxWidth: 500);