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.

Franz
  • 600
  • 1
  • 4
  • 12
  • Hi, I'm facing same issue. Did you find a solution? – sh_ark Jan 17 '22 at 08:47
  • 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. – Franz Jan 19 '22 at 18:04
  • 1
    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. – sh_ark Jan 20 '22 at 05:27
  • 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? – Franz Jan 21 '22 at 08:34
  • 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. – sh_ark Jan 21 '22 at 09:20

1 Answers1

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

Lerex
  • 313
  • 1
  • 9
  • 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." – Franz Jun 29 '22 at 14:41
  • @Franz I think i found a working solution , check the edited answear – Lerex Jun 30 '22 at 15:54
  • Thank you that looks good. To free the space: originalUnit8List = [] as Uint8List; should work. – Franz Jul 01 '22 at 16:17