fluttercandies / extended_image

A powerful official extension library of image, which support placeholder(loading)/ failed state, cache network, zoom pan image, photo view, slide out page, editor(crop,rotate,flip), paint custom etc.
https://fluttercandies.github.io/extended_image/
MIT License
1.9k stars 499 forks source link

getCropRect() returns Rect with negative values #580

Open mitrakov opened 1 year ago

mitrakov commented 1 year ago

Version

7.0.2

Platforms

macOS

Device Model

MacOS 13.3.1

flutter info

<details>
  <summary>flutter doctor -v</summary>

flutter doctor -v
[✓] Flutter (Channel stable, 3.7.12, on macOS 13.3.1 22E261 darwin-x64, locale en-GB)
    • Flutter version 3.7.12 on channel stable at /Users/macbook1/soft/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 4d9e56e694 (4 weeks ago), 2023-04-17 21:47:46 -0400
    • Engine revision 1a65d409c7
    • Dart version 2.19.6
    • DevTools version 2.20.1

[!] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
    • Android SDK at /Users/macbook1/Library/Android/sdk
    ✗ cmdline-tools component is missing
      Run `path/to/sdkmanager --install "cmdline-tools;latest"`
      See https://developer.android.com/studio/command-line for more details.
    ✗ Android license status unknown.
      Run `flutter doctor --android-licenses` to accept the SDK licenses.
      See https://flutter.dev/docs/get-started/install/macos#android-setup for more details.

[✓] Xcode - develop for iOS and macOS (Xcode 14.3)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 14E222b
    • CocoaPods version 1.11.3

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2021.3)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.13+0-b1751.21-8125866)

[✓] IntelliJ IDEA Community Edition (version 2022.3.1)
    • IntelliJ at /Applications/IntelliJ IDEA CE.app
    • Flutter plugin version 72.1.4
    • Dart plugin version 223.8214.16

[✓] VS Code (version 1.74.2)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.21.0

[✓] Connected device (2 available)
    • macOS (desktop) • macos  • darwin-x64     • macOS 13.3.1 22E261 darwin-x64
    • Chrome (web)    • chrome • web-javascript • Google Chrome 113.0.5672.126

[✓] HTTP Host Availability
    • All required HTTP hosts are available

! Doctor found issues in 1 category.

</details>

How to reproduce?

case ExtendedImageMode.editor:
    final state = editorKey.currentState!;
    final cropRect = state.getCropRect()!;
    print(cropRect);

Logs

After several attempts of cropping, it may return "-0.0", which causes issues in other libraries:

flutter: Rect.fromLTRB(0.0, 51.6, 1080.0, 1545.0)
flutter: Rect.fromLTRB(0.0, 23.1, 1080.0, 1493.0)
flutter: Rect.fromLTRB(0.0, 28.8, 1080.0, 1470.0)
flutter: Rect.fromLTRB(0.0, 31.5, 1080.0, 1441.0)
flutter: Rect.fromLTRB(0.0, 45.3, 1080.0, 1802.0)
flutter: Rect.fromLTRB(0.0, 157.0, 1080.0, 1757.0)
flutter: Rect.fromLTRB(-0.0, 70.6, 1080.0, 1600.0)
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: 'package:image_editor_platform_interface/src/option/clip.dart': Failed assertion: line 17 pos 16: 'x >= 0': true
#0      _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:51:61)
#1      _AssertionError._throwNew (dart:core-patch/errors_patch.dart:40:5)
#2      new ClipOption (package:image_editor_platform_interface/src/option/clip.dart:17:16)
#3      _MyAppState._saveFile.converterMacOs (package:tommyview/main.dart:283:46)
#4      _MyAppState._saveFileInternal (package:tommyview/main.dart:318:47)
#5      _MyAppState._saveFile (package:tommyview/main.dart:289:10)
#6      _MyAppState.build.<anonymous closure> (package:tommyview/main.dart:132:75)
#7      CallbackAction.invoke (package:flutter/src/widgets/actions.dart:541:39)

Example code (optional)

No response

Contact

mitrakov-artem@yandex.ru

zmtzawqlp commented 1 year ago

