Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Null Safety on exportImage #10

Closed
ccc-dvansevenant opened this issue Jun 25, 2021 · 10 comments
Closed

Null Safety on exportImage #10

ccc-dvansevenant opened this issue Jun 25, 2021 · 10 comments

Comments

@ccc-dvansevenant
Copy link

ccc-dvansevenant commented Jun 25, 2021

Thanks for this library, and starting to migrate it to null safety.

I am using image_painter: ^1.0.0-nullsafety.0.

My project is set with:

environment:
  sdk: ">=2.12.0 <3.0.0"

As I was implementing image_painter in my project, I was having issues with exportImage.

It kept complaining about ByteData, and then buffer. Eventually I hit upon this combination:

  ///Generates [Uint8List] of the [ui.Image] generated by the [renderImage()] method.
  ///Can be converted to image file by writing as bytes.
  Future<Uint8List?> exportImage() async {
    ui.Image _image;
    if (widget.isSignature) {
      final _boundary = _repaintKey.currentContext!.findRenderObject()
          as RenderRepaintBoundary;
      _image = await _boundary.toImage(pixelRatio: 3);
    } else if (widget.byteArray != null && _paintHistory.isEmpty) {
      return widget.byteArray;
    } else {
      _image = await _renderImage();
    }
    final byteData = await (_image.toByteData(format: ui.ImageByteFormat.png) as FutureOr<ByteData?>);
    return byteData?.buffer.asUint8List();

Note the last 2 lines, specifically.

I don't know if it's correct or not, but thought I'd pass it along in case it helps.

I'm still learning, very slowly, so it's certainly possible this could be done better.

@lively-bigyan
Copy link
Collaborator

Thank you for opening up the issue and bringing it to my attention. I will definitely take a look at it.

@lively-bigyan
Copy link
Collaborator

I am not able to reproduce the issue. It would be much faster and easier for us to fix the issue if you could provide the following informations.

  • flutter version and device,
  • Steps to reproduce and
  • error log

@ccc-dvansevenant
Copy link
Author

Sorry for the delay. Thanks for the quick reply. Here's my discovery process. Might be a bit verbose, but I want to cover the bases in case I did something wrong.

Using Android Studio 4.2.2 (was 4.2.1 when this started)
Flutter v2.2.3 (was 2.2.2)
Mac OS X Catalina

E/flutter (16431): [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: Unable to load asset: assets/sample.jpg
E/flutter (16431): #0      PlatformAssetBundle.load (package:flutter/src/services/asset_bundle.dart:224:7)
E/flutter (16431): <asynchronous suspension>
E/flutter (16431): #1      ImagePainterState._resolveAndConvertImage (package:image_painter/src/paint_over_image.dart:211:19)
E/flutter (16431): <asynchronous suspension>
E/flutter (16431): 
  • fix by creating /assets, adding a file called sample.jpg and editing pubspec.yml and adding:
assets:
  - sample.jpg

(Really, a non-issue, since that part will be replaced by loading an actual image)

  • Run app on emulator and draw, then save.

  • Note error message about Future<Uint8List?> not being a subtype of <FutureOr<Uint8List>

E/flutter ( 4984): [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: type 'Future<Uint8List?>' is not a subtype of type 'FutureOr<Uint8List>' in type cast 

From the saveImage function:

void saveImage() async {  
final image =  
    await (_imageKey.currentState!.exportImage() as FutureOr<Uint8List>);  
final directory = (await getApplicationDocumentsDirectory()).path;

The FutureOr is not liked.
I removed it in my code.
The line became:

final Uint8List? image = await (_imageKey.currentState!.exportImage());

Which then causes an issue with image:

final imgFile = File('$fullPath');  
imgFile.writeAsBytesSync(image);  
ScaffoldMessenger.of(context).showSnackBar(

So, add a null check:

imgFile.writeAsBytesSync(image!);

Running again:

E/flutter ( 6142): [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: type 'Future<ByteData?>' is not a subtype of type 'FutureOr<ByteData>' in type cast
E/flutter ( 6142): #0      ImagePainterState.exportImage (package:image_painter/src/paint_over_image.dart:464:5)
E/flutter ( 6142): <asynchronous suspension>
E/flutter ( 6142): #1      _ImagePainterExampleState.saveImage (package:image_painter_null_safety_test/main.dart:57:30)
E/flutter ( 6142): <asynchronous suspension>
E/flutter ( 6142): 

Modifying paint_over_image.dart line 463-464 gets rid of that error:

final byteData = await (\_image.toByteData(format: ui.ImageByteFormat.png)  
as FutureOr<ByteData?>);

But introduces an error about buffer:

/usr/local/Caskroom/flutter/2.0.4/flutter/.pub-cache/hosted/pub.dartlang.org/image_painter-1.0.0-nullsafety.0/lib/src/paint_over_image.dart:465:21: Error: Property 'buffer' cannot be accessed on 'ByteData?' because it is potentially null.
 - 'ByteData' is from 'dart:typed_data'.
Try accessing using ?. instead.
    return byteData.buffer.asUint8List();
                    ^^^^^^

So, modifying 465, as suggested:

return byteData?.buffer.asUint8List();

Seems to make it all work without complaint. But, again, do not know if it is the right way.

@dchrzanowski
Copy link

Flutter 2.5.1, dart 2.14.2

@lively-bigyan

I'm working with this library at the moment and can confirm that I have the same issue as @ccc-dvansevenant. Can also confirm that changing the paint_over_image.dart file (line 464/465) from:

final byteData = await (_image.toByteData(format: ui.ImageByteFormat.png)
    as FutureOr<ByteData>);
return byteData.buffer.asUint8List();

To:

final byteData = await (_image.toByteData(format: ui.ImageByteFormat.png)
    as FutureOr<ByteData?>);
return byteData?.buffer.asUint8List();

Does fix the problem.

Should I create a PR or are you ok fixing this @lively-bigyan ?

@lively-bigyan
Copy link
Collaborator

@dchrzanowski Thank you for the tests and the solution. I am currently working on some new features of the package so I couldn't push the fixes sooner. I shall fix it today.

@lively-bigyan
Copy link
Collaborator

lively-bigyan commented Oct 5, 2021

On second thought, I just realized that I had it fixed on 0.4.0. Have you guys tried that version? @dchrzanowski @ccc-dvansevenant

@ccc-dvansevenant
Copy link
Author

On second thought, I just realized that I had it fixed on 0.4.0. Have you guys tried that version? @dchrzanowski @ccc-dvansevenant

I've had to set aside that part of my project for a while, so I haven't updated anything. I'll try to have a look soon. Thanks!

@dchrzanowski
Copy link

@lively-bigyan I did not realize that 0.4.0 was null safety ready. I'll check it out tomorrow morning so.

@dchrzanowski
Copy link

On second thought, I just realized that I had it fixed on 0.4.0. Have you guys tried that version? @dchrzanowski @ccc-dvansevenant

0.4.0 works like a charm! Thanks @lively-bigyan!

@lively-bigyan
Copy link
Collaborator

Not a problem. Glad it helped.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants