拍摄视频快照时,Flutter中的图像尺寸无效

时间:2020-10-28 10:06:58

标签: image flutter dart video

我有一个Flutter应用,可从ESP32相机流式传输视频。我感兴趣的代码应该对图像进行快照。但是,当我按下按钮时,出现以下错误。

我尝试更改代码中的分辨率以及发送流的摄像机的分辨率。两者都给了我同样的错误。

有人可以帮助我吗?

E/flutter (22722): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: Exception: Invalid image dimensions.
E/flutter (22722): #0      Scene.toImage (dart:ui/compositing.dart:28:7)
E/flutter (22722): #1      OffsetLayer.toImage (package:flutter/src/rendering/layer.dart:1208:26)
E/flutter (22722): #2      RenderRepaintBoundary.toImage (package:flutter/src/rendering/proxy_box.dart:2960:24)
E/flutter (22722): #3      _HomeState.takeScreenShot (package:traincam/main.dart:173:32)
E/flutter (22722): #4      _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:993:19)
E/flutter (22722): #5      _InkResponseState.build.<anonymous closure> (package:flutter/src/material/ink_well.dart:1111:38)
E/flutter (22722): #6      GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:183:24)
E/flutter (22722): #7      TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:598:11)
E/flutter (22722): #8      BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:287:5)
E/flutter (22722): #9      BaseTapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:222:7)
E/flutter (22722): #10     PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:476:9)
E/flutter (22722): #11     PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:77:12)
E/flutter (22722): #12     PointerRouter._dispatchEventToRoutes.<anonymous closure> (package:flutter/src/gestures/pointer_router.dart:122:9)
E/flutter (22722): #13     _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:377:8)
E/flutter (22722): #14     PointerRouter._dispatchEventToRoutes (package:flutter/src/gestures/pointer_router.dart:120:18)
E/flutter (22722): #15     PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:106:7)
E/flutter (22722): #16     GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:358:19)
E/flutter (22722): #17     GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:338:22)
E/flutter (22722): #18     RendererBinding.dispatchEvent (package:flutter/src/rendering/binding.dart:267:11)
E/flutter (22722): #19     GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:295:7)
E/flutter (22722): #20     GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:240:7)
E/flutter (22722): #21     GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:213:7)
E/flutter (22722): #22     _rootRunUnary (dart:async/zone.dart:1206:13)
E/flutter (22722): #23     _CustomZone.runUnary (dart:async/zone.dart:1100:19)
E/flutter (22722): #24     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1005:7)
E/flutter (22722): #25     _invoke1 (dart:ui/hooks.dart:265:10)
E/flutter (22722): #26     _dispatchPointerDataPacket (dart:ui/hooks.dart:174:5)

代码如下:

import 'dart:ui';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:gesture_zoom_box/gesture_zoom_box.dart';
import 'package:web_socket_channel/io.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
import 'package:save_in_gallery/save_in_gallery.dart';

void main() {
    runApp(MyApp());
}
class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    return MaterialApp(
        debugShowCheckedModeBanner: false,
        theme: ThemeData.dark(),
        title: "Train Cam",
        home: Home(
        channel: IOWebSocketChannel.connect('ws://192.168.1.213:8888'),
        )
    );
    }
}

class Home extends StatefulWidget {
    final WebSocketChannel channel;
    Home({Key key, @required this.channel}) : super (key: key);
    @override
    _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
    final videoWidth = 640;
    final videoHeight = 480;
    double newVideoSizeWidth = 640;
    double newVideoSizeHeight = 480;
    bool isLandscape = false;
    String _timeString;
    var _globalKey = new GlobalKey();
    final _imageSaver = ImageSaver();
    @override
    void initState() {
    super.initState();
    isLandscape = false;
    }

    @override
    void dispose() {
    widget.channel.sink.close();
        super.dispose();
    }

