diff --git a/README.md b/README.md
index 9ca6189..98bcbbe 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@ A Flutter plugin enabling the user to detect edges of a given image. It returns
## Demo
-
+
## Try out
diff --git a/example/lib/edge_detection_preview.dart b/example/lib/edge_detection_preview.dart
deleted file mode 100644
index 86a89bd..0000000
--- a/example/lib/edge_detection_preview.dart
+++ /dev/null
@@ -1,149 +0,0 @@
-import 'dart:async';
-import 'dart:io';
-import 'dart:math';
-import 'dart:typed_data';
-import 'dart:ui' as ui;
-import 'package:simple_edge_detection/edge_detection.dart';
-import 'package:flutter/material.dart';
-
-class EdgeDetectionPreview extends StatefulWidget {
- EdgeDetectionPreview({
- this.imagePath,
- this.edgeDetectionResult
- });
-
- final String imagePath;
- final EdgeDetectionResult edgeDetectionResult;
-
- @override
- _EdgeDetectionPreviewState createState() => _EdgeDetectionPreviewState();
-}
-
-class _EdgeDetectionPreviewState extends State {
- GlobalKey imageWidgetKey = GlobalKey();
-
- @override
- Widget build(BuildContext mainContext) {
- return Center(
- child: Stack(
- fit: StackFit.expand,
- children: [
- Center(
- child: Text('Loading ...')
- ),
- Image.file(
- File(widget.imagePath),
- fit: BoxFit.contain,
- key: imageWidgetKey
- ),
- FutureBuilder(
- future: loadUiImage(widget.imagePath),
- builder: (BuildContext context, AsyncSnapshot snapshot) {
- return _getEdgePaint(snapshot, context);
- }
- ),
- ],
- ),
- );
- }
-
- Widget _getEdgePaint(AsyncSnapshot imageSnapshot, BuildContext context) {
- if (imageSnapshot.connectionState == ConnectionState.waiting)
- return Container();
-
- if (imageSnapshot.hasError)
- return Text('Error: ${imageSnapshot.error}');
-
- if (widget.edgeDetectionResult == null)
- return Container();
-
- final keyContext = imageWidgetKey.currentContext;
-
- if (keyContext == null) {
- return Container();
- }
-
- final box = keyContext.findRenderObject() as RenderBox;
-
- return CustomPaint(
- size: Size(box.size.width, box.size.height),
- painter: EdgePainter(
- topLeft: widget.edgeDetectionResult.topLeft,
- topRight: widget.edgeDetectionResult.topRight,
- bottomLeft: widget.edgeDetectionResult.bottomLeft,
- bottomRight: widget.edgeDetectionResult.bottomRight,
- image: imageSnapshot.data,
- color: Theme.of(context).accentColor
- )
- );
- }
-
- Future loadUiImage(String imageAssetPath) async {
- final Uint8List data = await File(imageAssetPath).readAsBytes();
- final Completer completer = Completer();
- ui.decodeImageFromList(Uint8List.view(data.buffer), (ui.Image image) {
- return completer.complete(image);
- });
- return completer.future;
- }
-}
-
-class EdgePainter extends CustomPainter {
- EdgePainter({
- this.topLeft,
- this.topRight,
- this.bottomLeft,
- this.bottomRight,
- this.image,
- this.color
- });
-
- Offset topLeft;
- Offset topRight;
- Offset bottomLeft;
- Offset bottomRight;
-
- ui.Image image;
- Color color;
-
- @override
- void paint(Canvas canvas, Size size) {
- double top = 0.0;
- double left = 0.0;
-
- double widthFactor = size.width / image.width;
- double heightFactor = size.height / image.height;
- double sizeFactor = min(widthFactor, heightFactor);
-
- double renderedImageHeight = image.height * sizeFactor;
- top = ((size.height - renderedImageHeight) / 2);
-
- double renderedImageWidth = image.width * sizeFactor;
- left = ((size.width - renderedImageWidth) / 2);
-
-
- final points = [
- Offset(left + topLeft.dx * renderedImageWidth, top + topLeft.dy * renderedImageHeight),
- Offset(left + topRight.dx * renderedImageWidth, top + topRight.dy * renderedImageHeight),
- Offset(left + bottomRight.dx * renderedImageWidth, top + (bottomRight.dy * renderedImageHeight)),
- Offset(left + bottomLeft.dx * renderedImageWidth, top + bottomLeft.dy * renderedImageHeight),
- Offset(left + topLeft.dx * renderedImageWidth, top + topLeft.dy * renderedImageHeight),
- ];
-
- final paint = Paint()
- ..color = color.withOpacity(0.5)
- ..strokeWidth = 2
- ..strokeCap = StrokeCap.round;
-
- canvas.drawPoints(ui.PointMode.polygon, points, paint);
-
- for (Offset point in points) {
- canvas.drawCircle(point, 10, paint);
- }
- }
-
- @override
- bool shouldRepaint(CustomPainter old) {
- return true;
- }
-}
\ No newline at end of file
diff --git a/example/lib/edge_detection_shape/animated_touch_bubble_part.dart b/example/lib/edge_detection_shape/animated_touch_bubble_part.dart
new file mode 100644
index 0000000..a587aaf
--- /dev/null
+++ b/example/lib/edge_detection_shape/animated_touch_bubble_part.dart
@@ -0,0 +1,85 @@
+import 'package:flutter/material.dart';
+
+class AnimatedTouchBubblePart extends StatefulWidget {
+ AnimatedTouchBubblePart({this.dragging, this.size});
+
+ final bool dragging;
+ final double size;
+
+ @override
+ _AnimatedTouchBubblePartState createState() => _AnimatedTouchBubblePartState();
+}
+
+class _AnimatedTouchBubblePartState extends State with SingleTickerProviderStateMixin {
+ AnimationController _controller;
+ Animation _colorAnimation;
+ Animation _sizeAnimation;
+
+ @override
+ void didChangeDependencies() {
+ _controller = new AnimationController(
+ duration: const Duration(milliseconds: 1000),
+ vsync: this,
+ );
+
+ _sizeAnimation = Tween(
+ begin: 0.5,
+ end: 1.0
+ ).animate(_controller);
+
+ _colorAnimation = ColorTween(
+ begin: Theme.of(context).accentColor.withOpacity(0.5),
+ end: Theme.of(context).accentColor.withOpacity(0.0)
+ ).animate(
+ CurvedAnimation(
+ parent: _controller,
+ curve: Interval(0.5, 1.0)
+ )
+ );
+
+ _controller.repeat();
+ super.didChangeDependencies();
+ }
+
+ @override
+ void dispose() {
+ _controller.dispose();
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Stack(
+ children: [
+ Center(
+ child: Container(
+ width: widget.dragging ? widget.size : widget.size / 2,
+ height: widget.dragging ? widget.size : widget.size / 2,
+ decoration: BoxDecoration(
+ color: Theme.of(context).accentColor.withOpacity(0.5),
+ borderRadius: widget.dragging ? BorderRadius.circular(widget.size) : BorderRadius.circular(widget.size / 4)
+ )
+ )
+ ),
+ AnimatedBuilder(
+ builder: (BuildContext context, Widget child) {
+ return Center(
+ child: Container(
+ width: widget.dragging ? 0 : widget.size * _sizeAnimation.value,
+ height: widget.dragging ? 0 : widget.size * _sizeAnimation.value,
+ decoration: BoxDecoration(
+ border: Border.all(
+ color: _colorAnimation.value,
+ width: widget.size / 20
+ ),
+ borderRadius: widget.dragging ? BorderRadius.zero : BorderRadius.circular(widget.size * _sizeAnimation.value / 2)
+ )
+ )
+ );
+ },
+ animation: _controller
+ )
+ ],
+ );
+ }
+}
\ No newline at end of file
diff --git a/example/lib/edge_detection_shape/edge_detection_shape.dart b/example/lib/edge_detection_shape/edge_detection_shape.dart
new file mode 100644
index 0000000..c48e3ef
--- /dev/null
+++ b/example/lib/edge_detection_shape/edge_detection_shape.dart
@@ -0,0 +1,170 @@
+import 'dart:math';
+import 'dart:ui';
+
+import 'package:flutter/material.dart';
+import 'package:simple_edge_detection/edge_detection.dart';
+
+import 'edge_painter.dart';
+import 'touch_bubble.dart';
+
+class EdgeDetectionShape extends StatefulWidget {
+ EdgeDetectionShape({
+ @required this.renderedImageSize,
+ @required this.originalImageSize,
+ @required this.edgeDetectionResult
+ });
+
+ final Size renderedImageSize;
+ final Size originalImageSize;
+ final EdgeDetectionResult edgeDetectionResult;
+
+ @override
+ _EdgeDetectionShapeState createState() => _EdgeDetectionShapeState();
+}
+
+class _EdgeDetectionShapeState extends State {
+ double edgeDraggerSize;
+
+ EdgeDetectionResult edgeDetectionResult;
+ List points;
+
+ double renderedImageWidth;
+ double renderedImageHeight;
+ double top;
+ double left;
+
+ @override
+ void didChangeDependencies() {
+ double shortestSide = min(MediaQuery.of(context).size.width, MediaQuery.of(context).size.height);
+ edgeDraggerSize = shortestSide / 8;
+ super.didChangeDependencies();
+ }
+
+ @override
+ void initState() {
+ edgeDetectionResult = widget.edgeDetectionResult;
+ _calculateDimensionValues();
+
+ super.initState();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Stack(
+ children: [
+ _getTouchBubbles(),
+ CustomPaint(
+ painter: EdgePainter(
+ points: points,
+ color: Theme.of(context).accentColor.withOpacity(0.5)
+ ),
+ )
+ ],
+ );
+ }
+
+ void _calculateDimensionValues() {
+ top = 0.0;
+ left = 0.0;
+
+ double widthFactor = widget.renderedImageSize.width / widget.originalImageSize.width;
+ double heightFactor = widget.renderedImageSize.height / widget.originalImageSize.height;
+ double sizeFactor = min(widthFactor, heightFactor);
+
+ renderedImageHeight = widget.originalImageSize.height * sizeFactor;
+ top = ((widget.renderedImageSize.height - renderedImageHeight) / 2);
+
+ renderedImageWidth = widget.originalImageSize.width * sizeFactor;
+ left = ((widget.renderedImageSize.width - renderedImageWidth) / 2);
+ }
+
+ Offset _getNewPositionAfterDrag(Offset position, double renderedImageWidth, double renderedImageHeight) {
+ return Offset(
+ position.dx / renderedImageWidth,
+ position.dy / renderedImageHeight
+ );
+ }
+
+ Widget _getTouchBubbles() {
+ points = [
+ Offset(left + edgeDetectionResult.topLeft.dx * renderedImageWidth, top + edgeDetectionResult.topLeft.dy * renderedImageHeight),
+ Offset(left + edgeDetectionResult.topRight.dx * renderedImageWidth, top + edgeDetectionResult.topRight.dy * renderedImageHeight),
+ Offset(left + edgeDetectionResult.bottomRight.dx * renderedImageWidth, top + (edgeDetectionResult.bottomRight.dy * renderedImageHeight)),
+ Offset(left + edgeDetectionResult.bottomLeft.dx * renderedImageWidth, top + edgeDetectionResult.bottomLeft.dy * renderedImageHeight),
+ Offset(left + edgeDetectionResult.topLeft.dx * renderedImageWidth, top + edgeDetectionResult.topLeft.dy * renderedImageHeight),
+ ];
+
+ final Function onDragFinished = () {
+ setState(() {});
+ };
+
+ return Container(
+ width: widget.renderedImageSize.width,
+ height: widget.renderedImageSize.height,
+ child: Stack(
+ children: [
+ Positioned(
+ child: TouchBubble(
+ size: edgeDraggerSize,
+ onDrag: (position) {
+ setState(() {
+ edgeDetectionResult.topLeft += _getNewPositionAfterDrag(
+ position, renderedImageWidth, renderedImageHeight
+ );
+ });
+ },
+ onDragFinished: onDragFinished
+ ),
+ left: points[0].dx - (edgeDraggerSize / 2),
+ top: points[0].dy - (edgeDraggerSize / 2)
+ ),
+ Positioned(
+ child: TouchBubble(
+ size: edgeDraggerSize,
+ onDrag: (position) {
+ setState(() {
+ edgeDetectionResult.topRight += _getNewPositionAfterDrag(
+ position, renderedImageWidth, renderedImageHeight
+ );
+ });
+ },
+ onDragFinished: onDragFinished
+ ),
+ left: points[1].dx - (edgeDraggerSize / 2),
+ top: points[1].dy - (edgeDraggerSize / 2)
+ ),
+ Positioned(
+ child: TouchBubble(
+ size: edgeDraggerSize,
+ onDrag: (position) {
+ setState(() {
+ edgeDetectionResult.bottomRight += _getNewPositionAfterDrag(
+ position, renderedImageWidth, renderedImageHeight
+ );
+ });
+ },
+ onDragFinished: onDragFinished
+ ),
+ left: points[2].dx - (edgeDraggerSize / 2),
+ top: points[2].dy - (edgeDraggerSize / 2)
+ ),
+ Positioned(
+ child: TouchBubble(
+ size: edgeDraggerSize,
+ onDrag: (position) {
+ setState(() {
+ edgeDetectionResult.bottomLeft += _getNewPositionAfterDrag(
+ position, renderedImageWidth, renderedImageHeight
+ );
+ });
+ },
+ onDragFinished: onDragFinished
+ ),
+ left: points[3].dx - (edgeDraggerSize / 2),
+ top: points[3].dy - (edgeDraggerSize / 2)
+ ),
+ ],
+ ),
+ );
+ }
+}
\ No newline at end of file
diff --git a/example/lib/edge_detection_shape/edge_painter.dart b/example/lib/edge_detection_shape/edge_painter.dart
new file mode 100644
index 0000000..782a08e
--- /dev/null
+++ b/example/lib/edge_detection_shape/edge_painter.dart
@@ -0,0 +1,28 @@
+import 'dart:ui';
+
+import 'package:flutter/material.dart';
+
+class EdgePainter extends CustomPainter {
+ EdgePainter({
+ @required this.points,
+ @required this.color
+ });
+
+ final List points;
+ final Color color;
+
+ @override
+ void paint(Canvas canvas, Size size) {
+ final paint = Paint()
+ ..color = color.withOpacity(0.5)
+ ..strokeWidth = 2
+ ..strokeCap = StrokeCap.round;
+
+ canvas.drawPoints(PointMode.polygon, points, paint);
+ }
+
+ @override
+ bool shouldRepaint(CustomPainter old) {
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/example/lib/edge_detection_shape/touch_bubble.dart b/example/lib/edge_detection_shape/touch_bubble.dart
new file mode 100644
index 0000000..2d45933
--- /dev/null
+++ b/example/lib/edge_detection_shape/touch_bubble.dart
@@ -0,0 +1,68 @@
+import 'package:flutter/material.dart';
+
+import 'animated_touch_bubble_part.dart';
+
+class TouchBubble extends StatefulWidget {
+ TouchBubble({
+ @required this.size,
+ @required this.onDrag,
+ @required this.onDragFinished,
+ });
+
+ final double size;
+ final Function onDrag;
+ final Function onDragFinished;
+
+ @override
+ _TouchBubbleState createState() => _TouchBubbleState();
+}
+
+class _TouchBubbleState extends State {
+ bool dragging = false;
+
+ @override
+ Widget build(BuildContext context) {
+ return GestureDetector(
+ behavior: HitTestBehavior.opaque,
+ onTapDown: (_) => _startDragging(),
+ onPanStart: (_) => _startDragging(),
+ onTapUp: (_) => _cancelDragging(),
+ onTapCancel: _cancelDragging,
+ onPanUpdate: _drag,
+ onPanCancel: _cancelDragging,
+ onPanEnd: (_) => _cancelDragging(),
+ child: Container(
+ width: widget.size,
+ height: widget.size,
+ decoration: BoxDecoration(
+ color: Colors.transparent,
+ borderRadius: BorderRadius.circular(widget.size / 2)
+ ),
+ child: AnimatedTouchBubblePart(
+ dragging: dragging,
+ size: widget.size,
+ )
+ )
+ );
+ }
+
+ void _startDragging() {
+ setState(() {
+ dragging = true;
+ });
+ }
+
+ void _cancelDragging() {
+ setState(() {
+ dragging = false;
+ });
+ widget.onDragFinished();
+ }
+
+ void _drag(DragUpdateDetails data) {
+ if (!dragging) {
+ return;
+ }
+ widget.onDrag(data.delta);
+ }
+}
\ No newline at end of file
diff --git a/example/lib/image_preview.dart b/example/lib/image_preview.dart
new file mode 100644
index 0000000..e4ebf82
--- /dev/null
+++ b/example/lib/image_preview.dart
@@ -0,0 +1,87 @@
+import 'dart:async';
+import 'dart:io';
+import 'dart:typed_data';
+import 'dart:ui' as ui;
+import 'package:simple_edge_detection/edge_detection.dart';
+import 'package:flutter/material.dart';
+
+import 'edge_detection_shape/edge_detection_shape.dart';
+
+class ImagePreview extends StatefulWidget {
+ ImagePreview({
+ this.imagePath,
+ this.edgeDetectionResult
+ });
+
+ final String imagePath;
+ final EdgeDetectionResult edgeDetectionResult;
+
+ @override
+ _ImagePreviewState createState() => _ImagePreviewState();
+}
+
+class _ImagePreviewState extends State {
+ GlobalKey imageWidgetKey = GlobalKey();
+
+ @override
+ Widget build(BuildContext mainContext) {
+ return Center(
+ child: Stack(
+ fit: StackFit.expand,
+ children: [
+ Center(
+ child: Text('Loading ...')
+ ),
+ Image.file(
+ File(widget.imagePath),
+ fit: BoxFit.contain,
+ key: imageWidgetKey
+ ),
+ FutureBuilder(
+ future: loadUiImage(widget.imagePath),
+ builder: (BuildContext context, AsyncSnapshot snapshot) {
+ return _getEdgePaint(snapshot, context);
+ }
+ ),
+ ],
+ ),
+ );
+ }
+
+ Widget _getEdgePaint(AsyncSnapshot imageSnapshot, BuildContext context) {
+ if (imageSnapshot.connectionState == ConnectionState.waiting)
+ return Container();
+
+ if (imageSnapshot.hasError)
+ return Text('Error: ${imageSnapshot.error}');
+
+ if (widget.edgeDetectionResult == null)
+ return Container();
+
+ final keyContext = imageWidgetKey.currentContext;
+
+ if (keyContext == null) {
+ return Container();
+ }
+
+ final box = keyContext.findRenderObject() as RenderBox;
+
+ return EdgeDetectionShape(
+ originalImageSize: Size(
+ imageSnapshot.data.width.toDouble(),
+ imageSnapshot.data.height.toDouble()
+ ),
+ renderedImageSize: Size(box.size.width, box.size.height),
+ edgeDetectionResult: widget.edgeDetectionResult,
+ );
+ }
+
+ Future loadUiImage(String imageAssetPath) async {
+ final Uint8List data = await File(imageAssetPath).readAsBytes();
+ final Completer completer = Completer();
+ ui.decodeImageFromList(Uint8List.view(data.buffer), (ui.Image image) {
+ return completer.complete(image);
+ });
+ return completer.future;
+ }
+}
\ No newline at end of file
diff --git a/example/lib/scan.dart b/example/lib/scan.dart
index 9debfa5..51e9c46 100644
--- a/example/lib/scan.dart
+++ b/example/lib/scan.dart
@@ -7,9 +7,9 @@ import 'package:simple_edge_detection/edge_detection.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path_provider/path_provider.dart';
+import 'package:simple_edge_detection_example/image_preview.dart';
import 'camera_view.dart';
-import 'edge_detection_preview.dart';
import 'edge_detector.dart';
class Scan extends StatefulWidget {
@@ -50,7 +50,7 @@ class _ScanState extends State {
);
}
- return EdgeDetectionPreview(
+ return ImagePreview(
imagePath: imagePath,
edgeDetectionResult: edgeDetectionResult,
);