Issues with Image selection from disk Flutter - flutter

I have this form where I need to upload a profilePic and companyLogo. Earlier I faced some issues regarding updating images on the selection which I fixed using : imageCache.clear() & imageCache.clearLiveImages() and passing Unique key to Image.file widgets.
Now, the problem is, if I select the profile Pic then select the company Logo & When I send the images as Multipart in FormData, it uses the file which I selected later for both, i.e, if I select _companyLogo after _profilePic, it replaces _profilePic data with _companyLogo, however the displaying images remains correct for Image.file widget.
//Widgets using GestureDetector to call onAddProfilePic() and onAddCompanyLogo()
File _profilePic;
Key _keyProfilePic = Key('key1');
Image.file(
_profilePic,
fit: BoxFit.cover,
key: _keyProfilePic,
)
File _companyLogo;
Key _keyCompanyLogo = Key('key2');
Image.file(
_companyLogo,
fit: BoxFit.cover,
key: _keyCompanyLogo,
)
onAddProfilePic(){
Utils.selectImage(context, (newPic) {
if(newPic != null){
_profilePic = newPic;
_keyProfilePic = Key(Uuid().v4());
setState(() {});
}
});
}
onAddCompanyLogo(){
Utils.selectImage(context, (newPic) {
if(newPic != null){
_companyLogo = newPic;
_keyCompanyLogo = Key(Uuid().v4());
setState(() {});
}
});
}
The function selectImage is in Utils Class
static Future<void> selectImage(context, callback, {int minSize = 480, double ratioX = 1.0, double ratioY = 1.0}) async {
int sourceSelected = await showDialog(context: context, builder: (context) => DialogImagePicker());
if(sourceSelected == null) return;
var pickedImage = await ImagePicker().getImage(source: sourceSelected == 0 ? ImageSource.camera : ImageSource.gallery);
if(pickedImage==null) return;
File croppedFile = await ImageCropper.cropImage(
maxWidth: (minSize * ratioX).toInt(),
maxHeight: (minSize * ratioY).toInt(),
compressFormat: ImageCompressFormat.jpg,
sourcePath: pickedImage.path,
aspectRatio: CropAspectRatio(ratioX: ratioX, ratioY: ratioY),
compressQuality: 80,
androidUiSettings: AndroidUiSettings(
toolbarColor: kDarkBlueColor,
toolbarTitle: 'Crop Image',
hideBottomControls: true,
toolbarWidgetColor: Colors.white
),
);
if(croppedFile == null){
return;
}
croppedFile = croppedFile.renameSync(path.join(path.dirname(croppedFile.path), 'image'+'.jpg'));
print('Cropped file :$croppedFile');
imageCache.clear();
imageCache.clearLiveImages();
callback(croppedFile);
}

The problem is, since I was cropping the image & was changing the cropped file name, which was replacing previous images with newly selected ones. Not renaming so fixed the issue.
Additional to this, no unique key or image cache clearance is required.
Updated code:
File _profilePic;
Image.file(
_profilePic,
fit: BoxFit.cover,
)
File _companyLogo;
Image.file(
_companyLogo,
fit: BoxFit.cover,
)
onAddProfilePic(){
Utils.selectImage(context, (newPic) {
if(newPic != null){
_profilePic = newPic;
setState(() {});
}
});
}
onAddCompanyLogo(){
Utils.selectImage(context, (newPic) {
if(newPic != null){
_companyLogo = newPic;
setState(() {});
}
});
}
static Future<void> selectImage(context, callback, {int minSize = 480, double ratioX = 1.0, double ratioY = 1.0}) async {
int sourceSelected = await showDialog(context: context, builder: (context) => DialogImagePicker());
if(sourceSelected == null) return;
var pickedImage = await ImagePicker().getImage(source: sourceSelected == 0 ? ImageSource.camera : ImageSource.gallery);
if(pickedImage==null) return;
File croppedFile = await ImageCropper.cropImage(
maxWidth: (minSize * ratioX).toInt(),
maxHeight: (minSize * ratioY).toInt(),
compressFormat: ImageCompressFormat.jpg,
sourcePath: pickedImage.path,
aspectRatio: CropAspectRatio(ratioX: ratioX, ratioY: ratioY),
compressQuality: 80,
androidUiSettings: AndroidUiSettings(
toolbarColor: kDarkBlueColor,
toolbarTitle: 'Crop Image',
hideBottomControls: true,
toolbarWidgetColor: Colors.white
),
);
if(croppedFile == null){
return;
}
//croppedFile = croppedFile.renameSync(path.join(path.dirname(croppedFile.path), 'image'+'.jpg'));
callback(croppedFile);
}

