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.93k stars 503 forks source link

Crop rect gets invalid randomly on zooming in and out #548

Closed kreativityapps closed 3 weeks ago

kreativityapps commented 1 year ago

Version

7.0.2

Platforms

dart, Android

Device Model

Samsung A21

flutter info

[✓] Flutter (Channel stable, 3.7.3, on macOS 13.1 22C65 darwin-arm64, locale en-DE)
    • Flutter version 3.7.3 on channel stable at /Users/me/Downloads/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 9944297138 (6 days ago), 2023-02-08 15:46:04 -0800
    • Engine revision 248290d6d5
    • Dart version 2.19.2
    • DevTools version 2.20.1

[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.1)
    • Android SDK at /Users/me/Library/Android/sdk
    • Platform android-33, build-tools 33.0.1
    • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.15+0-b2043.56-8887301)
    • All Android licenses accepted.

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

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

[✓] Android Studio (version 2022.1)
    • 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.15+0-b2043.56-8887301)

[✓] VS Code (version 1.74.2)
    • VS Code at /Users/me/Downloads/Visual Studio Code.app/Contents
    • Flutter extension version 3.58.0

[✓] Connected device (4 available)
    • SM A217F (mobile) • 192.168.55.104:33827                          • android-arm64  • Android 11 (API 30)
    • SM A217F (mobile) • adb-RF8N90WKSAA-SpQbtC._adb-tls-connect._tcp. • android-arm64  • Android 11 (API 30)
    • macOS (desktop)   • macos                                         • darwin-arm64   • macOS 13.1 22C65 darwin-arm64
    • Chrome (web)      • chrome                                        • web-javascript • Google Chrome 109.0.5414.119

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

• No issues found!

How to reproduce?

After the image is loaded I zoom in and out. After some time randomly the image jumps and then it turns all white. I can't zoom or drag any more. Trying to get the crop rect now returns: Rect.fromLTRB(NaN, -0.0, NaN, 4000.0) It looks like left and right are NaN.

Logs

======== Exception caught by rendering library =====================================================
The following UnsupportedError was thrown during paint():
Unsupported operation: Compared with Infinity or NaN

