I'm trying to find a solution for resizing an image.
The images are picked from a gallery or camera. The problem that I have Is that the image always is not sharp.
This Is How I pick the photo
void _showPickOptionsDialog(BuildContext context, UserData userData) {
final user = Provider.of<Userforid>(context, listen: false);
showDialog(
context: context,
builder: (context) => AlertDialog(
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListTile(
title: Text("Pick From Gallery"),
onTap: () {
_loadPicker(ImageSource.gallery, userData);
Navigator.pop(context);
},
),
ListTile(
title: Text("Pick from Camera"),
onTap: () {
_loadPicker(ImageSource.camera, userData);
Navigator.pop(context);
},
),
],
),
),
);
}
Future _loadPicker(ImageSource source, UserData userData) async {
final XFile file =
await picker.pickImage(source: source, imageQuality: 100);
if (this.mounted) {
// This checks if the widget is still in the tree
setState(() {
if (file != null) {
_cropImage(file, userData);
} else {
return null;
}
});
//Navigator.pop(context);
}
}
_cropImage(XFile picked, UserData userData) async {
final user = FirebaseAuth.instance.currentUser.uid;
File cropped = await ImageCropper.cropImage(
sourcePath: picked.path,
aspectRatioPresets: [
CropAspectRatioPreset.original,
CropAspectRatioPreset.ratio16x9,
CropAspectRatioPreset.ratio5x4
],
maxWidth: 800,
);
if (cropped != null) {
setState(() {
_pickedImage = cropped;
});
}
if (_pickedImage != null) {
final ref = FirebaseStorage.instance
.ref()
.child('user_profile_pictures')
.child(user + '.jpg');
await ref.putFile(_pickedImage);
final url = await ref.getDownloadURL();
_curenturl = url;
await DatbaseService(uid: user).updateUserData(
...);
}
}
And this is how I display them
Container(
child: ClipRRect(
borderRadius:
BorderRadius.circular(60),
child: Container(
height: 110,
width: 110,
decoration: BoxDecoration(
color: Colors.white,
),
child: _pickedImage != null
? Image.file(
_pickedImage,
fit: BoxFit.cover,
)
: userData.url != null &&
userData.url !=
"profilepictureer"
? Image.network(
userData.url,
fit: BoxFit.cover,
)
: Image.asset(
'assets/profilepictureer.png') // Your widget is here when image is no available.
),
),
decoration: new BoxDecoration(
shape: BoxShape.circle,
border: new Border.all(
color: Colors.black,
width: 1)),
),
So the images are set as user profile photos. Probably a solution will be to upload rounded images like Instagram. So the question that I have is how can a user picks a normal photo from camera or gallery and upload it as rounded?
If not how to solve ghe problem then?
You can simply wrap the widget with a ClipOval with flutter.
Take a look at this doc: Flutter Document
or Try using BoxFit.fill
child: ClipRRect(
borderRadius: BorderRadius.circular(16),
child: Image.network(
userData.url,
fit: BoxFit.fill,
),
Related
how to preview an image is to be chosen from gallery or camera in flutter with the new version of image_picker where
PickedFile image = await _picker.getImage(...)
is replace with
final XFile? photo = await _picker.pickImage(source: ImageSource.camera);
so photo must be displayed when it is selected properly
You can do it by using dialog in flutter.
Here is how I dealt with it.
onLongPress: () {
showDialog(
context: context,
builder: (ctx) {
final width = ctx.getWidth(1);
final height = ctx.getHeight(1);
return AlertDialog(
content: Stack(
children: [
SizedBox(
width: width * 0.9,
height: height * 0.7,
child: Image.network(
food.imageUrl,
fit: BoxFit.fill,
),
),
GestureDetector(
onTap: () => Navigator.pop(context),
child: Padding(
padding: const EdgeInsets.all(3.0),
child: Container(
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.5),
shape: BoxShape.circle),
child: Icon(
CupertinoIcons.xmark_circle,
color: Colors.white.withOpacity(0.9),
size: 40,
),
),
),
)
],
),
insetPadding: EdgeInsets.zero,
contentPadding: EdgeInsets.zero,
clipBehavior: Clip.antiAliasWithSaveLayer,
);
},
);
},
You can preview image which you select from gallery or camera as below :
Image.file(
File("file path will be here"), // You can access it with . operator and path property
fit: BoxFit.cover,
)
convert to file:
File newPhoto = File(photo.path);
Use:
Image.file(newPhoto);
I used image_pickers package much easier
late File imageFile = File("");
bool isloaded = false;
ElevatedButton(
onPressed: () => pickImageFromCamera(),)
Padding(
padding: const EdgeInsets.all(8.0),
child: !isloaded
? Image.network(
"https://upload.wikimedia.org/wikipedia/commons/thumb/a/ac/No_image_available.svg/2048px-No_image_available.svg.png")
: Image.file(imageFile)),
void pickImageFromCamera() async {
List<Media>? res = await ImagesPicker.openCamera(
pickType: PickType.image,
);
print(res);
if (res != null) {
print(res[0].path);
setState(() {
imageFile = File(res[0].path);
isloaded = true;
setState(() {});
});
} else {
setState(() {
isloaded = false;
});
}
}
Hey I am using a method for picking photos for user profile picture like that
void _showPickOptionsDialog(BuildContext context, UserData userData) {
final user = Provider.of<Userforid>(context, listen: false);
showDialog(
context: context,
builder: (context) => AlertDialog(
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListTile(
title: Text("Pick From Gallery"),
onTap: () {
_loadPicker(ImageSource.gallery, userData);
Navigator.pop(context);
},
),
ListTile(
title: Text("Pick from Camera"),
onTap: () {
_loadPicker(ImageSource.camera, userData);
Navigator.pop(context);
},
),
],
),
),
);
}
Future _loadPicker(ImageSource source, UserData userData) async {
final XFile file =
await picker.pickImage(source: source, imageQuality: 100);
if (this.mounted) {
// This checks if the widget is still in the tree
setState(() {
if (file != null) {
_cropImage(file, userData);
} else {
return null;
}
});
//Navigator.pop(context);
}
}
_cropImage(XFile picked, UserData userData) async {
final user = FirebaseAuth.instance.currentUser.uid;
File cropped = await ImageCropper.cropImage(
sourcePath: picked.path,
aspectRatioPresets: [
CropAspectRatioPreset.original,
CropAspectRatioPreset.ratio16x9,
CropAspectRatioPreset.ratio5x4
],
maxWidth: 800,
);
if (cropped != null) {
setState(() {
_pickedImage = cropped;
});
}
if (_pickedImage != null) {
final ref = FirebaseStorage.instance
.ref()
.child('user_profile_pictures')
.child(user + '.jpg');
await ref.putFile(_pickedImage);
final url = await ref.getDownloadURL();
_curenturl = url;
await DatbaseService(uid: user).updateUserData(
...);
}
}
And then I displaying the image like that
Container(
child: ClipRRect(
borderRadius:
BorderRadius.circular(60),
child: Container(
height: 110,
width: 110,
decoration: BoxDecoration(
color: Colors.white,
),
child: _pickedImage != null
? Image.file(
_pickedImage,
fit: BoxFit.cover,
)
: userData.url != null &&
userData.url !=
"profilepictureer"
? Image.network(
userData.url,
fit: BoxFit.cover,
)
: Image.asset(
'assets/profilepictureer.png') // Your widget is here when image is no available.
),
),
decoration: new BoxDecoration(
shape: BoxShape.circle,
border: new Border.all(
color: Colors.black,
width: 1)),
),
So a user picks a photo then he can choose if he wanna crop the image and then im creating a downloadurl which im uploading into cloud firestorm and finally uploading the image into firebase cloud storage.
When ever I wanna display the photo I just calling the url.
The problem that I have is that the image looks pixaled and not sharp.
Like this
Hope anyone can help.
My 2 cents
First, try downloading the image directly from the online storage to your computer to check if it was corrupted during the upload.
Next, use the CircleAvatar widget to check whether the problem is not with the displaying part.
CircleAvatar(
radius: 50.0,
backgroundImage: _pickedImage,
)
I wanted to add 3 circle image picker avatar and wanted to upload 3 different pictures in them but unfortunately not able to do that. I tried to do this by extracting the method and passing the image to the single extracted build method and in result the chosen one image is applied to all three avatars. Kindly help me get through it.
Below are the functions for picking image from gallery and camera :
File _image;
final Picker = ImagePicker();
_imgFromCamera() async {
final image = await Picker.pickImage(
source: ImageSource.camera, imageQuality: 50
);
setState(() {
_image = File(image.path);
});
}
_imgFromGallery() async {
final image = await Picker.pickImage(
source: ImageSource.gallery, imageQuality: 50
);
setState(() {
_image = File(image.path);
});
}
Next is function for bottom sheet for picking the image either from gallery or camera:
void _showPicker(context) {
showModalBottomSheet(
context: context,
builder: (BuildContext bc) {
return SafeArea(
child: Container(
child: new Wrap(
children: <Widget>[
new ListTile(
leading: new Icon(Icons.photo_library),
title: new Text('Photo Library'),
onTap: () {
_imgFromGallery();
Navigator.of(context).pop();
}),
new ListTile(
leading: new Icon(Icons.photo_camera),
title: new Text('Camera'),
onTap: () {
_imgFromCamera();
Navigator.of(context).pop();
},
),
],
),
),
);
}
);
}
And here is the extracted method that I want to use for once for all three images:
GestureDetector buildGestureDetector(BuildContext context) {
return GestureDetector(
onTap: () {
_showPicker(context);
},
child: CircleAvatar(
radius: 53,
backgroundColor: Colors.black,
child: _image != null
? ClipRRect(
borderRadius: BorderRadius.circular(50),
child: Image.file(
_image,
width: 100,
height: 100,
fit: BoxFit.fitHeight,
),
)
: Container(
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: BorderRadius.circular(50)),
width: 100,
height: 100,
child: Icon(
Icons.camera_alt,
color: Colors.grey[800],
),
),
),
);
}
}
And here is that extracted method is called inside widget :
Row(
children: [
Expanded(
child: buildGestureDetector(context),
),
],
),
Kindly help me with applying 3 different pictures using this one extracted method and all the functions used once so that I don't need to go through all this process for all three pictures again and again.
The easiest way to handle this is of course passing "which avatar" info down to _imgFromCamera or _imgFromGallery .
For example, if your 3 images have their own identities like 'A', 'B' and 'C',
onTap: () {
_showPicker(context, 'A');
},
Then pass it to the _showPicker.
void _showPicker(context, id) {
...
onTap: () {
_imgFromGallery(id); // Passed 'A' in this example
Navigator.of(context).pop();
}),
...
Then,
_imgFromGallery(id) async {
final image = await Picker.pickImage(
source: ImageSource.gallery, imageQuality: 50
);
// Depends on the id, decide where and how to save the image.
switch(id) {
case 'A': setState(...); break;
case 'B': saveIntoLocal(...); break;
case 'C': uploadToServer(...); break;
....
}
}
I'm getting the image from the image_picker package and loading the image in CircleAvatar but image is not filling across the circle. I have used boxfit.fill in the ClipRRect and also in the ClipOval.
import 'package:image_picker/image_picker.dart';
class EditProfileScreen extends StatefulWidget {
static const String routename = "/EditProfileScreen";
const EditProfileScreen({Key? key}) : super(key: key);
#override
_EditProfileScreenState createState() => _EditProfileScreenState();
}
class _EditProfileScreenState extends BaseState<EditProfileScreen> {
final ImagePicker _picker = ImagePicker();
XFile? _imageFileSelected;
set _imageFile(XFile? value) {
_imageFileSelected = value == null ? null : value;
}
void _onImageButtonPressed(ImageSource source,
{BuildContext? context, bool isMultiImage = false}) async {
try {
final pickedFile = await _picker.pickImage(
source: source, maxHeight: 160, maxWidth: 200);
setState(() {
_imageFile = pickedFile;
});
} catch (e) {
setState(() {
_pickImageError = e;
});
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppWidgets.backgroundColor,
appBar: AppWidgets.appbar(text: "Edit Profile", actionWidgets: []),
body: SingleChildScrollView(
child: Container(
margin: EdgeInsets.fromLTRB(20, 16, 20, 20),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Center(
child: Column(
children: [
CircleAvatar(
child: ClipRRect(
borderRadius: BorderRadius.circular(48),
child: (_imageFileSelected?.path == null)
? Image.network(
profileImagePath,
)
: Image.file(
File(_imageFileSelected!.path),
),
),
radius: 50.0,
),
SizedBox(
height: 10,
),
TextButton(
onPressed: () {
_onImageButtonPressed(ImageSource.gallery,
context: context);
},
child: AppWidgets.text(
string: 'Change Photo',
weight: FontWeight.w500,
textColor: AppWidgets.buttonColor,
size: 16),
),
],
),
),
),
);
}
Note:
I have used boxfit no luck.
I tried clipoval in the child didn't work.
I tried to put images in backgroundImage and foregroundImage unable to do
Instead of using circleavatar you can use Container with background property Try this code.
Container(
height: 88.5.h,
width: 88.5.w,
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.cover,
image: CachedNetworkImageProvider(
state.details["profile_photo"]),
shape: BoxShape.circle,
border: Border.all(
color: ColorConstant.buttonColor,
width: 5.w)),
),
I use this to store the updated picture locally.
ps. this already has a picture which can be changed but you can just use background color to hold instead.
File _image;
String _imagepath;
Future _getImage() async {
var image = await ImagePicker.pickImage(source: ImageSource.gallery);
if (image != null) {
var cropped = await ImageCropper.cropImage(
sourcePath: image.path,
maxHeight: 100,
maxWidth: 100,
aspectRatio: CropAspectRatio(ratioX: 1, ratioY: 1),
cropStyle: CropStyle.circle,
compressQuality: 100,
);
this.setState(() {
_image = cropped;
});
saveImage(_image.path);
}
}
void saveImage(path) async {
SharedPreferences saveimage = await SharedPreferences.getInstance();
saveimage.setString('imagepath', path);
}
void LoadImage() async {
SharedPreferences saveimage = await SharedPreferences.getInstance();
setState(() {
_imagepath = saveimage.getString('imagepath');
});
}
#override
void initState() {
// TODO: implement initState
super.initState();
LoadImage();
}
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: _getImage,
child: Container(
//padding: EdgeInsets.all(2),
decoration: BoxDecoration(
border: Border.all(
color: Colors.white,
width: 5.0,
),
shape: BoxShape.circle,
),
child: _imagepath != null
? CircleAvatar(
backgroundImage: FileImage(File(_imagepath)),
radius: 60,
)
: CircleAvatar(
backgroundImage: _image != null
? FileImage(_image)
: AssetImage('assets/mypic1.jpg'),
backgroundColor: Colors.blue[200],
radius: 60,
),
),
);
I am trying to enable to the app user to change his/her profile picture and upload it via camera or gallery, I used
the image picker package for this purpose,
this is my code snippet:
`
class ProfilePic extends StatefulWidget {
const ProfilePic({
Key key,
}) : super(key: key);
#override
_ProfilePicState createState() => _ProfilePicState();
}
class _ProfilePicState extends State<ProfilePic> {
File image = new File("");
final _picker = ImagePicker();
#override
Widget build(BuildContext context) {
return SizedBox(
height: 115,
width: 115,
child: Stack(
fit: StackFit.expand,
overflow: Overflow.visible,
children: [
CircleAvatar(
backgroundImage: AssetImage(image.uri.toFilePath()),
// child: ClipRRect(
// borderRadius: BorderRadius.circular(50),
// child: image != null
// ? Image.file(
// image,
// width: 115,
// height: 115,
// fit: BoxFit.fitHeight,
// )
// : Container(
// decoration: BoxDecoration(
// color: Colors.grey[100],
// borderRadius: BorderRadius.circular(50)),
// width: 100,
// height: 100,
// child: Icon(
// Icons.camera_alt,
// color: Colors.grey[800],
// ),
// ),
// ),
),
Positioned(
right: -16,
bottom: 0,
child: SizedBox(
height: 46,
width: 46,
child: FlatButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
side: BorderSide(color: Colors.white),
),
color: Color(0xFFF5F6F9),
onPressed: () {
_showPicker(context);
},
child: SvgPicture.asset("icons/cameraIcon.svg"),
),
),
)
],
),
);
}
_imgFromCamera() async {
PickedFile pickedFile =
await _picker.getImage(source: ImageSource.camera, imageQuality: 50);
setState(() {
image = File(pickedFile.path);
});
}
_imgFromGallery() async {
PickedFile pickedFile =
await _picker.getImage(source: ImageSource.gallery, imageQuality: 50);
setState(() {
image = File(pickedFile.path);
});
}
void _showPicker(context) {
showModalBottomSheet(
context: context,
builder: (BuildContext bc) {
return SafeArea(
child: Container(
child: new Wrap(
children: <Widget>[
new ListTile(
leading: new Icon(Icons.photo_library),
title: new Text('Gallerie'),
onTap: () {
_imgFromGallery();
Navigator.of(context).pop();
}),
new ListTile(
leading: new Icon(Icons.photo_camera),
title: new Text('Caméra'),
onTap: () {
_imgFromCamera();
Navigator.of(context).pop();
},
),
],
),
),
);
});
}
}
`
PS: I am using Chrome for debugging.
Its select the image from the device but doesn't change the state to upload the image, am asking if it is a flutter web related problem so in a real device or emulator can work smoothly?
Any suggestion please.
AssetImage takes asset files that you have referenced in your pubspec.yaml. you should use FileImage instead if you are trying to display images from the camera or gallery.
example: FileImage(image)
You can read more here