Flutter display package:image/image.dart:Image in UI Widget - flutter

We can work on images in Flutter using import 'package:image/image.dart' as ToolsImage; package to scale them with ToolsImage.copyResize() and manipulate individual pixels with ToolsImage.Image.getPixel(x,y)
To display image from memory bytes (ByteData/Uint8List/List<int>) we can use MemoryImage:
Container(child: Image(image: MemoryImage(image.data.buffer.asUint8List())))
I'm getting an exception:
Exception: Invalid image data
whichever List I use. What's wrong?

Remember to add HEADER to image bytes after format conversions!
ByteData imageByteData = await rootBundle.load('res/images/basic/dizzy-face.png');
List<int> values = imageByteData.buffer.asUint8List();
ToolsImage.Image? photo = ToolsImage.decodeImage(values);
photo = ToolsImage.copyResize(photo!, height: 32, width: 32);
removes header information (pixel-by-pixel manipulation removes header info).
Use:
List<int>? imageWithHeader = ToolsImage.encodeNamedImage(TEST_IMAGE, ".bmp");
and then:
Container(child: Image(image: MemoryImage(Uint8List.fromList(imageWithHeader))))
Last line enables us to convert package:image/image.dart to package:flutter/src/widgets/image.dart (UI Image Widget)

Related

Flutter listview moving when loading images from network