The relevant error-causing widget was: 
  ExtendedImage-[GlobalKey#1b185] ExtendedImage:file:///Users/me/Downloads/project/title/lib/src/file.dart:324:72
When the exception was thrown, this was the stack: 
#0      DoubleExtension.compare (package:extended_image/src/utils.dart:95:7)
#1      DoubleExtension.lessThan (package:extended_image/src/utils.dart:109:12)
#2      RectExtension.beyond (package:extended_image/src/utils.dart:129:17)
#3      paintExtendedImage (package:extended_image/src/image/painting.dart:130:21)
#4      ExtendedRenderImage.paint (package:extended_image/src/image/render_image.dart:503:5)
#5      RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2853:7)
#6      PaintingContext.paintChild (package:flutter/src/rendering/object.dart:253:13)
#7      RenderBoxContainerDefaultsMixin.defaultPaint (package:flutter/src/rendering/box.dart:2924:15)
#8      RenderStack.paintStack (package:flutter/src/rendering/stack.dart:654:5)
#9      RenderStack.paint (package:flutter/src/rendering/stack.dart:670:7)
#10     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2853:7)
#11     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:253:13)
#12     RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:144:15)
#13     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2853:7)
#14     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:253:13)
#15     RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:144:15)
#16     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2853:7)
#17     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:253:13)
#18     RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:144:15)
#19     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2853:7)
#20     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:253:13)
#21     RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:144:15)
#22     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2853:7)
#23     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:253:13)
#24     RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:144:15)
#25     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2853:7)
#26     PaintingContext._repaintCompositedChild (package:flutter/src/rendering/object.dart:169:11)
#27     PaintingContext.repaintCompositedChild (package:flutter/src/rendering/object.dart:112:5)
#28     PipelineOwner.flushPaint (package:flutter/src/rendering/object.dart:1137:31)
#29     RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:518:19)
#30     WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:865:13)
#31     RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:381:5)
#32     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1289:15)
#33     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1218:9)
#34     SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1076:5)
#38     _invoke (dart:ui/hooks.dart:147:10)
#39     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:338:5)
#40     _drawFrame (dart:ui/hooks.dart:112:31)
(elided 3 frames from dart:async)
The following RenderObject was being processed when the exception was fired: ExtendedRenderImage#da128
...  parentData: top=0.0; right=0.0; bottom=0.0; left=0.0; offset=Offset(0.0, 0.0) (can use size)
...  constraints: BoxConstraints(w=411.4, h=258.8)
...  size: Size(411.4, 258.8)
...  image: [3000×4000]
...  fit: contain
...  alignment: Alignment.center
...  invertColors: false
...  filterQuality: low
RenderObject: ExtendedRenderImage#da128
  parentData: top=0.0; right=0.0; bottom=0.0; left=0.0; offset=Offset(0.0, 0.0) (can use size)
  constraints: BoxConstraints(w=411.4, h=258.8)
  size: Size(411.4, 258.8)
  image: [3000×4000]
  fit: contain
  alignment: Alignment.center
  invertColors: false
  filterQuality: low
====================================================================================================

Example code (optional)

ExtendedImage.file(
    _pickedImageFile!,
    key: keyButton,
    fit: BoxFit.contain,
    extendedImageEditorKey: editorKey,
    mode: ExtendedImageMode.editor,
    enableLoadState: true,
    cacheRawData: true,
    clearMemoryCacheWhenDispose: true,
    initEditorConfigHandler: (
      ExtendedImageState? state,
    ) {
      return EditorConfig(
        maxScale: 10.0,
        // Only for debugging:
        editActionDetailsIsChanged: (EditActionDetails? details) {
          Rect? cropRect = editorKey.currentState?.getCropRect();
          print(cropRect);
        }
      );
    },
  ),

Contact

No response

zmtzawqlp commented 1 year ago

please provide the url in your issue demo

TomcatCbn commented 8 months ago

I got the same problem when I continually zoom in and out. I found after calling the method, the rect will have NaN

Rect getFinalDestinationRect() { _reachCropRectEdge = false;

if (screenDestinationRect != null) {
  /// scale
  final double scaleDelta = totalScale / preTotalScale;
  if (scaleDelta != 1.0) {
    Offset focalPoint = screenFocalPoint ?? _screenDestinationRect!.center;
    focalPoint = Offset(
      focalPoint.dx
          .clamp(
              _screenDestinationRect!.left, _screenDestinationRect!.right)
          .toDouble(),
      focalPoint.dy
          .clamp(
              _screenDestinationRect!.top, _screenDestinationRect!.bottom)
          .toDouble(),
    );

    _screenDestinationRect = Rect.fromLTWH(
        focalPoint.dx -
            (focalPoint.dx - _screenDestinationRect!.left) * scaleDelta,
        focalPoint.dy -
            (focalPoint.dy - _screenDestinationRect!.top) * scaleDelta,
        _screenDestinationRect!.width * scaleDelta,
        _screenDestinationRect!.height * scaleDelta);
    preTotalScale = totalScale;
    delta = Offset.zero;
  }

  /// move
  else {
    if (_screenDestinationRect != screenCropRect) {
      final bool topSame =
          _screenDestinationRect!.topIsSame(screenCropRect!);
      final bool leftSame =
          _screenDestinationRect!.leftIsSame(screenCropRect!);
      final bool bottomSame =
          _screenDestinationRect!.bottomIsSame(screenCropRect!);
      final bool rightSame =
          _screenDestinationRect!.rightIsSame(screenCropRect!);

      if (topSame && bottomSame) {
        delta = Offset(delta.dx, 0.0);
      } else if (leftSame && rightSame) {
        delta = Offset(0.0, delta.dy);
      }

      _screenDestinationRect = _screenDestinationRect!.shift(delta);
    }
    //we have shift offset, we should clear delta.
    delta = Offset.zero;
  }

  _screenDestinationRect =
      computeBoundary(_screenDestinationRect!, screenCropRect!);

  // make sure that crop rect is all in image rect.
  if (screenCropRect != null) {
    Rect rect = screenCropRect!.expandToInclude(_screenDestinationRect!);
    if (rect != _screenDestinationRect) {
      final bool topSame = rect.topIsSame(screenCropRect!);
      final bool leftSame = rect.leftIsSame(screenCropRect!);
      final bool bottomSame = rect.bottomIsSame(screenCropRect!);
      final bool rightSame = rect.rightIsSame(screenCropRect!);

      // make sure that image rect keep same aspect ratio
      if (topSame && bottomSame) {
        rect = Rect.fromCenter(
            center: rect.center,
            width: rect.height /
                _screenDestinationRect!.height *
                _screenDestinationRect!.width,
            height: rect.height);
        _reachCropRectEdge = true;
      } else if (leftSame && rightSame) {
        rect = Rect.fromCenter(
          center: rect.center,
          width: rect.width,
          height: rect.width /
              _screenDestinationRect!.width *
              _screenDestinationRect!.height,
        );
        _reachCropRectEdge = true;
      }
      totalScale =
          totalScale / (rect.width / _screenDestinationRect!.width);
      // init totalScale
      if (_rawDestinationRect!.isSame(_rawDestinationRect!)) {
        totalScale = 1.0;
      }
      preTotalScale = totalScale;
      _screenDestinationRect = rect;
    }
  }
} else {
  _screenDestinationRect = getRectWithScale(_rawDestinationRect!);
  _screenDestinationRect =
      computeBoundary(_screenDestinationRect!, screenCropRect!);
}
return _screenDestinationRect!;

}

zmtzawqlp commented 3 weeks ago

please update to lastest version