19

I have this scenario where I have to get a UInt8List from an image like that:

List stuff = image.toByteData().buffer.asUInt8List()

Do some manipulations and get back to a Image.

I've tried the following:

List stuff = image.toByteData().buffer.asUInt8List()
ui.decodeImageFromList(stuff, (image){
  // do stuff with image
});

But I keep getting this Exception:

E/flutter (10201): [ERROR:flutter/lib/ui/painting/codec.cc(97)] Failed decoding image. Data is either invalid, or it is encoded using an unsupported format.
E/flutter (10201): [ERROR:flutter/shell/common/shell.cc(186)] Dart Error: Unhandled exception:
...

Take notice that even without any changes in the List the exception is thrown. How can I make the list have a encodable format?

Renan C. Araujo
  • 840
  • 2
  • 9
  • 14

6 Answers6

48

You can use memory image as given below, for the direct byte rendering

child: Image.memory(Uint8List bytes);
Kishan Donga
  • 2,851
  • 2
  • 23
  • 35
8

You can use MemoryImage class to convert a Uint8List to image.

var _image = MemoryImage(image);

You can find more details about this class here

Firosh Vasudevan
  • 671
  • 10
  • 11
5

ui.Image can turn itself into an RGBA bitmap (or PNG), but cannot convert itself back from a bitmap. (The reason for this is that there isn't any way to tell the image codec things like the color depth, geometry, etc.) The solution is to add a BMP file header onto the front of your bitmap, where you can describe those missing things, then pass that to instantiateImageCodec. See this answer, but note that in that case the bitmap in question had a strange packed color map. In your case of 32 bit RGBA, the header would be even simpler.

Richard Heap
  • 48,344
  • 9
  • 130
  • 112
  • 4
    After this answer, I started to work on something to make this easier. I'm converting Uint8List into Image with Bitmap, a package I've made. Thanks. https://github.com/renancaraujo/bitmap/ – Renan C. Araujo Sep 03 '19 at 19:09
5

use this.

static Future<ui.Image> bytesToImage(Uint8List imgBytes) async{
    ui.Codec codec = await ui.instantiateImageCodec(imgBytes);
    ui.FrameInfo frame;
    try {
      frame = await codec.getNextFrame();
    } finally {
      codec.dispose();
    }
    return frame.image;
  }
Luke Hutchison
  • 8,186
  • 2
  • 45
  • 40
Ali Bagheri
  • 3,068
  • 27
  • 28
1

Here is a tested code for you.

    final directory = await getApplicationDocumentsDirectory();
    final pathOfImage = await File('${directory.path}/legendary.png').create();
    final Uint8List bytes = stuff.buffer.asUint8List();
    await pathOfImage.writeAsBytes(bytes);

final Uint8List bytes = stuff.buffer.asUint8List();

Here, stuff refers to the Uint8List that should be converted to an image.

Shaan Mephobic
  • 1,148
  • 2
  • 7
  • 15
1

this method worked for me, got the reference from another answer to a similar kind of problem at stackoverflow here

Future<ui.Image> loadImage(Uint8List img) async {
    final Completer<ui.Image> completer = Completer();
    ui.decodeImageFromList(img, (ui.Image img) {
      return completer.complete(img);
    });
    return completer.future;
  }