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

decodePng returns empty buffer #422

Open
Mmisiek opened this issue Oct 31, 2022 · 15 comments
Open

decodePng returns empty buffer #422

Mmisiek opened this issue Oct 31, 2022 · 15 comments

Comments

@Mmisiek
Copy link

Mmisiek commented Oct 31, 2022

The decodePng used to work nicely with my PNG file in previous versions of Flutter.
ByteData bytes = await rootBundle.load('images/pestscope_tm.png'); logoImage = image.decodePng(bytes.buffer.asUint8List());
Suddenly it decodes PNG file, the size is set, and some other data too, but buffer is full of zeros:
Image blendMethod: BlendMode (BlendMode.over) channels: Channels (Channels.rgba) data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... disposeMethod: DisposeMode (DisposeMode.clear) duration: 0 exif: ExifData height: 82 iccProfile: ICCProfileData textData: null width: 480 xOffset: 0 yOffset: 0 hashCode: 780885460 length: 39360 numberOfChannels: 4 runtimeType: Type (Image)
I tried different methods and still getting zeros.

@brendan-duncan
Copy link
Owner

I'm not sure why you would be getting all zeros. The PNG unit tests are working. Is it a particular image that's failing?

@Mmisiek
Copy link
Author

Mmisiek commented Oct 31, 2022

The thing is it was working perfectly before, after recent Flutter upgrades it fails. I attached PNG for test.
pestscope_tm

@brendan-duncan
Copy link
Owner

The png loads fine when I just tested it. I'm having a hard time thinking what a Flutter update might be doing to zero out the image bytes. Do all pngs have the same behavior for you?

@Mmisiek
Copy link
Author

Mmisiek commented Oct 31, 2022