    @override
    Widget build(BuildContext context) {
    return Scaffold(
        body: OrientationBuilder(
            builder: (context, orientation) {
                var screenWidth = MediaQuery.of(context).size.width;
                var screenHeight = MediaQuery.of(context).size.height;
                if (orientation == Orientation.portrait) {
                //screenWidth < screenHeight
                isLandscape = false;
                newVideoSizeWidth =
                screenWidth > videoWidth ? videoWidth : screenWidth;
                newVideoSizeHeight =
                videoHeight * newVideoSizeHeight / screenWidth;
                }
                else {
                isLandscape = true;
                newVideoSizeHeight =
                screenHeight > videoHeight ? videoHeight : screenHeight;
                newVideoSizeWidth =
                    videoWidth * newVideoSizeHeight / videoHeight;
                }
                return Container(
                color: Colors.black,
                child: StreamBuilder(
                    stream: widget.channel.stream,
                    builder: (context, snapshot) {
                    if (!snapshot.hasData) {
                        return Center(
                        child: CircularProgressIndicator(
                            valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
                        ),
                        );
                    } else {
                        return Row(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                            Column(
                            children: [
                                SizedBox(
                                height: isLandscape ? 0 : 30,
                                ),
                                Stack(
                                children: <Widget>[
                                    RepaintBoundary(
                                    key: _globalKey,
                                    ),
                                    GestureZoomBox(
                                    maxScale: 5.0,
                                    doubleTapScale: 2.0,
                                    duration: Duration(milliseconds: 200),
                                    child: Image.memory(
                                        snapshot.data,
                                        gaplessPlayback: true,
                                        width: newVideoSizeWidth,
                                        height: newVideoSizeWidth,
                                    ),
                                    ),
                                    Positioned.fill(
                                        child: Align(
                                    child: Column(
                                        children: <Widget>[
                                        SizedBox(
                                            height: 16,
                                        ),
                                        Text('Train Cam', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w300),),
                                        SizedBox(
                                            height: 8,
                                        ),
                                        Text('Live | $_timeString', style: TextStyle(fontSize: 12, fontWeight: FontWeight.w300),),
                                        ]
                                    ),
                                        alignment: Alignment.topCenter,
                                    ))
                                ],
                                ),
                                Expanded(flex: 1,
                                child: Container(
                                    color: Colors.black,
                                    width: MediaQuery.of(context).size.width,
                                    child: Padding(
                                    padding: const EdgeInsets.symmetric(vertical: 16),
                                    child: Row(
                                        crossAxisAlignment: CrossAxisAlignment.start,
                                        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                                        children: <Widget>[
                                        IconButton(icon: Icon(Icons.videocam, size: 24,), onPressed: () {  },),
                                        IconButton(icon: Icon(Icons.photo_camera, size: 24,), onPressed:  takeScreenShot,),
                                        IconButton(icon: Icon(Icons.mic, size: 24,), onPressed: () {  },),
                                        IconButton(icon: Icon(Icons.speaker, size: 24,), onPressed: () {  },),
                                        IconButton(icon: Icon(Icons.add_alert, size: 24,), onPressed: () {  },)
                                    ],
                                ),

                            )
                            ),)
                        ],
                        ),
                    ],
                    );
                }
                },
            ),
            );
        }
    )
    );
    }

    takeScreenShot()async{
    RenderRepaintBoundary boundary = _globalKey.currentContext.findRenderObject();
    var image = await boundary.toImage();
    var byteData = await image.toByteData(format: ImageByteFormat.png);
    var pngBytes = byteData.buffer.asUint8List();
    final res = await _imageSaver.saveImage(imageBytes: pngBytes);
    Fluttertoast.showToast(msg: res? "Screenshot saved" : "Screenshot failed!",
        toastLength: Toast.LENGTH_SHORT,
        gravity: ToastGravity.CENTER,
        timeInSecForIosWeb: 1,
        backgroundColor: Colors.red,
        textColor: Colors.white,
        fontSize: 16.0);
}
}

1 个答案:

答案 0 :(得分:0)

拍摄视频快照时 Flutter 中的图像尺寸无效, 这意味着您需要为错误小部件设置约束 例如:

我对以下代码有同样的问题:

Widget carIconImage =
              Image.asset(BYDConstants().getBydImageHome("box.png"));

用具有宽度和高度的容器包裹,问题解决了。

Widget carIconImage =
                    Container(width:30,height:30,child: Image.asset(BYDConstants().getBydImageHome("box.png")),);