Related

Flutter Upload Images

I try to use upload image from Flutter libary, but it doesn't work. The codes just run to gallery and choose the image, but the image doesn't show to the screen.
Please help me to make it work, from choosing the image and show the image result that I choose. Thanks
You have to update the state of the screen for seeing the changes. If you are using stateful just simply use setState to do this.
setState(() {
uploadFile = File(image!.path);
});
I hope this answer will help you.
static String? pickImage({bool useCamera = false, bool crop = true,
CropAspectRatio ratio = const CropAspectRatio(
ratioX: 1, ratioY: 1,
)}) {
ImagePicker().pickImage(source: useCamera ? ImageSource.camera : ImageSource.gallery, imageQuality: 60).then((pickedFile) {
if (pickedFile == null || !File(pickedFile.path).existsSync()) {
return Stream.error(Exception('No image picked!'));
}
if (crop) {
ImageCropper().cropImage(sourcePath: pickedFile.path ?? '', aspectRatio: ratio, uiSettings: [
AndroidUiSettings(
toolbarTitle: 'Cropper',
toolbarColor: AppStyles.primary500Color,
toolbarWidgetColor: Colors.white,
initAspectRatio: CropAspectRatioPreset.original,
lockAspectRatio: false),
IOSUiSettings(
title: 'Cropper',
),
]).then((value) {
if (value != null) {
croppedFile = value;
// selectedPhotoStream.add(croppedFile);
/// ** You are missing **
setState((){
uploadFile = croppedFile.path;
});
return croppedFile?.path;
}
});
}
});
return croppedFile?.path;
}

File Picker png format images is giving issues

I was using ImagePicker in my application to select and upload images, but it recently started giving me errors, and constantly glitches when selecting png format images.
For this reason I switched to File picker. But it only works somewhat, and my application still gets stuck. I can only see its display, the image unfortunately does not get stored in the backend (jpg and jpeg images work fine).
Here is the image picker code (if there is a workaround uploading png images using this package, it would be much appreciated):
final ImagePicker _picker = ImagePicker();
Future imageSelectorGallery() async {
var image = (await _picker.pickImage(
source: ImageSource.gallery,
));
if (image != null) {
Uint8List imageBytes = await image
.readAsBytes(); // A fixed-length list of 8-bit unsigned integers which is the file read as bytes
String baseimage = base64Encode(imageBytes);
if (mounted) setState(() {});
post = baseimage;
Navigator.push(context,MaterialPageRoute(builder: (context) => CreatePosts(post,user,caption,upvotes)));
}
}
Here is the file picker code which I have implemented, any help figuring out the error here would also be appreciated:
Future imageSelectorGallery() async {
FilePickerResult? image = await FilePicker.platform.pickFiles(
type: FileType.custom,
allowedExtensions: ['jpg', 'jpeg', 'png', 'gif'],
);
if (image != null) {
Uint8List? imageBytes = image.files.first.bytes;
String baseimage = base64Encode(imageBytes!);
if (mounted) setState(() {});
post = baseimage;
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => CreatePosts(post, user, caption, upvotes)));
} else {
print("File picker error");
}
}
The image is displayed using:
child: Container(
height:
MediaQuery.of(context).size.height / 4.3,
width: MediaQuery.of(context).size.width / 3.4,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
image: DecorationImage(
fit: BoxFit.cover,
image: Image.memory(
_bytesImage,
gaplessPlayback: true,
).image,
))),
),

How to convert a Image file to Asset Image in flutter?

