如何确定Flutter中图像的宽度和高度?

Set*_*add 18 dart flutter

假设我在pubspec.yaml中声明了我的图像,如下所示:

  assets:
    - assets/kitten.jpg
Run Code Online (Sandbox Code Playgroud)

我的Flutter代码是这样的:

void main() {
  runApp(
    new Center(
      child: new Image.asset('assets/kitten.jpg'),
    ),
  );
}
Run Code Online (Sandbox Code Playgroud)

现在我有了,我该new Image.asset()如何确定该图像的宽度和高度?例如,我只想打印出图像的宽度和高度.

(看起来像dart:ui的Image类有宽度和高度,但不知道如何从widget的Image转到dart:ui的Image.)

谢谢!

Col*_*son 20

如果你已经有了一个addListener小部件,你可以ImageStreamListener通过调用它来读取ImageImageStream.

截图

Widget build(BuildContext context) {
    Image image = new Image.network('https://i.stack.imgur.com/lkd0a.png');
    Completer<ui.Image> completer = new Completer<ui.Image>();
    image.image
      .resolve(new ImageConfiguration())
      .addListener(ImageStreamListener(ImageInfo info, bool _) { 
        completer.complete(info.image));
      })
    ...
    ...
Run Code Online (Sandbox Code Playgroud)

  • 我们需要更新这个答案。addListener 需要一个 ImageStreamListener。即使这样,我在“completer.complete(info.image)”这一行收到一个错误,说“参数类型‘Image’不能分配给参数类型‘FutureOr&lt;Image&gt;’” (9认同)
  • 这是否会导致图像被加载***两次***,从而浪费大量网络和CPU? (2认同)
  • 需要是:`image.image.resolve(ImageConfiguration()).addListener( ImageStreamListener((ImageInfo info, bool synchronousCall) {completer.complete(info.image); }));` (2认同)

Col*_*son 17

你可以resolveImageProvider得到一个ImageStream,然后用addListener得到通知时,图像已准备就绪.

截图

import 'dart:ui' as ui;
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() {
  runApp(new MaterialApp(
    home: new MyHomePage(),
  ));
}

class MyHomePage extends StatelessWidget {

  Future<ui.Image> _getImage() {
    Completer<ui.Image> completer = new Completer<ui.Image>();
    new NetworkImage('https://i.stack.imgur.com/lkd0a.png')
      .resolve(new ImageConfiguration())
      .addListener((ImageInfo info, bool _) => completer.complete(info.image));
    return completer.future;
  }

  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Image Dimensions Example"),
      ),
      body: new Center(
        child: new FutureBuilder<ui.Image>(
          future: _getImage(),
          builder: (BuildContext context, AsyncSnapshot<ui.Image> snapshot) {
            if (snapshot.hasData) {
              ui.Image image = snapshot.data;
              return new Text(
                '${image.width}x${image.height}',
                style: Theme.of(context).textTheme.display4);
            } else {
              return new Text('Loading...');
            }
          },
        ),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)


qwe*_*guy 16

如果您只想在异步函数中调整图像的宽度和高度,则其他答案似乎过于复杂。您可以像下面这样直接使用flutter lib获得图像分辨率:

import 'dart:io';

File image = new File('image.png'); // Or any other way to get a File instance.
var decodedImage = await decodeImageFromList(image.readAsBytesSync());
print(decodedImage.width);
print(decodedImage.height);
Run Code Online (Sandbox Code Playgroud)

  • 这返回的高度比图像的实际高度高得多。当我使用这个值来设置高度时,我在顶部和底部获得了很多额外的空间。 (2认同)
  • 最简单的解决方案,截至 2020 年 7 月 26 日仍然可以正常工作 (2认同)
  • 我不明白这部分。我的资产文件夹中有一张图像,它说无法读取该图像。`文件图像 = new File("lib/pages/assets/images/road_map.png");` (2认同)
  • @nrion我认为你可以使用 rootBundle.load('assets/image.png') 并将其直接传递给decodeImageFromList (2认同)

Cop*_*oad 15

创建一个方法,例如:

Future<Size> _calculateImageDimension() {
  Completer<Size> completer = Completer();
  Image image = Image.network("https://i.stack.imgur.com/lkd0a.png");
  image.image.resolve(ImageConfiguration()).addListener(
    ImageStreamListener(
      (ImageInfo image, bool synchronousCall) {
        var myImage = image.image;
        Size size = Size(myImage.width.toDouble(), myImage.height.toDouble());
        completer.complete(size);
      },
    ),
  );
  return completer.future;
}
Run Code Online (Sandbox Code Playgroud)

并像这样使用它:

_calculateImageDimension().then((size) => print("size = ${size}")); // 487.0,696.0
Run Code Online (Sandbox Code Playgroud)


小智 10

对于只想解码图像边界的人来说,一种方法:

import 'dart:ui' as ui;

final buffer = await ui.ImmutableBuffer.fromUint8List(bytes);
final descriptor = await ui.ImageDescriptor.encoded(buffer);

final imageWidth = descriptor.width;
final imageHeight = descriptor.height;
print("imageWidth: $imageWidth, imageHeight: $imageHeight");

descriptor.dispose();
buffer.dispose();
Run Code Online (Sandbox Code Playgroud)


Erk*_*bay 9

使用新版本的 flutter 旧解决方案不起作用示例:

  image.image
  .resolve(new ImageConfiguration())
  .addListener((ImageInfo info, bool _) => completer.complete(info.image));
Run Code Online (Sandbox Code Playgroud)

在工作版本下方

_image.image
    .resolve(new ImageConfiguration())
    .addListener(new ImageStreamListener((ImageInfo image, bool _) {
  completer.complete(image.image);
}));
Run Code Online (Sandbox Code Playgroud)

  • 我可以确认这是添加侦听器的新方法,但我在 `completer.complete(image.image);` 上收到错误:`Image 类型的参数无法分配给类型参数 FutureOr&lt;Image&gt; `。这怎么解决呢? (2认同)

Jan*_*nen 9

如果你不想使用FutureBuilder或者然后,你也可以像这样使用await:

不要忘记导入图像。但由于有两个 Image 类,因此像这样导入它并与 ui.Image 一起使用

 import 'dart:ui' as ui
Run Code Online (Sandbox Code Playgroud)

然后您可以按如下方式获取图像的尺寸。

 final Image image = Image(image: AssetImage('assets/images/someimage.png'));
 Completer<ui.Image> completer = new Completer<ui.Image>();
    image.image
        .resolve(new ImageConfiguration())
        .addListener(new ImageStreamListener((ImageInfo image, bool _) {
      completer.complete(image.image);
    }));
 ui.Image info = await completer.future;
 int width = info.width;
 int height = info.height;
Run Code Online (Sandbox Code Playgroud)

  • 绝对比接受的答案更好 (2认同)

Ben*_*ing 5

这是一个基于其他解决方案的方便的辅助函数

辅助函数

Future<ImageInfo> getImageInfo(Image img) async {
  final c = new Completer<ImageInfo>();
  img.image
    .resolve(new ImageConfiguration())        
    .addListener(new ImageStreamListener((ImageInfo i, bool _) {
      c.complete(i);
    }));
  return c.future;    
}
Run Code Online (Sandbox Code Playgroud)

用法

Image image = Image.network("https://example.com/pic.png");
ImageInfo info = await getImageInfo(image);
Run Code Online (Sandbox Code Playgroud)