How to use an UI Image as an Image Provider Data Source

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

The Photovoice framework accepts an Asset Image as a type of provider but not any of the other Image Provider types.

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;
  }
}

This Post Has One Comment

  1. No Fault

    Pass your Model to ImageRow struct which contains url.

    import SwiftUI
    import Combine

    struct ContentView : View {
    var listData: Post
    var body: some View {
    List(model.post) { post in
    ImageRow(model: post) // Get image
    }
    }
    }

    /********************************************************************/
    // Download Image

    struct ImageRow: View {
    let model: Post
    var body: some View {
    VStack(alignment: .center) {
    ImageViewContainer(imageUrl: model.avatar_url)
    }
    }
    }

    struct ImageViewContainer: View {
    @ObjectBinding var remoteImageURL: RemoteImageURL

    init(imageUrl: String) {
    remoteImageURL = RemoteImageURL(imageURL: imageUrl)
    }

    var body: some View {
    Image(uiImage: UIImage(data: remoteImageURL.data) ?? UIImage())
    .resizable()
    .clipShape(Circle())
    .overlay(Circle().stroke(Color.black, lineWidth: 3.0))
    .frame(width: 70.0, height: 70.0)
    }
    }

    class RemoteImageURL: BindableObject {
    var didChange = PassthroughSubject()
    var data = Data() {
    didSet {
    didChange.send(data)
    }
    }
    init(imageURL: String) {
    guard let url = URL(string: imageURL) else { return }

    URLSession.shared.dataTask(with: url) { (data, response, error) in
    guard let data = data else { return }

    DispatchQueue.main.async { self.data = data }

    }.resume()
    }

Leave a Reply