Flutter - Get Image Width and Height Dimensions Examples

This tutorial explains some different ways to get the width and height of an image.

If you want to get the dimensions of an image programmatically in Flutter, it can be done in several ways. You can read the examples below. This tutorial only explains how to get the dimensions of the original image, not how to get the rendered size. You can read our tutorial about how to get the size of a widget in Flutter if what you need to get is the rendered size.

For this tutorial, we create a simple class ImageDetail that stores the width and height values of an image.

  class ImageDetail {

    final int width;
    final int height;
    final Uint8List? bytes;

    ImageDetail({required this.width, required this.height, this.bytes});
  }

Below are different ways to get the dimensions of an image.

Using ImageStreamListener

This method is suitable if you want to display the image using Image widget. The source of the image can be from network, file, asset, or memory. First of all, you need to create the Image widget. The example below uses a network URL as the source. However, the steps for other sources are very similar.

  final Image image = Image.network(
    'https://www.woolha.com/media/2020/05/flutter-colorfilter-merge-identity.jpg',
  );

The Image widget has image property which returns an ImageProvider. Then, use the resolve method of the ImageProvider class to create an ImageStream. Finally, you can add an ImageStreamListener listener.

The constructor of ImageStreamListener has a required positional argument whose type is a function. You have to pass a function which accepts ImageInfo as the first argument and a boolean as the second argument. The ImageInfo contains the actual data of the image. The second argument indicates whether the listener is being invoked during the call to addListener. For getting the image size, you only need to use the first argument.

The listener is invoked when the image information becomes available. Inside the listener, you can get the value of ImageInfo that's passed as the argument. It has a property named ui.Image, which has the width and height properties of the image.

  Completer<ImageDetail> completer = Completer<ImageDetail>();

  image.image
    .resolve(const ImageConfiguration())
    .addListener(ImageStreamListener((ImageInfo imageInfo, bool _) {
      final dimensions = ImageDetail(
        width: imageInfo.image.width,
        height: imageInfo.image.height,
      );
      completer.complete(dimensions);
    }));

The example above uses a Completer which will complete inside the listener after the image information has been available. Therefore, we can use the FutureBuilder widget by using the Completer's Future.

  return FutureBuilder(
    future: completer.future,
    builder: (BuildContext context, AsyncSnapshot<ImageDetail> snapshot) {
      if (!snapshot.hasData) {
        return Container();
      }

      return Column(
        children: [
          image,
          Text('${snapshot.data?.width} x ${snapshot.data?.height}')
        ],
      );
    },
  );

Using ImageDescriptor

Another way to get the size of an image is by using ImageDescriptor. It doesn't require you to create a widget, so it's suitable if you don't want to render the image. First, you need to get the bytes of the image as Unit8List type. Below is the example if the image is from a network URL. The code below requires the http package added to the dependencies in pubspec.yaml file. Then, add import 'package:http/http.dart' as http; at the top of the file.

  final response = await http.get(Uri.parse(imageUrl));
  final bytes = response.bodyBytes; // returns Unit8List

If the source is the application's asset, it's also necessary to get the bytes as shown in the example below.

  final byteData = await rootBundle.load(assetPath);
  final bytes = byteData.buffer.asUint8List();

To create the ImageDescriptor, you need to have the ImmutableBuffer value, which can be obtained using ImmutableBuffer.fromUint8List. Then, convert the buffer to ImageDescriptor by using ImageDescriptor.encoded method. The ImageDescriptor has the width and height properties of the image. After getting the necessary values, don't forget to dispose the descriptor and the buffer.

  final buffer = await ImmutableBuffer.fromUint8List(bytes);
  final descriptor = await ImageDescriptor.encoded(buffer);
  final dimensions = ImageDetail(
    width: descriptor.width,
    height: descriptor.height,
    bytes: bytes,
  );

  descriptor.dispose();
  buffer.dispose();

Using ImageDimensions

Another way is by decoding the image bytes to ui.Image. Assuming you already have the bytes in Unit8List, you need to decode the image to ui.Image by using decodeImageFromList method. Then, you can get the width and height values.

  final response = await http.get(Uri.parse(imageUrl));
  final bytes = response.bodyBytes;
  final decodedImage = await decodeImageFromList(bytes);

  return ImageDetail(
    width: decodedImage.width,
    height: decodedImage.height,
    bytes: bytes,
  );

