How to store signature as an image in firebase storage - flutter

I have a form, in that form I have a signature pad. I used signature 3.2.0 package. That package consist a method toImage(). I want to store that image in the firebase storage. when I try below code.
fileImage = _controller.toImage() as File;
final FirebaseStorage storage = FirebaseStorage.instance;
final String picture = "${DateTime.now().millisecondsSinceEpoch.toString()}.jpg";
StorageUploadTask task = storage.ref().child(picture).putFile(fileImage);
task.onComplete.then((snapshot) async{
loadData.setSignatureURL = await snapshot.ref.getDownloadURL();
});
loadData.storeDetails();
I got an error type 'Image' is not a subtype of type 'File' in type cast.
How can I store signature as an image/

Casting can't be done on a whim, which is why you get this error.
The Image class provides a toByteData method that allows you to retrieve the raw image data as a ByteData object. You can then convert this to a Uint8List. This list then can be directly used for firebase storage with the putData method instead of putFile.
var image = await _controller.toImage();
ByteData data = await image.toByteData();
Uint8List listData = data.buffer.asUint8List();
final FirebaseStorage storage = FirebaseStorage.instance;
final String picture = "${DateTime.now().millisecondsSinceEpoch.toString()}.jpg";
StorageUploadTask task = storage.ref().child(picture).putData(listData);
...
If you need to encode this image to a specific type. You can use a version of the following code which encodes to JPG. It uses the image package which needs to be added as a dependency
import 'package:image/image.dart' as encoder;//This import needs to be added in the file this is being done
var image = await _controller.toImage();
//Store image dimensions for later
int height = image.height;
int width = image.width;
ByteData data = await image.toByteData();
Uint8List listData = data.buffer.asUint8List();
encoder.Image toEncodeImage = encoder.Image.fromBytes(width, height, listData);
encoder.JpegEncoder jpgEncoder = encoder.JpegEncoder();
List<int> encodedImage = jpgEncoder.encodeImage(toEncodeImage);
final FirebaseStorage storage = FirebaseStorage.instance;
final String picture = "${DateTime.now().millisecondsSinceEpoch.toString()}.jpg";
StorageUploadTask task = storage.ref().child(picture).putData(Uint8List.fromList(encodedImage));
...

Related

How to convert an Image instance to File instance in Flutter?

I am using VideoThumbanil class to fetch an Uint8List image of a video like this:
final uint8List = await VideoThumbnail.thumbnailData(video: videoFile.path,);
After doing so, i am converting the Uint8LIST to an Image using the following code:
Image image = Image.memory(uint8List);
What I want to do is to convert this image to a File class instance so that I can upload this image to my server. Code for uploading on server is:
void asyncFileUpload(File file) async {
//create multipart request for POST or PATCH method
var request = http.MultipartRequest("POST", Uri.parse("127.0.0.1/upload"));
//create multipart using filepath, string or bytes
var pic = await http.MultipartFile.fromPath("image", file.path);
//add multipart to request
request.files.add(pic);
var response = await request.send();
//Get the response from the server
var responseData = await response.stream.toBytes();
var responseString = String.fromCharCodes(responseData);
print(responseString);
}
You can fetch the path to the temporary directory:
final tempDir = await getTemporaryDirectory();
After doing so, you can create a File in that temporary directory:
File fileToBeUploaded = await File('${tempDir.path}/image.png').create();
This way your file has a path and it's instance has been created. Now, you can write the file as:
fileToBeUploaded.writeAsBytesSync(uint8List);
Now, you can use fileToBeUploaded as File that is actually an image.
Complete code:
final uint8List = await VideoThumbnail.thumbnailData(video: videoFile.path,);
final tempDir = await getTemporaryDirectory();
File fileToBeUploaded = await File('${tempDir.path}/image.png').create();
fileToBeUploaded.writeAsBytesSync(uint8List);
asyncFileUpload(fileToBeUploaded);
Since you already have the uint8 list you can try
File fileTpSend = File.fromRawPath(Uint8List uint8List);
Based on your code you need to import 'dart:io' and user fromRawPath function from File class (check snippet below)
import 'dart:io';
final uint8List = await VideoThumbnail.thumbnailData(video:videoFile.path);
final imageAsFile = File.fromRawPath(uint8List);
await asyncFileUpload(imageAsFile);
But this method doesn't work for Flutter WEB

How to convert Image Data type from imageUrl

