Image class
A widget that displays an image.
Several constructors are provided for the various ways that an image can be specified:
- Image.new, for obtaining an image from an ImageProvider.
- Image.asset, for obtaining an image from an AssetBundle using a key.
- Image.network, for obtaining an image from a URL.
- Image.file, for obtaining an image from a File.
- Image.memory, for obtaining an image from a Uint8List.
The following image formats are supported: JPEG, PNG, GIF, Animated GIF, WebP, Animated WebP, BMP, and WBMP. Additional formats may be supported by the underlying platform. Flutter will attempt to call platform API to decode unrecognized formats, and if the platform API supports decoding the image Flutter will be able to render it.
To automatically perform pixel-density-aware asset resolution, specify the image using an AssetImage and make sure that a MaterialApp, WidgetsApp, or MediaQuery widget exists above the Image widget in the widget tree.
The image is painted using paintImage, which describes the meanings of the various fields on this class in more detail.
const Image(
image: NetworkImage('https://flutter.github.io/assets-for-api-docs/assets/widgets/owl.jpg'),
)
Image.network('https://flutter.github.io/assets-for-api-docs/assets/widgets/owl-2.jpg')
Multiframe images, such as animated GIFs, are paused when TickerMode is disabled just like any other animation. They also paused when animations are disabled via MediaQueryData.disableAnimations, such as for accessibility purposes. If the animation is paused when the image first loads, the first frame will be displayed and then animation will stop.
TickerMode(
enabled: !isPaused,
child: Image(image: myAnimatedGif),
),
Memory usage
The image is stored in memory in uncompressed form (so that it can be rendered). Large images will use a lot of memory: a 4K image (3840×2160) will use over 30MB of RAM (assuming 32 bits per pixel).
This problem is exacerbated by the images being cached in the ImageCache, so large images can use memory for even longer than they are displayed.
The Image.asset, Image.network, Image.file, and Image.memory
constructors allow a custom decode size to be specified through cacheWidth
and cacheHeight parameters. The engine will then decode and store the
image at the specified size, instead of the image's natural size.
This can significantly reduce the memory usage. For example, a 4K image that
will be rendered at only 384×216 pixels (one-tenth the horizontal and
vertical dimensions) would only use 330KB if those dimensions are specified
using the cacheWidth and cacheHeight parameters, a 100-fold reduction in
memory usage.
Custom image providers
To create a local project with this code sample, run:
flutter create --sample=widgets.Image.4 mysample
import 'dart:async';
import 'dart:io';
import 'dart:ui' as ui;
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
@immutable
class CustomNetworkImage extends ImageProvider<Uri> {
const CustomNetworkImage(this.url);
final String url;
@override
Future<Uri> obtainKey(ImageConfiguration configuration) {
final Uri result = Uri.parse(url).replace(
queryParameters: <String, String>{
'dpr': '${configuration.devicePixelRatio}',
'locale': '${configuration.locale?.toLanguageTag()}',
'platform': '${configuration.platform?.name}',
'width': '${configuration.size?.width}',
'height': '${configuration.size?.height}',
'bidi': '${configuration.textDirection?.name}',
},
);
return SynchronousFuture<Uri>(result);
}
static HttpClient get _httpClient {
HttpClient? client;
assert(() {
if (debugNetworkImageHttpClientProvider != null) {
client = debugNetworkImageHttpClientProvider!();
}
return true;
}());
return client ?? HttpClient()
..autoUncompress = false;
}
@override
ImageStreamCompleter loadImage(Uri key, ImageDecoderCallback decode) {
final StreamController<ImageChunkEvent> chunkEvents =
StreamController<ImageChunkEvent>();
debugPrint('Fetching "$key"...');
return MultiFrameImageStreamCompleter(
codec: _httpClient
.getUrl(key)
.then<HttpClientResponse>(
(HttpClientRequest request) => request.close(),
)
.then<Uint8List>((HttpClientResponse response) {
return consolidateHttpClientResponseBytes(
response,
onBytesReceived: (int cumulative, int? total) {
chunkEvents.add(
ImageChunkEvent(
cumulativeBytesLoaded: cumulative,
expectedTotalBytes: total,
),
);
},
);
})
.catchError((Object e, StackTrace stack) {
scheduleMicrotask(() {
PaintingBinding.instance.imageCache.evict(key);
});
return Future<Uint8List>.error(e, stack);
})
.whenComplete(chunkEvents.close)
.then<ui.ImmutableBuffer>(ui.ImmutableBuffer.fromUint8List)
.then<ui.Codec>(decode),
chunkEvents: chunkEvents.stream,
scale: 1.0,
debugLabel: '"key"',
informationCollector: () => <DiagnosticsNode>[
DiagnosticsProperty<ImageProvider>('Image provider', this),
DiagnosticsProperty<Uri>('URL', key),
],
);
}
@override
String toString() =>
'${objectRuntimeType(this, 'CustomNetworkImage')}("$url")';
}
void main() => runApp(const ExampleApp());
class ExampleApp extends StatelessWidget {
const ExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
return Image(
image: const CustomNetworkImage(
'https://flutter.github.io/assets-for-api-docs/assets/widgets/flamingos.jpg',
),
width: constraints.hasBoundedWidth ? constraints.maxWidth : null,
height: constraints.hasBoundedHeight ? constraints.maxHeight : null,
);
},
),
);
}
}
See also:
- Icon, which shows an image from a font.
- Ink.image, which is the preferred way to show an image in a material application (especially if the image is in a Material and will have an InkWell on top of it).
- Image, the class in the dart:ui library.
- Cookbook: Display images from the internet
- Cookbook: Fade in images with a placeholder
- Inheritance
Constructors
-
Image({Key? key, required ImageProvider<
Object> image, ImageFrameBuilder? frameBuilder, ImageLoadingBuilder? loadingBuilder, ImageErrorWidgetBuilder? errorBuilder, String? semanticLabel, bool excludeFromSemantics = false, double? width, double? height, Color? color, Animation<double> ? opacity, BlendMode? colorBlendMode, BoxFit? fit, AlignmentGeometry alignment = Alignment.center, ImageRepeat repeat = ImageRepeat.noRepeat, Rect? centerSlice, bool matchTextDirection = false, bool gaplessPlayback = false, bool isAntiAlias = false, FilterQuality filterQuality = FilterQuality.medium}) -
Creates a widget that displays an image.
const
-
Image.asset(String name, {Key? key, AssetBundle? bundle, ImageFrameBuilder? frameBuilder, ImageErrorWidgetBuilder? errorBuilder, String? semanticLabel, bool excludeFromSemantics = false, double? scale, double? width, double? height, Color? color, Animation<
double> ? opacity, BlendMode? colorBlendMode, BoxFit? fit, AlignmentGeometry alignment = Alignment.center, ImageRepeat repeat = ImageRepeat.noRepeat, Rect? centerSlice, bool matchTextDirection = false, bool gaplessPlayback = false, bool isAntiAlias = false, String? package, FilterQuality filterQuality = FilterQuality.medium, int? cacheWidth, int? cacheHeight}) -
Creates a widget that displays an ImageStream obtained from an asset
bundle. The key for the image is given by the
nameargument. -
Image.file(File file, {Key? key, double scale = 1.0, ImageFrameBuilder? frameBuilder, ImageErrorWidgetBuilder? errorBuilder, String? semanticLabel, bool excludeFromSemantics = false, double? width, double? height, Color? color, Animation<
double> ? opacity, BlendMode? colorBlendMode, BoxFit? fit, AlignmentGeometry alignment = Alignment.center, ImageRepeat repeat = ImageRepeat.noRepeat, Rect? centerSlice, bool matchTextDirection = false, bool gaplessPlayback = false, bool isAntiAlias = false, FilterQuality filterQuality = FilterQuality.medium, int? cacheWidth, int? cacheHeight}) - Creates a widget that displays an ImageStream obtained from a File.
- Image.memory(Uint8List bytes, {