How to use an ui.Image as an ImageProvider data source

8,024

PhotoView author here, the widget works fine with all ImageProvider (Memory and File extend ImageProvider).

The problem is how you are creating the provider. image.buffer.asUint8List() prints a headless map of bits, making it impossible to display. The head of a bitmap contains information such size of each pixel (in bits) and the size of the image (in pixels). I've actually created a whole package around that.

With bitmap package, you can retrieve a headful file from an ui.Image instance:

First, create a bitmap instance:

ByteData bytedata = await image.toByteData();
Bitmap bitmap = Bitmap.fromHeadless(imageWidth, imageHeight, bytedata.buffer.asUint8List());

Then, recover the final map of bits:

Uint8List headedIntList = bitmap.buildHeaded();

Now you can pass it into PhotoView:

PhotoView(imageProvider: headedIntList)
Share:
8,024
Yarm
Author by

Yarm

Updated on December 15, 2022

Comments

  • Yarm
    Yarm over 1 year

    I can set a standard flutter image from memory or from a file, but not an ImageProvider as required by the PhotoView framework.

    The PhotoView framework accepts an AssetImage as a type of provider but not any of the other ImageProvider types (File and Memory).

    What might be a workaround? I'd think the framework would support image sources other than from a project's assets

    import 'package:flutter/material.dart';
    import 'package:path_provider/path_provider.dart';
    import 'package:photo_view/photo_view.dart';
    import 'package:flutter/services.dart' show rootBundle;
    import 'dart:convert';
    
    import 'dart:ui' as ui;
    import 'dart:typed_data';
    import 'dart:async';
    import 'dart:io';
    
    
    class TestImageDraw extends StatefulWidget {
      TestImageDraw({Key key, this.title}) : super(key: key);
      final String title;
    
      @override
      _TestImageDrawState createState() => _TestImageDrawState();
    }
    
    class _TestImageDrawState extends State<TestImageDraw> {
      ImageProvider _imageProvider;
    
      @override
      void initState() {
        super.initState();
    
        _imageProvider = NetworkImage(
            "https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png");
      }
    
      _generateImage() {
        GenImage.generateImage().then((generatedImage) async {
          ByteData image =
              await generatedImage.toByteData(format: ui.ImageByteFormat.png);
    
          // String base64 = base64Encode(image.buffer.asInt64List());
          // print(base64);
          // Uint8List bytes = base64Decode(base64);
          // _imageProvider = MemoryImage(bytes);
    
          _imageProvider = MemoryImage(image.buffer.asUint8List());
    
          setState(() {});
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return new Scaffold(
          appBar: new AppBar(
            title: new Text(widget.title),
          ),
          body: Container(
              child: Column(children: <Widget>[
            //Image will display
            Image(image: _imageProvider),
            Container(
                child: _imageProvider != null
                    ? PhotoView(imageProvider: _imageProvider)
                    : Container()),
          ])),
          floatingActionButton: new FloatingActionButton(
            onPressed: _generateImage,
            tooltip: 'Generate',
            child: new Icon(Icons.add),
          ),
        );
      }
    }
    
    class GenImage {
      static Future<ui.Image> generateImage() async {
        ui.PictureRecorder recorder = new ui.PictureRecorder();
        Canvas c = new Canvas(recorder);
        var rect = new Rect.fromLTWH(0.0, 0.0, 200.0, 200.0);
        c.clipRect(rect);
    
        final paint = new Paint();
        paint.strokeWidth = 1;
        paint.color = const Color(0xFF0000FF);
        paint.style = PaintingStyle.stroke;
    
        final offset = new Offset(100.0, 100.0);
        c.drawCircle(offset, 50.0, paint);
        var picture = recorder.endRecording();
        final image = await picture.toImage(500, 500);
        return image;
      }
    }