i am trying to make a listview with lots of images with different dimensions loaded from network.
When I scroll down everything is okay, but when i am scrolling up, first images start to load changing the position of listview. I suppose I need to have a placeholder for images with height of image, but i dont know how to get their dimensions before them loaded. Or i need smth like listview that does not move because of smth upper loading.
I wrote a function that gets a height of image in a cycle (array favorites contains Maps which contain url parameter and height parameter if loaded). The function also converts image's height in the size i actually need by formula with MediaQuery.of(context).size.width - 80 which is the width of images on screen. (Width of the screen minus 40 padding from each side).
This is the code of getting height function:
Future<void> getImageHeight(String url, index) async {
Image image = Image.network(url);
image.image
.resolve(const ImageConfiguration())
.addListener(ImageStreamListener((ImageInfo info, bool isSync) {
favorites[index]['height'] = info.image.height *
((MediaQuery.of(context).size.width - 80) / info.image.width);
setState(() {});
}));
}
And this is the code of image with placeholder (Container):
Container(
color: const Color(0xffE8E6EA),
height: favorites[index]['height'] == null || favorites[index
['height'].isNaN ? 0: favorites[index]['height'],
child: Image.network(
favorites[index]['url'],
width: double.infinity,
),
),
On first loading size of placeholder is still going to be zero, because it takes time to get height of them. But after few time (it usually takes about a second or less) setState is going to be called and images will not lag on scrolling. And if you are loading your images urls from database not all at once you'll need to rerun function to get height of newly added images.
Set minCacheExtend large enough
(to be higher than the highest picture's height)
I had the same issue, I resolved it by Increasing the cache of the flutter app. Default cache size is 100mb. You can place this at the beginning of main.dart
WidgetsFlutterBinding.ensureInitialized();
PaintingBinding.instance!.imageCache!.maximumSizeBytes = 1024 * 1024 * 300; // 300 MB
More Info Here

Flutter: Display grid of images on PDF

I'm using flutter with the pdf plugin to generate a PDF document where I need to display a grid of images. The images are stored in a List<File>.
Here's what I've tried. Keep in mind that all these widgets are from the pdf package and not from material.
GridView(
crossAxisCount: 5,
childAspectRatio: 1,
children: door.images.map((image) {
return Container(
child: Image(MemoryImage(?????), fit: BoxFit.cover),
);
}).toList(),
),
Note: door.images is the List<File>
How do I convert the File image (from the List<File>) to the Uint8List bytes needed for the MemoryImage widgets?
Convert your File to imagebytes.
final List<int> _imageBytes = await image.readAsBytes();
And then convert the imagebytes to your Uint8List.
final String _uint8List = base64Encode(_imageBytes);

How to compress image asset from multi_image_picker flutter?

Libraries used: https://pub.dev/packages/multi_image_picker, https://pub.dev/packages/flutter_image_compress
I am using multi image picker lib to get multiple images from the gallery. However, before uploading them I want to compress image's size first.
Multiple image picker return List<Asset> but in flutter_image_compress lib, we can only compress image as a type of File like this:
Future<Uint8List> testCompressFile(File file) async {
var result = await FlutterImageCompress.compressWithFile(
file.absolute.path,
minWidth: 2300,
minHeight: 1500,
quality: 94,
rotate: 90,
);
return result;
}
How can I convert List<Asset> to List<File> in order to compress image?
I solved this problem. Please check my full source code here: https://soksereyphon8.medium.com/upload-multiple-images-and-compress-image-in-flutter-62d113a3247a

Flutter remove image after upload using image_picker package

I have managed to upload an image using the image picker package as shown below:
final picker = ImagePicker();
Future selectPhoto() async {
final pickedFile = await picker.getImage(source: ImageSource.gallery);
setState(() {
_image = File(pickedFile.path);
});
}
The image has been displayed on the device where I have a remove button which I can use to remove the image and upload another before saving it.
child: Container(
height: height * 0.2,
width: width * 0.2,
child: Image.file(
_image,
fit: BoxFit.fill,
),
),
My question is how can I remove the image from cache as this piece is not working
onTap: () {
setState(() {
imageCache.clear();
print('removes $_image');
});
},
You have a misunderstanding of what the cache is compared to explicitly storing a file in memory with your code. Flutter may store images that you use in widgets in a cache so that they may load faster in the future. imageCache.clear(); does clear the cache and is likely doing it's work in your code. However, your method of checking if the image is still cached is flawed.
imageCache.clear(); only clears the cache, it does not delete the file that you're passing to the Image.file widget. This means that _image(the file variable you have stored in memory) will persist even over the cache clearing. To truly delete this image you could use the delete method or if you just want to stop showing the image, deference the file by setting the file reference to null:
_image = null;
Solved it by calling a method within the button which had set state method where the path was returned back to null
clearimage() {
setState(() {
_image = null;
});
}

Show svg or image from network depending on type flutter

Hi I'm using a service that send me images, sometimes png or jpeg images and I use the flutter widget Image. In the other hand sometimes send me svg images intuit case I can use flutter_svg package, but I don't know how to switch between that widgets depending on the image type.
There isn't nothing on the url that I can use to determine the image type.
How I can do that?
UPDATE: Example response from the server, the image is on property lexeme_image
{
"has_tts": true,
"word": "one",
"language_information": {},
"from_language_name": "Spanish",
"tts": "https://d1vq87e9lcf771.cloudfront.net/joeyn/b53723d682be1114be1cefce3ddbb908",
"infinitive": null,
"learning_language": "en",
"translations": "un, una, uno",
"learning_language_name": "English",
"pos": "Numeral",
"lexeme_image": "https://d2pur3iezf4d1j.cloudfront.net/images/4be10d03a4c6ac4078b6be0df2eb5247",
"from_language": "es",
"is_generic": false,
"lexeme_id": "dd0309fb9cf34f8a2b2e029889c26ec5",
"related_lexemes": [],
"canonical_path": "/dictionary/English/one/d3a447831e3322e78309fa3a161c0ebf"
}
Rather than using the .network constructors provided by the Image widgets, retrieve the Image file with a network request like below:
HttpClient().getUrl(Uri.parse(STRING URL HERE))
.then((HttpClientRequest request) => request.close())
.then((HttpClientResponse response) =>
response.pipe(File('foo').openWrite()));
or a better example using await:
HttpClientRequest request = await HttpClient().getUrl(Uri.parse(STRING URL HERE));
HttpClientResponse response = await request.close();
File file = File('foo');
await response.pipe(file .openWrite());
Then using the image library's PngDecoder and JpegDecoder decoder classes isValidFile method, you can check if the image is a png or jpeg. Example:
PngDecoder png = PngDecoder();
JpegDecoder jpg = JpegDecoder();
if(png.isValidFile(file) || jpg.isValidFile(file)) {
//use `Image.file(file)`
}
else {
//use `SvgPicture.file(file)`
}
If it is either of those, you can pass the file you retrieved to the Image.file constructor. If it's not then use the SvgPicture.file constructor.
I found a pretty neat work-around for this and this is working fine for me.Hope that it helps you guys as well.
First use the flutter_svg package
Now i am assuming that you're getting the image extension as .svg or other image extensions like .jpg , .jpg etc.
Now i would recommend you to use Image.network and pass the SvgPicture widget in the errorBuilder property of Image.network
Here's an example for the same.
return Image.network(
cryptoCoins[index]['logo_url'], //extensions like .jpg, .png etc
height: 90,
errorBuilder: (context, error, stackTrace) =>
SvgPicture.network(
cryptoCoins[index]['logo_url'], // for .svg extension
height: 90,
),
);
Hope it helps.
I had this problem as well and wrote a little wrapper around svgpicture and the other image widgets: https://pub.dev/packages/hybrid_image