How to resize a network image before showing it as NetworkImage in flutter web?
Asked Answered
M

1

7

My goal is to increase the performance of my website by downscaling images.

When i show NetworkImages they always render the full source image resolution (e.g. 7000x4667 pixel). The widget itself mostly has a smaller size (e.g. 200x200 pixel). I have the image url and want to scale the 7000x4667 pixel image down to 200x200 before loading it in the NetworkImage widget.

What i already tried is the answer from this question: Flutter - Resize network image That does work in flutter for mobil but not in flutter web as the line ByteData originalByteData = await originalUiImage.toByteData(); returns null in flutter web.

Already thank you a lot in advance for your help.

Manos answered 30/1, 2021 at 12:40 Comment(5)
Hi, I'm facing same issue. Did you find a solution?Reggy
I haven't found a solution yet. Something that helped me was to downscale the images when i upload them. But that only works when I just show images I uploaded by myself. Unfortunately I don't have a general solution for downscaling web images yet.Manos
Hi I found a working solution for downscaling images lately. It's using image package, everything works but it's very slow. For 4K images it takes ~30 seconds to process.Reggy
That sounds like a step in the right direction. Could you please tell me more about it. Does it slow down the website while loading and is the performance of the website after done loading similar to just showing a smaller network image?Manos
I'm using image package and it's decodeImage method is the bottleneck. So while it's decoding the image bytes into their Image object it freezes the flutter app (the tab where flutter app is loaded) for a while. And it depends on the size of image, big images takes longer. After the resize process completes, it reduces the image size and performance comes back to normal. For your use case, i think its not a solution as resizing image itself is a heavy op. So maybe while uploading images you can upload two versions, one full size and another downscaled.Reggy
C
1

I found a solution that propably suits you . Speed is fantastic and size of the image is reduced significantly.

Flutter Print

late Uint8List targetlUinit8List;
late Uint8List originalUnit8List;

Future<Uint8List> _resizeImage() async {
  var imageUrl = Uri.parse('https://picsum.photos/250?image=9');
  http.Response response = await http.get(imageUrl);
  originalUnit8List = response.bodyBytes;

  ui.Image originalUiImage = await decodeImageFromList(originalUnit8List);
  ByteData? originalByteData = await originalUiImage.toByteData();
  print('original image ByteData size is ${originalByteData!.lengthInBytes}');

  var codec = await ui.instantiateImageCodec(originalUnit8List,
      targetHeight: 200, targetWidth: 200);
  var frameInfo = await codec.getNextFrame();
  ui.Image targetUiImage = frameInfo.image;

  ByteData? targetByteData =
      await targetUiImage.toByteData(format: ui.ImageByteFormat.png);
  print('target image ByteData size is ${targetByteData!.lengthInBytes}');
  targetlUinit8List = targetByteData.buffer.asUint8List();

  //remove delay function
  await Future.delayed(Duration(seconds: 2));
  return targetlUinit8List;
}

Then I have a futureBuilder for my example , but you can use anything you want :

if (snapshot.hasData) {
              children = <Widget>[
                const Icon(
                  Icons.check_circle_outline,
                  color: Colors.green,
                  size: 60,
                ),
                Padding(
                  padding: const EdgeInsets.only(top: 16),
                  child: Image.memory(snapshot.data!),
                )
              ];
            }

Working Example

Only thing left to implement is to dispose the unused variables , and I have no idea how to do it (I am not the best at flutter). I want to know if anyone implements this with disposed variables

Coad answered 27/6, 2022 at 17:40 Comment(3)
Thats correct for mobile and other platforms but not for web. "In the case where the network image is on the Web platform, the [cacheWidth] and [cacheHeight] parameters are ignored as the web engine delegates image decoding to the web which does not support custom decode sizes."Manos
@Manos I think i found a working solution , check the edited answearCoad
Thank you that looks good. To free the space: originalUnit8List = [] as Uint8List; should work.Manos

© 2022 - 2024 — McMap. All rights reserved.