yekeskin / flutter_avif

A flutter plugin to view and encode avif images.
https://pub.dev/packages/flutter_avif
MIT License
61 stars 17 forks source link

Encoding on Web breaks the image #59

Closed enqvida closed 1 month ago

enqvida commented 1 month ago

Not sure where the issue is coming from. I'm clearly doing something wrong. Help :D

Screenshot 2024-10-04 at 13 05 32

`

final ByteData byteData = await rootBundle.load(assetPath);
final Uint8List inputBytes = byteData.buffer.asUint8List();
final Uint8List avifBytes = await encodeAvif(inputBytes);
final uniqueFileName = '${nanoid()}.avif';

final supabase = Supabase.instance.client;

await supabase.storage.from(bucketName).uploadBinary(
      uniqueFileName,
      avifBytes,
      fileOptions: const FileOptions(
        contentType: 'image/avif', 
      ),
    );
michaelnew commented 1 month ago

Yeah I'm seeing this too. The output resembles the input image but it's garbled. So it's not failing outright; it's just messing up the conversion somehow. I'd try to debug it but I'm not really sure yet how to look into the rust/wasm side of things.

yekeskin commented 1 month ago

It looks like there might be an issue with width/height detection. All my original test images for this were square images and I couldn't replicate the issue. Then I tried with a non square image and I got the same broken result.

michaelnew commented 1 month ago

Ah yep, I can replicate that. Works fine with a square-cropped image, and becomes increasingly more garbled as the aspect ratio grows.

michaelnew commented 1 month ago

Okay I poked around with this a bit more. I think it has something to do with the decoder returning pixels in the wrong orientation.

On line 37 of lib/src/avif_encoder.dart, I can change the orientation value to anything from 2 through 8 and it will encode the image fine (although it appears in the wrong orientation):

// any value but 1 works
final decoded = await avif_platform.FlutterAvifPlatform.decode(input, 2);

If the orientation is 1 the image becomes garbled, but if I manually swap the width and height values it ends up encoding correctly:

width = orientation == 1 ? decoded.height: decoded.width;
height = orientation == 1 ? decoded.width: decoded.height;

Unfortunately, even with all this hackery I can't it to output a correctly-encoded image in the right orientation. It feels like the problem might be somewhere in the blob of wasm but I don't really know how to explore that.

yekeskin commented 1 month ago

This part of the code is for fixing the exif orientation issue.

I think you are right about the issue being on the wasm side. We probably shouldn't rotate the image here.

I can take a detailed look at this over the weekend and publish a fix. Feel free to open a PR yourself if you need this sooner.

Thanks for your help.

michaelnew commented 1 month ago

I think you're exactly right. I was able to to test this locally and it works great.

I'd be happy to publish a PR, but I'm a little lost with the Rust side of things. Seems like that function needs to return an ImageBuffer, and I'm not sure how to do that from a GenericImageView without doing a transformation. I just did imageops::flip_horizontal twice to hack together a test.

I'm not in any desperate hurry for a fix; just needed to get something working for a small test build, which I can do now. Thanks for being so responsive and for keeping up with this plugin in general. Really a lifesaver.