How to load network image in Flame? - image

In Flame documentation, Image class just load from asset folder.
bgSprite = Sprite('avatar/avatar-sample.png');
How can I load network images in Flame.

You could do something like this in versions after 1.0.0:
import dart:ui; // This is the package you want the Image class from, there are several
Future<Image> getImage(String path) async {
Completer<ImageInfo> completer = Completer();
var img = new NetworkImage(path);
img.resolve(ImageConfiguration()).addListener(ImageStreamListener((ImageInfo info,bool _){
completer.complete(info);
}));
ImageInfo imageInfo = await completer.future;
return imageInfo.image;
}
and then in your onLoad method, just initiate bgSprite:
#override
Future<void> onLoad() async {
final image = await getImage("your-url.com/sample.png");
bgSprite = Sprite(image);
}
In 0.28.0, which it looks like you are running, you'll just replace the last line with (but I really recommend upgrading to a version after 1.0.0):
bgSprite = Sprite.fromImage(image);

Related

Flutter changenotifier not updating or recalling the paint function after loading the images?

I have the following function. The problem here is that I need to load all this 3 img and recall the paint function. I am trying to use ChangeNotifier after I get the image but it seems not working or refreshing the ui/rebuild? What else can I change to get it refresh only after all 3 images loaded completely.
class BarChartPainter extends AxisChartPainter<BarChartData>
with ChangeNotifier {
late Paint _barPaint, _bgTouchTooltipPaint;
List<_GroupBarsPosition>? _groupBarsPosition;
BarChartPainter() : super() {
_barPaint = Paint()..style = PaintingStyle.fill;
asyncFunction().then((val) {
print("Return after build and await" + val.toString());
notifyListeners();
});
}
You need to update your async code to use async/await.
var _data1 = await rootBundle.load('assets/img/pic1.png');
_img1 = await decodeImageFromList(_data1.buffer.asUint8List());
var _data2 = await rootBundle.load('assets/img/pic2.png');
_img2 = await decodeImageFromList(_data2.buffer.asUint8List());
var _data3 = await rootBundle.load('assets/img/pic3.png');
_img3 = await decodeImageFromList(_data3.buffer.asUint8List());
notifyListeners();
So the refresh operation (notifyListeners()) runs only when the others have completed.

In Flutter, how to load a local image as ui.image to draw it in canvas?

I read almost all the posts but still can't find a proper way if any to load a local image as ui.image so that it can be used in canvas.drawImage in Flutter. I have come out with the following code block to get an ui.image from an Asset image. However, it took a few seconds event for a 32x32 size of image and I can't figure it out when it is fully loaded and ready to be drawn in canvas.
static Future<ui.Image> askImage(String path) async {
Completer<ImageInfo> completer = Completer();
final img = Image(image: AssetImage(path));
img.image
.resolve(ImageConfiguration())
.addListener(ImageStreamListener((ImageInfo info, bool _) {
completer.complete(info);
}));
ImageInfo imageInfo = await completer.future;
return imageInfo.image;
}
static ui.Image load2(String xxxx) {
ui.Image info;
askImage(xxxx).then((info) {
if (info != null) {
print(info.width);
print(info.height);
}
return (info);
});
}
I'm also looking at the Image package 'https://pub.dev/packages/image' but I'm not sure how to convert Image from that package to ui.image which is needed for canvas.drawImage function in Flutter. I also saw an old post here (https://flutter2015.firefirestyle.net/rendering/doc-5) but I'm not sure where does the ImageResource comes from.

"Could not convert: Instance of '_Uri'" error while uploading image on cloud firestore's latest version on flutter web

Getting below error while using the latest version of cloud_firestore: ^0.14.0+2 while uploading image on cloud firestore.
Uncaught (in promise) Error: [cloud_firestore/unknown] Invalid argument (dartObject): Could not convert: Instance of '_Uri'
The image gets successfully uploaded in the storage portion but the image link doesn't get updated in cloud firestore db.
Below is the class from where I pick the image and and hit he upload btn to upload the image
class AddNewItemView extends StatefulWidget {
#override
_AddNewItemViewState createState() => _AddNewItemViewState();
}
class _AddNewItemViewState extends State<AddNewItemView> {
MediaInfo _itemPic;
#override
Widget build(BuildContext context) {
return Scaffold(
.....
child: RawMaterialButton(
onPressed: () async {
MediaInfo pickedImg = await ImagePickerWeb.getImageInfo; <---- image_picker_web package
setState(() {
_itemPic = pickedImg;
});
.........
FlatButton(
onPressed: () async {
bool addDataSuccess = await model.addNewItem( _itemPic);
if (addDataSuccess) {
print("Inside addDataSuccess");
} else {
print("Outside addDataSuccess");
}
},
),
.....
);
}
This class is responsible for extracting image uri from uploadImageFile funtion and uploading it in cloud firestore.
Any other info passed alongside pic gets uploaded in cloud firestore, only 'pic' is not uploading
class ItemViewModel extends BaseViewModel {
Future<bool> addNewItem( MediaInfo pic ) async {
Uri _uploadedImgURL = await ConstantFtns()
.uploadImageFile(pic, "ImgPathString", "fileName");
await FirebaseFirestore.instance.collection('item').doc("tempID").set(
{
'pic': _uploadedImgURL,
'otherInfo': 'otherTempInfo'
},
);
}
in below class I get valid imageUri without any error and image gets uploaded in storage portion only problem is that it don't get uploaded in cloud firestore database
import 'package:firebase/firebase.dart' as fb;
import 'package:mime_type/mime_type.dart';
import 'package:path/path.dart' as p;
class ConstantFtns {
Future<Uri> uploadImageFile(
MediaInfo mediaInfo, String ref, String fileName) async {
try {
String mimeType = mime(p.basename(mediaInfo.fileName));
final String extension = extensionFromMime(mimeType);
var metadata = fb.UploadMetadata(
contentType: mimeType,
);
fb.StorageReference storageReference =
fb.storage().ref(ref).child(fileName + ".$extension");
fb.UploadTaskSnapshot uploadTaskSnapshot =
await storageReference.put(mediaInfo.data, metadata).future;
Uri imageUri = await uploadTaskSnapshot.ref.getDownloadURL();
print("download url $imageUri"); <---- IT GETS P[RINTED AND IT SHOWED VALED IMAGE URL STORED IN STORAGE
return imageUri;
} catch (e) {
print("File Upload Error $e");
return null;
}
}
}
Since what you want is simply to store the URL into firestore you don't really need the getDownloadURL() value to be a Uri object, you just need it's string value, being the error you are getting a conversion error, I suggest that you follow what is recommended in this community answer, that way your code will look like this:
String uploadImageFile(
MediaInfo mediaInfo, String ref, String fileName) async {
try {
...
var imageUri = await uploadTaskSnapshot.ref.getDownloadURL() as String;
print("download url $imageUri"); <---- IT GETS P[RINTED AND IT SHOWED VALED IMAGE URL STORED IN STORAGE
return imageUri
} catch (e) {
...
}
}
})
And you also have to change the call in the ItemViewModel class to:
String _uploadedImgURL = await ConstantFtns()
.uploadImageFile(pic, "ImgPathString", "fileName");

dart - Copy image and save in the same directory

I'm newbie in "flutter" and I have question.
It's possible to make copy of image and save it in device ?
File image;
picker() async {
print('Picker is called');
File img = await p.ImagePicker.pickImage(source: p.ImageSource.gallery);
if (img != null) {
image = img;
setState(() {});
}
}
save() async {
print('Save is called');
final Directory path = await image.parent;
setState(() {});
}
I have my image and I can get path of directory. But how to save this image in this directory but with another name ?
Let's say my picture is called x.jpg and I want to have the same picture saved as y.jpg without delete of x.jpg
Use simple_permissions plugin to get the permission to write to the external storage.
Use path_provider plugin to get the path to the external storage folder
Finally use the image plugin to write the image
sample code
Future<Io.File> saveImage(Io.File file) async {
try {
var dir = await getExternalStorageDirectory();
var testdir =
await new Io.Directory('${dir.path}/testfolder').create(recursive: true);
IM.Image image = IM.decodeImage(file.readAsBytesSync());
return new Io.File(
'${testdir.path}/${DateTime.now().toUtc().toIso8601String()}.png')
..writeAsBytesSync(IM.encodePng(image));
} catch (e) {
print(e);
return null;
}
}
also check the permission
void checkPer() async {
bool checkResult = await SimplePermissions.checkPermission(
Permission.WriteExternalStorage);
if (!checkResult) {
var status = await SimplePermissions.requestPermission(
Permission.WriteExternalStorage);
//print("permission request result is " + resReq.toString());
if (status == PermissionStatus.authorized) {
//saveimage
}
} else {
//saveimage
}
}
namespaces
import 'dart:io' as Io;
import 'package:image/image.dart' as IM;
import 'package:path_provider/path_provider.dart';
import 'package:simple_permissions/simple_permissions.dart';

How to get a Flutter Uint8List from a Network Image?

I'm trying to convert a network image into a file and the first part of that is to convert it into a Uint8List. Here is how I'm doing this with 1 of my asset images...
final ByteData bytes = await rootBundle.load('assests/logo');
final Uint8List list = bytes.buffer.asUint8List();
final tempDir = await getTemporaryDirectory();
final file = await new File('${tempDir.path}/image.jpg').create();
file.writeAsBytesSync(list);
How can I do this with Image.network(imageUrl.com/image)
The simplest way seeems to get the http response using the image url and response.bodyBytes would contain the data in Uint8List.
http.Response response = await http.get(
'https://flutter.io/images/flutter-mark-square-100.png',
);
response.bodyBytes //Uint8List
Now you can do things like converting to base64 encoded string base64.encode(response.bodyBytes);
Update: With newer version of http, you need to add Uri.parse()
Eg.
http.Response response = await http.get(
Uri.parse('https://flutter.io/images/flutter-mark-square-100.png'),
);
I figured out a different solution. Hope it helps someone.
import 'dart:typed_data';
import 'package:flutter/services.dart';
Uint8List bytes = (await NetworkAssetBundle(Uri.parse(imageUrl))
.load(imageUrl))
.buffer
.asUint8List();
void initState() {
super.initState();
var sunImage = new NetworkImage(
"https://resources.ninghao.org/images/childhood-in-a-picture.jpg");
sunImage.obtainKey(new ImageConfiguration()).then((val) {
var load = sunImage.load(val);
load.addListener((listener, err) async {
setState(() => image = listener);
});
});
}
See also https://github.com/flutter/flutter/issues/23761#issuecomment-434606683
Then you can use image.toByteData().buffer.asUInt8List()
See also https://docs.flutter.io/flutter/dart-ui/Image/toByteData.html
The answers here are relevant and help explain how dart and flutter image compression/conversion works. If you would like a shortcut, there is this package https://pub.dev/packages/network_image_to_byte that makes it really easy.
After trying for hours this is what helped me
import 'dart:io';
import 'package:http/http.dart' as http;
import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart';
Future<File> getFileFromNetworkImage(String imageUrl) async {
var response = await http.get(imageUrl);
final documentDirectory = await getApplicationDocumentsDirectory();
String fileName = DateTime.now().millisecondsSinceEpoch.toString();
File file = File(path.join(documentDirectory.path, '$fileName.png'));
file.writeAsBytes(response.bodyBytes);
return file;
}
final file = await getFileFromNetworkImage("<your network image Url here>");
Note: this also converts mp4 videos to a File.
originally answered here
As http needs Uri this would be helpful:
you should remove the begining serverAddress from your ImageAddress first :
something like this in my case that I have 3001 in my url:
String serverAddress = 'myAddress.com:3001';
int indexOf3001 = imageAddress.indexOf('3001');
String trimmedImageAddress= imageAddress.substring(indexOf3001 + 4);
then :
var imageUrl = Uri.https(serverAddress, trimmedImageAddress);
final http.Response responseData = await http.get(imageUrl);
Uint8List imageBytes = responseData.bodyBytes;
this works on device and web too, hope it can help.

Resources