6

我可以从内存或文件中设置标准颤动图像,但不能像 PhotoView 框架所要求的那样设置 ImageProvider。

PhotoView 框架接受 AssetImage 作为提供程序类型,但不接受任何其他 ImageProvider 类型(文件和内存)。

什么可能是解决方法?我认为该框架将支持项目资产以外的图像源

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

2 回答 2

4

PhotoView 作者在这里,该小部件适用于所有 ImageProvider(内存和文件扩展 ImageProvider)。

问题是您如何创建提供程序。image.buffer.asUint8List()打印无头位图,使其无法显示。位图的头部包含每个像素的大小(以位为单位)和图像的大小(以像素为单位)等信息。我实际上已经围绕它创建了一个完整的包。

使用bitmap packageui.Image ,您可以从实例中检索 headful 文件:

首先,创建一个位图实例:

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

然后,恢复最终的位图:

Uint8List headedIntList = bitmap.buildHeaded();

现在您可以将其传递给 PhotoView:

PhotoView(imageProvider: headedIntList)
于 2019-11-27T10:28:41.580 回答
0

编辑您的新代码运行良好,但您看不到这个圆圈,因为 paint.strokeWidth 为 1 请更改为 10
在新的完整代码中,我也PhotoView使用Container并设置height

代码片段paint.strokeWidth = 10

final paint = new Paint();
paint.strokeWidth = 10;
paint.color = const Color(0xFF0000FF);
paint.style = PaintingStyle.stroke;

新的完整代码

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

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application
        // is not restarted.
        primarySwatch: Colors.blue,
      ),
      home: TestImageDraw(
        title: "test",
      ),
    );
  }
}

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: SingleChildScrollView(
        child: Container(
            child: Column(children: <Widget>[
              //Image will display
              //Image(image: _imageProvider),
              Container(
                  height: 300,
                  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 = 10;
    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;
  }
}

在此处输入图像描述

照片视图可以正常工作MemoryImage,您可以在下面复制粘贴运行完整代码
您遇到的错误可能是显示时图像未准备好
您可以检查pngBytes == null return Container()
代码片段

 children: <Widget>[
            bytes == null
                ? Container()
                : Expanded(
                    flex: 1,
                    child: PhotoView(
                      imageProvider: MemoryImage(bytes),
                    ),
                  ),

工作演示动画 gif

在此处输入图像描述

完整代码

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:photo_view/photo_view.dart';
import 'package:http/http.dart' as http;
import 'dart:typed_data';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application
        // is not restarted.
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  // This widget is the home page of your application. It is stateful, meaning
  // that it has a State object (defined below) that contains fields that affect
  // how it looks.

  // This class is the configuration for the state. It holds the values (in this
  // case the title) provided by the parent (in this case the App widget) and
  // used by the build method of the State. Fields in a Widget subclass are
  // always marked "final".

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  String _base64;
  Uint8List bytes;

  void _incrementCounter() {
    (() async {
      http.Response response = await http.get(
        'https://picsum.photos/250?image=9',
      );
      if (mounted) {
        setState(() {
          _base64 = base64Encode(response.bodyBytes);
          print(_base64);
          bytes = base64Decode(_base64);
        });
      }
    })();
  }

  @override
  void initState() {
    super.initState();
   /* (() async {
      http.Response response = await http.get(
        'https://picsum.photos/250?image=9',
      );
      if (mounted) {
        setState(() {
          _base64 = base64Encode(response.bodyBytes);
          print(_base64);
          bytes = base64Decode(_base64);
        });
      }
    })();*/
  }


  @override
  Widget build(BuildContext context) {
    // This method is rerun every time setState is called, for instance as done
    // by the _incrementCounter method above.
    //
    // The Flutter framework has been optimized to make rerunning build methods
    // fast, so that you can just rebuild anything that needs updating rather
    // than having to individually change instances of widgets.
    return Scaffold(
      appBar: AppBar(
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: Text(widget.title),
      ),
      body: Center(
        // Center is a layout widget. It takes a single child and positions it
        // in the middle of the parent.
        child: Column(
          // Column is also a layout widget. It takes a list of children and
          // arranges them vertically. By default, it sizes itself to fit its
          // children horizontally, and tries to be as tall as its parent.
          //
          // Invoke "debug painting" (press "p" in the console, choose the
          // "Toggle Debug Paint" action from the Flutter Inspector in Android
          // Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
          // to see the wireframe for each widget.
          //
          // Column has various properties to control how it sizes itself and
          // how it positions its children. Here we use mainAxisAlignment to
          // center the children vertically; the main axis here is the vertical
          // axis because Columns are vertical (the cross axis would be
          // horizontal).
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            bytes == null
                ? Container()
                : Expanded(
                    flex: 1,
                    child: PhotoView(
                      imageProvider: MemoryImage(bytes),
                    ),
                  ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}
于 2019-11-27T05:47:35.220 回答