I loaded one of your test PNGs and got different results but it still failed same way:
blendMethod: BlendMode (BlendMode.over) channels: Channels (Channels.rgba) data: [4278255615, 4278255614, 4278255614, 4278255614, 4278255613, 4278255612, 4278255611, 4278255610, 4278255609, 4278255608, 4278255607, 4278255606, 4278255605, 4278255604, 4278255603, 4278255602, 4278255601, 4278255600, 4227923951, 4227923950, 4227923949, 4227923948, 4194369515, 4177592298, 4160815081, 4110483432, 4076928999, 4060151782, 4026597349, 4026597348, 4026597347, 4026597346, 4026597344, 4026597343, 4026597342, 4026597341, 4026597340, 4026597339, 4026597338, 4026597337, 4026597336, 4026597335, 4026597334, 4026597333, 4026597332, 4026597331, 4026597330, 4009820113, 4009820112, 4009820111, 4009820110, 4009820109, 4009820108, 4009820107, 3993042890, 3993042889, 3942711240, 3925934023, 3925934022, 3875602373, 3875602372, 3875602371, 3875602370, 3875602369, 3875602367, 3875602366, 3875602365, 3875602364, 3875602363, 3875602362, 3875602361, 3875602360, 3858825143, 3858825142, 3858825141, 3858825140, 3858825139, 3858825138, 3858825137, 3858825136, 3858825135, 3858825134, 3858825133, 3858825132, 3858825131, 385... disposeMethod: DisposeMode (DisposeMode.clear) duration: 0 exif: ExifData height: 256 iccProfile: null textData: null width: 256 xOffset: 0 yOffset: 0 hashCode: 385902476 length: 65536 numberOfChannels: 4 runtimeType: Type (Image)

And it fails later when I want to load it to MemoryImage:
E/flutter ( 8669): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Exception: Unable to guess the image type 262144 bytes E/flutter ( 8669): #0 new MemoryImage

@Mmisiek
Copy link
Author

Mmisiek commented Oct 31, 2022

I think problem is with data type. I pass image as UInt8 but decodeImage(Png) takes List which is 64 bit long.
I tried 64 bits asInt64 but failed to get anything then.

@brendan-duncan
Copy link
Owner

The library should definitely take a Uint8List. List is just the abstract base class. It seems to be decoding the PNG ok; the resolution is set, it's not crashing. But why the image pixels are all 0 in your image is strange. The pixels are not all 0 in the other test image.

When you say "load it to MemoryImage", are you re-encoding the image back to a PNG?

@Mmisiek
Copy link
Author

Mmisiek commented Oct 31, 2022

So I am trying to add images to PDF using the pdf package. This was working perfectly until I updated packages and flutter.
The image is loaded from assets:

import 'package:image/image.dart' as img;
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;

img.Image logoImage;
ByteData bytes = await rootBundle.load('images/pestscope_tm.png');
final bytesList = bytes.buffer.asInt64List();
logoImage = img.PngDecoder().decodeImage(bytesList);`

Then I am trying to create a PDF-based image, so I can add it to PDF. It used to accept Image now needs ImageProvider:

                          child: pw.FittedBox(
                            child:
                                pw.Image(pw.MemoryImage(logoImage.getBytes())),
                          ),

But this fails as MemoryImage can't detect image type as the buffer is full of "0". I tried to step into the image package, but it was very slow. Maybe I need to write some test app to check it? If any PNG fails to decode, I will try JPG etc too. I have a feeling that there is some mixing of packages happening.
Thank you for your package and support!

@brendan-duncan
Copy link
Owner

It probably doesn't matter because the numbers will be the same, but you should use a Uint8List and not a Int64List for bytesList. In the very least, it will use less memory.

I haven't used Flutter, or the PDF package, so I don't know thoise APIs very well, but I believe MemoryImage probably should be an encoded PNG. logoImage.getBytes() is the raw bytes of the image. it doesn't have any of the other information such as format or resolution. So I would think you'd want to do something like pw.MemoryImage(img.encodePNG(logoImage))

Or, if you're not doing anything to modify the image, do you even need to use the image library?

ByteData bytes = await rootBundle.load('images/pestscope_tm.png');
// ...
 pw.Image(pw.MemoryImage(bytes)),

@Mmisiek
Copy link
Author

Mmisiek commented Oct 31, 2022

Just out of curiosity what are you using Dart for ?
So I followed you advice and skip decoding phase. This solves my issue but does not explain why I get "0" in buffer after decode. I might try to build some test code to figure it out.

                         child: pw.FittedBox(
                            child: pw.Image(
                                pw.MemoryImage(logoBytes.buffer.asUint8List())),
                          ),

@brendan-duncan
Copy link
Owner

I wrote this library a long time ago, 2013 or so, when I was using Dart for some web projects. Dart is still a great language, but I don't use it for anything anymore, I just try to maintain the couple of libraries I published that people use.

It is curious why the image is decoding black. I'm glad you got unstuck. Not decoding/re-encoding the image will save you considerable performance.

@Mmisiek
Copy link
Author

Mmisiek commented Nov 1, 2022

This is a great library and is used by TFLITE package, so I need to use it in my project. I found out that images from my phone are decoded empty, and images from the internet or screenshots work just fine.
I noticed that camera pictures do not have iccProfile set but they have exif, the images from PC the other way around.
The images without iccProfile set come back as white. Any idea about that? I really would like it to work.

@brendan-duncan
Copy link
Owner

If you can send me an example image file that doesn't work, I can get it to work. The ICC profile or the EXIF data should impact the PNG pixels decoding or not, so there must be something else about the images from the phone, but I have no idea what.

@Mmisiek
Copy link
Author

Mmisiek commented Nov 1, 2022

Thanks a lot! Here is the working image: https://photos.app.goo.gl/k4uwrZgtKHutPX1a7
Here is an image from my phone not working: https://photos.app.goo.gl/5Hksnjj42YaXu6Y49
I pull both from the network via ImagePicker, then decode, resize, etc. The second one comes as a white square.

@brendan-duncan
Copy link
Owner

I got a chance to look into this, but both images stored on google photos are stored as JPEG, and I didn't have a problem loading either. I assume these are not the actual photos you're using in the app, since you were talking about PNG images.

@Mmisiek
Copy link
Author

Mmisiek commented Nov 2, 2022

So I solved the issue with PNG images as mentioned above by skipping the use of decode completely (as you suggested).
Those Jpegs are actually used in app, I load them to download them to app as a file, and then decode them to an image.
The first one comes out blank, the other not. I have no idea what it can be. Seems like some odd behavior.
I should try to write a test program to check which external package messes up with this behavior.

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

No branches or pull requests

2 participants