I need to convert this watermark(from assets) image and imageurl(getting from API) to Image data type, because ui.drawImage takes only Image data types
ui.Image? watermarkImage = ui.decodeImage('assets/images/watermark.png');// getting error
ui.Image? lookbookImage = ui.decodeImage(imageurl); // getting error
final originalImage = imgData;
ui.Image image = ui.Image(160, 50);
ui.drawImage(image, watermarkImage);
First you need to get the image bytes
// network
final response = await http.Client().get(Uri.parse(imageurl));
final bytes = response.bodyBytes;
//assets
final byteData = await rootBundle.load('assets/images/watermark.png');
final bytes = byteData.buffer.asUint8List();
Then you can decode ui.Image from the image bytes
final image = await decodeImageFromList(bytes);

Save Image From ImagePicker Locally as a Memory(cache)

I want to save an Image from ImagePicker as a Memory but error Occured . Can you Please help me with this function and if another function needed to load image please Mentioned it below.
Uint8List? memoryImage;
Future getImage() async {
final picker = ImagePicker();
final image = await picker.getImage(source: ImageSource.camera);
if (image == null) return;
final Directory directory = await getApplicationDocumentsDirectory();
final path=directory.path;
final Filename=basename(image.path);
File file = File('$directory/$Filename.jpg');
final bytes = await file.readAsBytes();
final byte1= file.writeAsBytes(bytes);
setState(() {
memoryImage = byte1 as Uint8List?;
});
}
With this line you can write image bytes as a file.
File imageFile = await File(fileSavePath).writeAsBytes(imageBytes);
To access the Uint8List from the file you need to use
Uint8List memoryImage = File(imagePath).readAsBytesSync();
Or
Uint8List memoryImage = await File(imagePath).readAsBytes();
here the problem in your code is you are assigning file to a Uint8List. That's the error I guess

Using Flutter Camera package, how do I convert a photo to a base64 string?

Using the Flutter Camera package (v0.9.4+5), how do I convert a captured photo into a base64 string?
I believe the following code will work, but welcome to any thoughts on how the code can be improved.
import 'dart:convert' as convert;
void capturePhoto() async {
// Note: `controller` being initialized as shown in readme
// https://pub.dev/packages/camera#example
XFile photo = await controller.takePicture();
List<int> photoAsBytes = await photo.readAsBytes();
String photoAsBase64 = convert.base64Encode(photoAsBytes);
}
Try this.
var image = await ImagePicker.pickImage(source: ImageSource.gallery);
final bytes = Io.File(image.path).readAsBytesSync();
String img64 = base64Encode(bytes);
print (img64);

Flutter cannot get download url firebase-storage

While trying to upload byteArray to the bucket in firebase storage, the file uploads to the storage but I cannot get the downloadUrl back from the file. I am getting the reference of bucket like this:
Future<Reference> get storageRef async {
final _bucketUrl = await bucketUrl;
return FirebaseStorage.instanceFor(bucket: _bucketUrl).ref();
}
And Uploading image like this:
Future<String> uploadImageByteArray({
#required Uint8List byteArray,
String fileName,
}) async {
final name = fileName ?? DateTime.now().toIso8601String();
final _ref = await storageRef;
final _refUrl = _ref.child("images/$name.png");
print(_refUrl.fullPath);
final uploadTask = _refUrl.putData(byteArray);
final snapshot = await uploadTask;
return snapshot.ref.getDownloadURL();
}
From above code I am getting this error:
Unhandled Exception: type 'NoSuchMethodError' is not a subtype of type 'Exception'.
It works if I get reference for the FirebaseStorage only and not the bucket like this:
Future<Reference> get storageRef{
return FirebaseStorage.instance.ref();
}
I cannot implement without using bucket reference because there can be different bucket urls depending on the tenants. What am I doing wrong?
Edit => Recent Developments:
I found out that it works if I get the downloadurl from the _refUrl itself. i.e:
String downloadUrl = _refUrl.getDownloadUrl();
It works but I can't help but wonder if it is correct implementation.
Your edit makes perfect sense since you have the reference to the uploaded file with _refUrl, fetching its long-lived download URL works as expected (That's how I have done it before btw). I don't have access to a project with FirebaseStorage to test this, but You can try printing snapshot.ref.fullPath and compare it with the fullPath of _refUrl.
try this
Future<String> uploadImageByteArray({
#required Uint8List byteArray,
String fileName,
}) async {
final name = fileName ?? DateTime.now().toIso8601String();
final _ref = await storageRef;
final _refUrl = _ref.child("images/$name.png");
print(_refUrl.fullPath);
final uploadTask = _refUrl.putData(byteArray);
final snapshot = (await uploadTask);
String url = await snapshot.ref.getDownloadURL(); // await
return url;
}