Full Code

  import 'dart:async';
  import 'dart:ui';
  
  import 'package:flutter/material.dart';
  import 'package:flutter/services.dart';
  import 'package:http/http.dart' as http;
  
  void main() => runApp(const MyApp());
  
  class MyApp extends StatelessWidget {
  
    const MyApp({Key? key}) : super(key: key);
  
    @override
    Widget build(BuildContext context) {
      return const MaterialApp(
        title: 'Woolha.com Flutter Tutorial',
        home: MyPage(),
      );
    }
  }
  
  class MyPage extends StatelessWidget {
  
    const MyPage({Key? key}) : super(key: key);
  
    @override
    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: const Text('Woolha.com Flutter Tutorial'),
          backgroundColor: Colors.teal,
        ),
        body: SingleChildScrollView(
          child: Column(
            children: const [
              GetImageDimensionsUsingWidgetListener(),
              GetImageDimensionsUsingImageDescriptor(),
              GetImageDimensionsUsingImageDecoder(),
              GetAssetImageDimensions(),
            ],
          ),
        ),
      );
    }
  }
  
  class ImageDetail {
  
    final int width;
    final int height;
    final Uint8List? bytes;
  
    ImageDetail({required this.width, required this.height, this.bytes});
  }
  
  class GetImageDimensionsUsingWidgetListener extends StatelessWidget {
  
    const GetImageDimensionsUsingWidgetListener({Key? key}) : super(key: key);
  
    @override
    Widget build(BuildContext context) {
      final Image image = Image.network(
        'https://www.woolha.com/media/2020/05/flutter-colorfilter-merge-identity.jpg',
      );
  
      Completer<ImageDetail> completer = Completer<ImageDetail>();
  
      image.image
          .resolve(const ImageConfiguration())
          .addListener(ImageStreamListener((ImageInfo imageInfo, bool _) {
            final dimensions = ImageDetail(
              width: imageInfo.image.width,
              height: imageInfo.image.height,
            );
            completer.complete(dimensions);
          }));
  
      return FutureBuilder(
        future: completer.future,
        builder: (BuildContext context, AsyncSnapshot<ImageDetail> snapshot) {
          if (!snapshot.hasData) {
            return Container();
          }
  
          return Column(
            children: [
              image,
              Text('${snapshot.data?.width} x ${snapshot.data?.height}')
            ],
          );
        },
      );
    }
  }
  
  class GetImageDimensionsUsingImageDescriptor extends StatelessWidget {
  
    const GetImageDimensionsUsingImageDescriptor({Key? key}) : super(key: key);
  
    Future<ImageDetail> _getImageDimensions(String imageUrl) async {
      final response = await http.get(Uri.parse(imageUrl));
      final bytes = response.bodyBytes;
      final buffer = await ImmutableBuffer.fromUint8List(bytes);
      final descriptor = await ImageDescriptor.encoded(buffer);
      final dimensions = ImageDetail(
        width: descriptor.width,
        height: descriptor.height,
        bytes: bytes,
      );
  
      descriptor.dispose();
      buffer.dispose();
  
      return dimensions;
    }
  
    @override
    Widget build(BuildContext context) {
      return FutureBuilder(
        future: _getImageDimensions('https://www.woolha.com/media/2020/05/flutter-colorfilter-merge-identity.jpg'),
        builder: (BuildContext context, AsyncSnapshot<ImageDetail> snapshot) {
          if (!snapshot.hasData) {
            return Container();
          }
  
          return Column(
            children: [
              Image.memory((snapshot.data?.bytes)!),
              Text('${snapshot.data?.width} x ${snapshot.data?.height}')
            ],
          );
        },
      );
    }
  }
  
  class GetImageDimensionsUsingImageDecoder extends StatelessWidget {
  
    const GetImageDimensionsUsingImageDecoder({Key? key}) : super(key: key);
  
    Future<ImageDetail> _getImageDimensions(String imageUrl) async {
      final response = await http.get(Uri.parse(imageUrl));
      final bytes = response.bodyBytes;
      final decodedImage = await decodeImageFromList(bytes);
  
      return ImageDetail(
        width: decodedImage.width,
        height: decodedImage.height,
        bytes: bytes,
      );
    }
  
    @override
    Widget build(BuildContext context) {
      return FutureBuilder(
        future: _getImageDimensions('https://www.woolha.com/media/2020/05/flutter-colorfilter-merge-identity.jpg'),
        builder: (BuildContext context, AsyncSnapshot<ImageDetail> snapshot) {
          if (!snapshot.hasData) {
            return Container();
          }
  
          return Column(
            children: [
              Image.memory((snapshot.data?.bytes)!),
              Text('${snapshot.data?.width} x ${snapshot.data?.height}')
            ],
          );
        },
      );
    }
  }
  
  class GetAssetImageDimensions extends StatelessWidget {
  
    const GetAssetImageDimensions({Key? key}) : super(key: key);
  
    Future<ImageDetail> _getImageDimensions(String assetPath) async {
      final byteData = await rootBundle.load(assetPath);
      final bytes = byteData.buffer.asUint8List();
      final decodedImage = await decodeImageFromList(bytes);
  
      return ImageDetail(
        width: decodedImage.width,
        height: decodedImage.height,
        bytes: bytes,
      );
    }
  
    @override
    Widget build(BuildContext context) {
      return FutureBuilder(
        future: _getImageDimensions('assets/images/flutter.png'),
        builder: (BuildContext context, AsyncSnapshot<ImageDetail> snapshot) {
          if (!snapshot.hasData) {
            return Container();
          }
  
          return Column(
            children: [
              Image.memory((snapshot.data?.bytes)!),
              Text('${snapshot.data?.width} x ${snapshot.data?.height}')
            ],
          );
        },
      );
    }
  }

Summary

There are several ways to get the dimensions of an image in Flutter. First, you can create an Image widget and add ImageStreamListener, which will be invoked when the image information becomes available. You can also get the ImageDescriptor from the bytes or decode the bytes to ui.Image to get the width and height values.

You can also read about: