如何在 Flutter Web 中显示 NetworkImage 之前调整网络图片的大小?

7

我的目标是通过缩小图片来提高网站的性能。

当我展示NetworkImages时,它们总是以完整的源图像分辨率呈现(例如7000x4667像素)。该小部件本身通常具有较小的大小(例如200x200像素)。我有图像URL并想在将其加载到NetworkImage小部件之前将7000x4667像素的图像缩小为200x200。

我已经尝试了这个问题的答案: Flutter - Resize network image这在Flutter移动端可以工作,但在Flutter Web中不行,因为ByteData originalByteData = await originalUiImage.toByteData();这一行返回null

非常感谢你的帮助。


嗨,我也遇到了同样的问题。你找到解决方法了吗? - sh_ark
我还没有找到解决方案。对我有帮助的是在上传图片时将其缩小。但这仅适用于我自己上传的图片。不幸的是,我还没有针对缩小网页图片的通用解决方案。 - Franz
1
嗨,最近我找到了一个可行的图像缩小解决方案。它使用图像包,一切都正常,但速度非常慢。对于4K图像,处理需要约30秒。 - sh_ark
听起来是朝着正确方向迈出的一步。您能否告诉我更多关于它的信息?在加载时会减慢网站速度吗?完成加载后,网站的性能是否与仅显示较小网络图像相似? - Franz
我正在使用image包,它的decodeImage方法是瓶颈。因此,在将图像字节解码为其Image对象时,它会冻结Flutter应用程序(加载Flutter应用程序的选项卡)一段时间。这取决于图像的大小,大图像需要更长的时间。调整大小过程完成后,它会减小图像大小,性能恢复正常。对于您的用例,我认为这不是一个解决方案,因为调整图像大小本身就是一个重量级操作。因此,也许在上传图像时,您可以上传两个版本,一个是完整尺寸,另一个是缩小版。 - sh_ark
1个回答

1
我找到了一个解决方案,可能适合您。速度非常快,图像的大小也显著减小。 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;
}

然后我有一个FutureBuilder的例子,但你可以使用任何你想要的东西:

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!),
                )
              ];
            }

示例

只剩下处理未使用的变量了,但我不知道该如何做(我在flutter方面不是很擅长)。我想知道是否有人已经实现了处理未使用的变量。


这适用于移动和其他平台,但不适用于Web。 "在网络图像位于Web平台的情况下,cacheWidth和cacheHeight参数将被忽略,因为Web引擎委托图像解码到Web上,Web不支持自定义解码尺寸。" - Franz
@Franz,我想我找到了一个可行的解决方案,请检查编辑后的答案。 - Lerex
谢谢,看起来不错。为了释放空间: originalUnit8List = [] as Uint8List; 应该可以。 - Franz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接