nikolaydymura / flutter_image_filters

MIT License
28 stars 13 forks source link

Export Image unusable. #19

Closed sokphengcheang closed 1 year ago

sokphengcheang commented 1 year ago

Screenshot 2023-02-17 at 4 14 47 PM

onTap: () async { if (textTure != null) { final directory = await getTemporaryDirectory(); final output = File('${directory.path}/doc.jpeg'); img.JpegEncoder encoder = img.JpegEncoder();

                          UI.Image image = await configuration.export(
                            textTure!,
                            textTure!.size,
                          );

                          final bytes = await image.toByteData();

                          final persistedImage = img.Image.fromBytes(
                            width: image.width,
                            height: image.height,
                            bytes: bytes!.buffer,
                          );

                          final data = encoder.encode(persistedImage);
                          await output.writeAsBytes(data);

                          await handleSingleUpload(output);

                          Navigator.of(context).pop();
                        }
                      },
nikolaydymura commented 1 year ago

@sokpheng, what filter you are using?

SmearyQuill commented 1 year ago

Same problem here, i'm using the grayscale filter

EDIT: happens on iOS too

nikolaydymura commented 1 year ago

@SmearyQuill what version of flutter are you using?

SmearyQuill commented 1 year ago

Here's the flutter doctor output, hope it helps. Also i noticed that the issue only happens when you export/save the image, if i use the filter without exporting and refreshing it works normally.

[√] Flutter (Channel stable, 3.10.2, on Microsoft Windows [Versi¢n 10.0.22621.1778], locale es-MX)
    • Flutter version 3.10.2 on channel stable at C:\flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 9cd3d0d9ff (13 days ago), 2023-05-23 20:57:28 -0700
    • Engine revision 90fa3ae28f
    • Dart version 3.0.2
    • DevTools version 2.23.1

[√] Windows Version (Installed version of Windows is version 10 or higher)

[√] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
    • Android SDK at C:\Users\AUMENTA\AppData\Local\Android\sdk
    • Platform android-33, build-tools 33.0.0
    • Java binary at: C:\Program Files\Common Files\Oracle\Java\javapath\java.exe
    • Java version Java(TM) SE Runtime Environment (build 18.0.2+9-61)
    • All Android licenses accepted.

[√] Chrome - develop for the web
    • Chrome at C:\Program Files\Google\Chrome\Application\chrome.exe

[√] Visual Studio - develop for Windows (Visual Studio Community 2022 17.6.2)
    • Visual Studio at D:\Vsiual Studio 2022
    • Visual Studio Community 2022 version 17.6.33723.286
    • Windows 10 SDK version 10.0.22000.0

[!] Android Studio (not installed)
    • Android Studio not found; download from https://developer.android.com/studio/index.html
      (or visit https://flutter.dev/docs/get-started/install/windows#android-setup for detailed instructions).

[√] VS Code (version 1.78.2)
    • VS Code at C:\Users\AUMENTA\AppData\Local\Programs\Microsoft VS Code
    • Flutter extension version 3.66.0

[√] Connected device (4 available)
    • moto g 6 play (mobile) • ZL6222NXM2 • android-arm    • Android 9 (API 28)
    • Windows (desktop)      • windows    • windows-x64    • Microsoft Windows [Versi¢n 10.0.22621.1778]
    • Chrome (web)           • chrome     • web-javascript • Google Chrome 114.0.5735.110
    • Edge (web)             • edge       • web-javascript • Microsoft Edge 113.0.1774.57

[√] Network resources
    • All expected network resources are available.
nikolaydymura commented 1 year ago

@SmearyQuill We have a large sample project with all filters. Have you tried filters there? Here is the working code for exporting images there.

Future<void> _exportImage() async {
    const asset = 'images/inputImage.jpg';
    final texture = await TextureSource.fromAsset(asset);
    final directory = await getTemporaryDirectory();
    final output =
        File('${directory.path}/${DateTime.now().millisecondsSinceEpoch}.jpg');
    final watch = Stopwatch();
    watch.start();
    final image = await configuration.export(
      texture,
      Size(texture.width.toDouble(), texture.height.toDouble()),
    );
    final bytes = await image.toByteData();
    debugPrint(
      'Exporting image took ${watch.elapsedMilliseconds} milliseconds',
    );
    if (bytes == null) {
      throw UnsupportedError('Failed to extract bytes for image');
    }
    final image1 = img.Image.fromBytes(
      image.width,
      image.height,
      bytes.buffer.asUint8List(),
    );
    img.JpegEncoder encoder = img.JpegEncoder();
    final data = encoder.encodeImage(image1);
    await output.writeAsBytes(data);
    debugPrint('Exporting file took ${watch.elapsedMilliseconds} milliseconds');
    debugPrint('Exported: ${output.absolute}');
  }
SmearyQuill commented 1 year ago

Yeah i have, actually i had the export working previously but it stopped working and sadly im not sure when it started. Here is the code i use to export the image:

final texture = await TextureSource.fromMemory(
    album.images![currentIndex].originalBytes!
    );
final grayscale = GrayscaleShaderConfiguration();
final thresh = LuminanceThresholdShaderConfiguration();
final config = GroupShaderConfiguration();
config.add(grayscale);
config.add(thresh);
final image = await config.export(texture, texture.size);
final bytes = await image.toByteData();
final persistedImage = img.Image.fromBytes(
    width: image.width,
    height: image.height,
    bytes: bytes!.buffer,
    );
img.JpegEncoder encoder = img.JpegEncoder();
final data = encoder.encode(persistedImage);
await File(album.images![currentIndex].path!).writeAsBytes(data);
nikolaydymura commented 1 year ago

@SmearyQuill Here is where the problem is. As you probably use the latest image you need to manually define the number of channels for the output image

final persistedImage = img.Image.fromBytes(
       width: image.width,
       height: image.height,
      bytes: bytes!.buffer,
      numChannels: 4,
    );
SmearyQuill commented 1 year ago

Well that did the trick, i'm not sure if i completely understand why i needed to specify the numChannels parameter but i really appreciate your help!