4Q-s-r-o / signature

Flutter plugin that creates a canvas for writing down a signature
MIT License
255 stars 85 forks source link

`toPngBytes` throws with Exception #68

Closed KirioXX closed 2 years ago

KirioXX commented 2 years ago

Hi, I try to export a signature as a png byte but I always get this exception: VERBOSE-2:dart_vm_initializer.cc(41)] Unhandled Exception: 'package:signature/signature.dart': Failed assertion: line 413 pos 9: '((width ?? defaultWidth!) - defaultWidth!) >= 0.0': Exported width cannot be smaller than actual width

This is my widget:

class SignaturePage extends StatefulWidget {
  const SignaturePage({Key? key}) : super(key: key);

  @override
  State<SignaturePage> createState() => _SignaturePageState();
}

class _SignaturePageState extends State<SignaturePage> {
  final SignatureController _controller = SignatureController(
    penStrokeWidth: 5,
    penColor: Colors.black,
    exportBackgroundColor: Colors.transparent,
  );

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<SendMeToTheMoonBloc, SendMeToTheMoonState>(
      builder: (context, stateMoon) {
        return Scaffold(
          body: SafeArea(
            child: Container(
              padding: const EdgeInsets.only(top: 20, left: 15, right: 20),
              child: BlocBuilder<SignOffBloc, SignOffState>(
                builder: (context, state) {
                  return Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Text('Thanks, ${state.signOffSigner!.firstName}.'),
                      const Text('Can you sign here to complete the job?'),
                      const SizedBox(height: 20),
                      LayoutBuilder(builder: (context, constraints) {
                        return ConstrainedBox(
                          constraints: BoxConstraints(
                            maxWidth: constraints.maxWidth,
                            maxHeight: 500,
                          ),
                          child: Card(
                            child: Stack(
                              children: [
                                const Padding(
                                  padding: EdgeInsets.all(8.0),
                                  child: Text('Signature'),
                                ),
                                Signature(
                                  controller: _controller,
                                  backgroundColor: Colors.transparent,
                                ),
                              ],
                            ),
                          ),
                        );
                      }),
                      Center(
                        child: ElevatedButton(
                          onPressed: () async {
                            final image = await _controller.toPngBytes();
                            if (image != null && mounted) {
                              final signature = UploadImage(
                                bucket: 'some_bucket',
                                filePath: 'some/path',
                                file: image,
                              );
                              context.read<SendMeToTheMoonBloc>().add(
                                    SignatureSubmitted(
                                      signature: signature,
                                    ),
                                  );
                            }
                          },
                          child: const Icon(Icons.arrow_forward),
                        ),
                      )
                    ],
                  );
                },
              ),
            ),
          ),
        );
      },
    );
  }
}

Is there something that I'm doing wrong when I wrap the signature? Thanks!

yurtemre7 commented 2 years ago

No you are not doing something wrong, its the toPngBytes method which sets fixed height and width values. Current workaround would be something like this:

ui.Image? img = await _controller?.toImage(
  height: _controller?.defaultHeight ?? 0,
  width: _controller?.defaultWidth ?? 0
);

ByteData? byteData = await img?.toByteData(
  format: ui.ImageByteFormat.png
);

// Image data
var data = byteData?.buffer.asUint8List();

Where ui.Image is from import 'dart:ui' as ui;

KirioXX commented 2 years ago

Awesome! Thanks, @yurtemre7. That seems to do the trick, what is odd though is that it sometimes worked without any issues.

yurtemre7 commented 2 years ago

Yeah I dont know, hope my PR #69 goes through then we will have a nice updated package and the new toPngBytes method

DmitrySikorsky commented 2 years ago

For now you can just use version 5.0.1. It doesn't contain this bug.

echb commented 2 years ago
    //WIDTH AND HEIGHT IS OPTIONAL. IMAGE WILL BE CENTERED
    final ui.Image? image = await toImage(height: 500, width: 400);  // --> Here is the issue

Height and width by default are set, so, when u set a higher value on the widget it breaks @yurtemre7 PR #69 might fix the issue, @DmitrySikorsky .

MartinHlavna commented 2 years ago

Hi

sorry for late response, we did not have available maintenance window for a while. I am looking at PR #69 right now

MartinHlavna commented 2 years ago

Fixed in 5.3.0