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,
))),
),
Related
I am downloading an image from Internet to the device and then updating a SQLITE table to store the image path:
Future<void> _download(String archivo, String docId, OfertaDB doc) async {
final docUrl = Constantes.docsProyecto+archivo;
final response = await http.get(Uri.parse(docUrl));
// Get the image name
final imageName = path.basename(docUrl);
// Get the document directory path
final appDir = await getApplicationDocumentsDirectory();
// This is the saved image path
// You can use it to display the saved image later
final localPath = path.join(appDir.path, imageName);
// Downloading
final imageFile = File(localPath);
await imageFile.writeAsBytes(response.bodyBytes);
print("path de ofertas ${appDir.path}/${imageName}");
var documentoDescargado = OfertaDB(
id: doc.id,
header: doc.header,
estado: doc.estado,
titulo: doc.titulo,
titulofr: doc.titulofr,
texto: doc.texto,
textofr: doc.textofr,
fechas: doc.fechas,
imagen: doc.imagen,
path: "${appDir.path}/${imageName}"
);
await dbHelper.updateOferta(documentoDescargado);
}
Then on another screen I need to display the image from SQLITE table:
var pathAr = news_promos.path;
print("path es ${pathAr}");//output /data/user/0/red.faro.labelconciergeflutter/app_flutter/Ezg7a9joalimaldivesvilla.jpeg
File image = File(pathAr);
Then to display the image:
Container(
alignment: Alignment.center,
width: 100,
height: 100,
child: image != null
? Image.file(image!, fit: BoxFit.cover)
: const Text('Please select an image'),
),
But the image is not displayed, it is shown an Exception: invalid image data error
What is wrong in the code used?
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);
}
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,
)
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
Using the play_games extension, I'm having trouble returning the user's profile image.
Use the method below to login and set the state with the return of the user's data.
Image provider: NetworkImage ("content: //com.google.android.gms.games.background/images/f56551ac/42", scale: 1.0)
// Google Play Games stance
final GameServices gameservices = GameServices();
Account profile;
ui.Image profileimage;
void _login() async {
final res = await gameservices.login();
final resimage = await res.hiResImage;
setState(() {
profile = res;
profileimage = resimage;
});
print(profileimage);
}
In the widget I'm in the form of NetworkImage, but it's still not rendering on the screen.
this error: The argument type 'Image' can't be assigned to the parameter type 'String'.
Container(
width: 128,
height: 128,
padding: EdgeInsets.all(8),
child: CircleAvatar(
backgroundImage: NetworkImage(this.profileimage != null ? this.profileimage : 'https://api.adorable.io/avatars/128/')
),
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.circle
),
),
[ RESOLVED!!! ]
Change my code and play_games returns type vars.
Lets go:
Future<Uint8List> get hiResImage async =>
await _fetchToMemory(await _channel.invokeMethod('getHiResImage'));
Future<Uint8List> get iconImage async =>
await _fetchToMemory(await _channel.invokeMethod('getIconImage'));
}
Future<Uint8List> _fetchToMemory(Map<dynamic, dynamic> result) {
Uint8List bytes = result['bytes'];
if (bytes == null) {
print('was null, mate');
return Future.value(null);
}
// Completer<Image> completer = new Completer();
// decodeImageFromList(bytes, (image) => completer.complete(image));
return Future.value(bytes);
}
And my code, only this change:
Uint8List profileimage;
Flutter is yelling at you because you gave it a URL with protocol content://, when it expects http:// or https:// for a NetworkImage widget. See documentation at: https://flutter.dev/docs/cookbook/images/network-image
This happen because google provide encoded image. In android we can use ImageManager for that as google suggest.
In flutter there are mechanism for getting Future<Image> from hiresImageUri. Check here.
Use Something like below,
profile.hiResImage.then((Image result){
//here you can get image in result
});