is there any cases or demo to reproduce it?

mitrakov commented 1 year ago
Source code ```dart import "dart:io"; import "package:flutter/material.dart"; import "package:flutter/services.dart"; import "package:image_editor/image_editor.dart"; import "package:extended_image/extended_image.dart"; // dependencies: // extended_image: 7.0.2 // image_editor: 1.3.0 // 1. Make sure to remove "com.apple.security.app-sandbox" from entitlements // 2. Prepare "1.png" file // 3. Click F3 to crop image, and ENTER to save the file // 4. Try several times! void main(List args) async { runApp(MaterialApp(home: Scaffold(body: MyApp(File("/Users/tommy/1.png"))))); } class MyApp extends StatefulWidget { final File startPath; const MyApp(this.startPath); @override State createState() => _MyAppState(); } class _MyAppState extends State { final editorKey = GlobalKey(); final extImgKey = GlobalKey(); ExtendedImageMode _mode = ExtendedImageMode.gesture; @override Widget build(BuildContext context) { return Shortcuts( shortcuts: { const SingleActivator(LogicalKeyboardKey.enter): SaveFileIntent(), const SingleActivator(LogicalKeyboardKey.f3): SwitchModeIntent(), }, child: Actions( actions: { SaveFileIntent: CallbackAction(onInvoke: (_) => _saveFile()), SwitchModeIntent: CallbackAction(onInvoke: (_) => _switchMode()), }, child: Focus( autofocus: true, child: ExtendedImage.file (key: extImgKey, widget.startPath, mode: _mode, fit: _mode == ExtendedImageMode.editor ? BoxFit.contain : null, width: double.infinity, height: double.infinity, extendedImageEditorKey: editorKey, cacheRawData: true) ) ) ); } void _switchMode() { setState(() { _mode = _mode == ExtendedImageMode.editor ? ExtendedImageMode.gesture : ExtendedImageMode.editor; }); } void _saveFile() { converterMacOs(Uint8List image, Rect? cropRect) async { final option = ImageEditorOption(); if (cropRect != null) option.addOption(ClipOption(x: cropRect.left, y: cropRect.top, width: cropRect.width, height: cropRect.height)); final result = await ImageEditor.editImage(image: image, imageEditorOption: option); return result!; } _saveFileInternal(converterMacOs); } void _saveFileInternal(ImageConverter converter) async { Rect? cropOption; switch (_mode) { case ExtendedImageMode.editor: final state = editorKey.currentState!; final action = state.editAction!; final cropRect = state.getCropRect()!; print("Rect is $cropRect"); if (action.needCrop) { cropOption = cropRect; } break; default: } if (cropOption != null) { final exImage = extImgKey.currentWidget as ExtendedImage; final imageProvider = exImage.image as ExtendedFileImageProvider; final Uint8List image = imageProvider.rawImageData; final Uint8List bytes = await converter.call(image, cropOption); widget.startPath.writeAsBytesSync(bytes, flush: true); clearMemoryImageCache(); _switchMode(); } } } typedef ImageConverter = Future Function(Uint8List curImage, Rect? cropRect); class SaveFileIntent extends Intent {} class SwitchModeIntent extends Intent {} ```

How to reproduce (press F3 and ENTER):

tommyview

zmtzawqlp commented 9 months ago

i can't reprduce it at my side, can you try it on latest version of extended_image?

mitrakov commented 9 months ago

@zmtzawqlp, I ended up with this dirty-hack method:

Rect _fixRect(Rect rect) {
  // extended_image: 7.0.2 has a bug when sometimes it provides "-0.0" values in Rect
  if (rect.left.isNegative || rect.right.isNegative || rect.top.isNegative || rect.bottom.isNegative) {
    final left   = rect.left.isNegative   ? 0.0 : rect.left;
    final right  = rect.right.isNegative  ? 0.0 : rect.right;
    final top    = rect.top.isNegative    ? 0.0 : rect.top;
    final bottom = rect.bottom.isNegative ? 0.0 : rect.bottom;
    return Rect.fromLTRB(left, top, right, bottom);
  }
  return rect;
}

which works for me.

Will try to check 8.2.0 at my spare time