如何在 Flutter 中确定图像的宽度和高度?
How do I determine the width and height of an image in Flutter?
假设我在 pubspec.yaml 中声明了我的图像,如下所示:
assets:
- assets/kitten.jpg
我的 Flutter 代码是这样的:
void main() {
runApp(
new Center(
child: new Image.asset('assets/kitten.jpg'),
),
);
}
既然我有了 new Image.asset()
,我该如何确定该图像的宽度和高度?例如,我只想打印出图像的宽度和高度。
(看起来 dart:ui's Image class 有宽度和高度,但不确定如何从小部件的图像转到 dart:ui 的图像。)
谢谢!
您可以resolve
the ImageProvider
to get an ImageStream
, then use 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...');
}
},
),
),
);
}
}
更新的解决方案:
有了新版本的flutter,旧的解决方案已经过时了。现在 addListener
需要 ImageStreamListener
.
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));
})
...
...
原始版本:
如果您已经有一个 Image
小部件,您可以通过在其 ImageProvider
上调用 resolve
从中读取 ImageStream
。
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 {
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((ImageInfo info, bool _) => completer.complete(info.image));
return new Scaffold(
appBar: new AppBar(
title: new Text("Image Dimensions Example"),
),
body: new ListView(
children: [
new FutureBuilder<ui.Image>(
future: completer.future,
builder: (BuildContext context, AsyncSnapshot<ui.Image> snapshot) {
if (snapshot.hasData) {
return new Text(
'${snapshot.data.width}x${snapshot.data.height}',
style: Theme.of(context).textTheme.display3,
);
} else {
return new Text('Loading...');
}
},
),
image,
],
),
);
}
}
如果您只想在异步函数中获取图像的宽度和高度,那么其他答案似乎过于复杂。您可以直接使用 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);
新版本的 flutter 旧解决方案不起作用示例:
image.image
.resolve(new ImageConfiguration())
.addListener((ImageInfo info, bool _) => completer.complete(info.image));
工作版本以下:
_image.image
.resolve(new ImageConfiguration())
.addListener(new ImageStreamListener((ImageInfo image, bool _) {
completer.complete(image.image);
}));
创建一个方法,例如:
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;
}
并像这样使用它:
_calculateImageDimension().then((size) => print("size = ${size}")); // 487.0,696.0
如果你不想使用 FutureBuilder 或 then,你也可以像这样使用 await:
别忘了导入图片。但是因为有两个图像类,像这样导入它并与ui.Image
一起使用
import 'dart:ui' as ui
然后就可以按如下方式获取图片的尺寸了。
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;
一种检查从资产加载的图像尺寸的简单方法。
var img = await rootBundle.load("Your image path");
var decodedImage = await decodeImageFromList(img.buffer.asUint8List());
int imgWidth = decodedImage.width;
int imgHeight = decodedImage.height;
这是一个方便的辅助函数,基于其他解决方案
辅助函数
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;
}
用法
Image image = Image.network("https://example.com/pic.png");
ImageInfo info = await getImageInfo(image);
最简单的方法是使用 MediaQuery
width: MediaQuery.of(context).size.width * 0.4,
获取资产图像大小的简单方法。
Future<Size> _loadAssetImageSize(String asset) async{
ByteData data = await rootBundle.load(asset);
ui.Codec codec = await
ui.instantiateImageCodec(data.buffer.asUint8List());
ui.FrameInfo fi = await codec.getNextFrame();
return Size(fi.image.width.toDouble(), fi.image.height.toDouble());
}
只需要解码图像边界的方法:
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.dipose();
buffer.dipose();
假设我在 pubspec.yaml 中声明了我的图像,如下所示:
assets:
- assets/kitten.jpg
我的 Flutter 代码是这样的:
void main() {
runApp(
new Center(
child: new Image.asset('assets/kitten.jpg'),
),
);
}
既然我有了 new Image.asset()
,我该如何确定该图像的宽度和高度?例如,我只想打印出图像的宽度和高度。
(看起来 dart:ui's Image class 有宽度和高度,但不确定如何从小部件的图像转到 dart:ui 的图像。)
谢谢!
您可以resolve
the ImageProvider
to get an ImageStream
, then use 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...');
}
},
),
),
);
}
}
更新的解决方案:
有了新版本的flutter,旧的解决方案已经过时了。现在 addListener
需要 ImageStreamListener
.
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));
})
...
...
原始版本:
如果您已经有一个 Image
小部件,您可以通过在其 ImageProvider
上调用 resolve
从中读取 ImageStream
。
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 {
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((ImageInfo info, bool _) => completer.complete(info.image));
return new Scaffold(
appBar: new AppBar(
title: new Text("Image Dimensions Example"),
),
body: new ListView(
children: [
new FutureBuilder<ui.Image>(
future: completer.future,
builder: (BuildContext context, AsyncSnapshot<ui.Image> snapshot) {
if (snapshot.hasData) {
return new Text(
'${snapshot.data.width}x${snapshot.data.height}',
style: Theme.of(context).textTheme.display3,
);
} else {
return new Text('Loading...');
}
},
),
image,
],
),
);
}
}
如果您只想在异步函数中获取图像的宽度和高度,那么其他答案似乎过于复杂。您可以直接使用 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);
新版本的 flutter 旧解决方案不起作用示例:
image.image
.resolve(new ImageConfiguration())
.addListener((ImageInfo info, bool _) => completer.complete(info.image));
工作版本以下:
_image.image
.resolve(new ImageConfiguration())
.addListener(new ImageStreamListener((ImageInfo image, bool _) {
completer.complete(image.image);
}));
创建一个方法,例如:
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;
}
并像这样使用它:
_calculateImageDimension().then((size) => print("size = ${size}")); // 487.0,696.0
如果你不想使用 FutureBuilder 或 then,你也可以像这样使用 await:
别忘了导入图片。但是因为有两个图像类,像这样导入它并与ui.Image
一起使用 import 'dart:ui' as ui
然后就可以按如下方式获取图片的尺寸了。
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;
一种检查从资产加载的图像尺寸的简单方法。
var img = await rootBundle.load("Your image path");
var decodedImage = await decodeImageFromList(img.buffer.asUint8List());
int imgWidth = decodedImage.width;
int imgHeight = decodedImage.height;
这是一个方便的辅助函数,基于其他解决方案
辅助函数
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;
}
用法
Image image = Image.network("https://example.com/pic.png");
ImageInfo info = await getImageInfo(image);
最简单的方法是使用 MediaQuery
width: MediaQuery.of(context).size.width * 0.4,
获取资产图像大小的简单方法。
Future<Size> _loadAssetImageSize(String asset) async{
ByteData data = await rootBundle.load(asset);
ui.Codec codec = await
ui.instantiateImageCodec(data.buffer.asUint8List());
ui.FrameInfo fi = await codec.getNextFrame();
return Size(fi.image.width.toDouble(), fi.image.height.toDouble());
}
只需要解码图像边界的方法:
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.dipose();
buffer.dipose();