Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I draw a image loaded from an asset on a Canvas object

Tags:

flutter

dart

I'm toying with Flutter and I have implemented a custom-drawn widget using CustomPainter class.

Primitives are quite well documented. However, it seems that there's Image (the widget) and Image (the data structure), because if I istantiate an Image (the widget) I cannot pass it to the Canvas method drawImage because it needs another type of Image.

Problem is, I cannot wrap my head on how to load a resource into an Image data structure.

Has anyone tackled this problem?

[edit] Thanks to rmtmckenzie I solved it this way:

rootBundle.load("assets/galaxy.jpg").then( (bd) {
  Uint8List lst = new Uint8List.view(bd.buffer);
  UI.instantiateImageCodec(lst).then( (codec) {
    codec.getNextFrame().then(
      (frameInfo) {
        bkImage = frameInfo.image;
        print ("bkImage instantiated: $bkImage");
        }
      }
    );
  });
});
like image 968
Max Lambertini Avatar asked Dec 05 '22 12:12

Max Lambertini


2 Answers

A working solution:

import 'dart:async';
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/services.dart' show rootBundle;

/// Load [Image] from asset path.
/// https://stackoverflow.com/a/61338308/1321917
Future<ui.Image> loadUiImage(String assetPath) async {
  final data = await rootBundle.load(assetPath);
  final list = Uint8List.view(data.buffer);
  final completer = Completer<ui.Image>();
  ui.decodeImageFromList(list, completer.complete);
  return completer.future;
}
like image 76
Andrey Gordeev Avatar answered Jun 07 '23 14:06

Andrey Gordeev


To do this, you need to load the image directly, and then instantiate it.

I'll leave the loading part up to you - you're either going to have to do an Http request directly or use AssetBundle.load; or you could possibly use a NetworkImage/AssetImage (which both inherit ImageProvider - see the docs which contain an example).

If you take the loading directly route, you can then instantiate an image (in the form of a codec -> frame -> image) using instantiateImageCodec.

If you take the other route, you have to listen to streams etc as it is done in the docs, but you should get an Image directly.

Edit: Thanks to the OP who has included the working code in his question. Here is what worked for him:

rootBundle.load("assets/galaxy.jpg").then( (bd) {
  Uint8List lst = new Uint8List.view(bd.buffer);
  UI.instantiateImageCodec(lst).then( (codec) {
    codec.getNextFrame().then(
      (frameInfo) {
        bkImage = frameInfo.image;
        print ("bkImage instantiated: $bkImage");
        }
      }
    );
  });
});
like image 44
rmtmckenzie Avatar answered Jun 07 '23 14:06

rmtmckenzie