Search code examples
imageflutterflutter-webimage-scalingimage-size

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


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.


Solution

  • 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