I am using the image_picker and image_cropper plugin to select or capture the image with the help of the camera and Gallery. I got an image file from an image_picker. Now, I am using the Image.asset() widget to show the image in the Circle Avatar. Can anyone please tell me how I convert an image File to an asset image?
My code:
//Function that decides if image is returned or not(If not, then it will show the default circle avator)
File getImageWidget() {
if (_selectedImage != null) {
return _selectedImage;
} else {
return null;
}
}
//Function to set the image in the circle avatar
circleAva(){
return profileIconSelector(
setProfileIconHighQuality(getImageWidget() ?? userDetails.profile_pic,
userDetails.loginInitFrom),
userDetails.name,
SizeConfig.heightMultiplier * 5);
}
//Function to get image from Camera or Gallery
getImage(ImageSource source) async {
this.setState((){
_inProcess = true;
});
File image = await ImagePicker.pickImage(source: source);
if(image != null){
File cropped = await ImageCropper.cropImage(
sourcePath: image.path,
aspectRatio: CropAspectRatio(
ratioX: 1, ratioY: 1),
compressQuality: 100,
maxWidth: 700,
maxHeight: 700,
compressFormat: ImageCompressFormat.jpg,
androidUiSettings: AndroidUiSettings(
toolbarColor: Colors.deepOrange,
toolbarTitle: "Cropper",
statusBarColor: Colors.deepOrange.shade900,
backgroundColor: Colors.white,
)
);
this.setState((){
_selectedImage = cropped;
_inProcess = false;
});
} else {
this.setState((){
_inProcess = false;
});
}
}
You can't add asset images from your app. Asset images are images that you add to your project manually, but you can save the path to the image once it has been picked, then use Image.file(File.fromUri(Uri.file(IMAGE_PATH))).
Fortunately, I found the solution for this by myself.
In the case of the Image.file() widget, we have to provide the image of a File type.
And, In the case of the AssetImage() or Image.asset() widget, we need to pass the image path of String type.
So the Solution to use Image of File type in AssetImage() or
Image.asset() widget:
File _selectedImage = fetchedFromCameraOrGallery;
getImageWidget() {
if (_selectedImage != null) {
return CircleAvatar(
radius: SizeConfig.heightMultiplier * 5,
backgroundImage: AssetImage(
_selectedImage.path, //Convert File type of image to asset image path
),
);
}
}
We have to simply use the _selectedImage.path that will convert the image file of File type to a valid Asset image path format.

Getting a "File$" instead of a File in flutter

I am allowing users to grab a profile pic and upload that picture as file to my server, but I'm getting this error when inputting the image via ImagePickerWeb:
<error>:<getObject: Unexpected error from chrome devtools:>
I don't know if it's my browser or me, but this is what I'm trying:
Future<void> getMultipleImageInfos() async {
var imageFile =
await ImagePickerWeb.getImage(outputType: ImageType.file);
print(imageFile);
if (imageFile != null) {
setState(() {
currentSelfie = imageFile;
_accDetails['customer_selfie'] = currentSelfie;
});
}
}
Then displaying that photo here:
Image.file(
currentSelfie,
height: screenAwareSize(100, context),
width: screenAwareSize(100, context),
fit: BoxFit.fill,
)

How to use preference for showing profile picture in my application in flutter

I want to display a profile picture of the user when they log in. I am using the image URL stored in firestore database.
I want to keep the image in the app until logout. Every time I start the app, Image is called from that URL but I want to store it. I am new to flutter and have no clue to achieve this task.
Future<void> _getImage(ImageSource source) async {
var image = await ImagePicker.pickImage(source: source);
if (image != null) {
setState(() {
_cropImage(image);
});
}
Navigator.pop(context);
}
// Crop fetched image
_cropImage(File image) async {
File cropped = await ImageCropper.cropImage(
sourcePath: image.path,
aspectRatio: CropAspectRatio(ratioY: 1.0, ratioX: 1.0));
if (cropped != null) {
setState(() {
_imageFile = cropped;
uploadFile();
});
}
}
// Upload image file to firestrore Storage and get image URL
Future uploadFile() async {
StorageReference storageReference = FirebaseStorage.instance
.ref()
.child('${Path.basename(_imageFile.path)}}');
StorageUploadTask uploadTask = storageReference.putFile(_imageFile);
var downUrl = await (await uploadTask.onComplete).ref.getDownloadURL();
var url = downUrl.toString();
await uploadTask.onComplete;
setState(() {
imageUrl = url.toString();
});
// Show message on successful image upload
AppUtils.showToast('Picture Uploaded', green, white);
// Updating database with Image URL
Firestore.instance
.collection('account')
.document(widget.user)
.updateData({"url": imageUrl});
}
// Display Image
ClipRRect(
borderRadius: BorderRadius.circular(200.0),
clipBehavior: Clip.hardEdge,
child: Container(
height: 200,
width: 200,
child: widget.photoUrl == null
? Image(
image: NetworkImage(
'https://cdn1.iconfinder.com/data/icons/technology-devices-2/100/Profile-512.png'),
fit: BoxFit.fill,
)
: Image(
image: NetworkImage(widget.photoUrl),
fit: BoxFit.fill,
))),
What you need is a proper State Management throughout your app.
You can check the Provider Package to get started.
You can find more information about State Management here and here