adjustDocumentCorners method

  1. @override
Future<String?> adjustDocumentCorners(
  1. String base64Image
)
override

Implementation

@override
Future<String?> adjustDocumentCorners(String base64Image) {
  final completer = Completer<String?>();
  final html.DivElement modal = html.DivElement()
    ..style.position = 'fixed'
    ..style.left = '0'
    ..style.top = '0'
    ..style.width = '100%'
    ..style.height = '100%'
    ..style.backgroundColor = 'rgba(0, 0, 0, 0.8)'
    ..style.zIndex = '9999'
    ..style.display = 'flex'
    ..style.flexDirection = 'column'
    ..style.alignItems = 'center'
    ..style.justifyContent = 'center';

  final html.CanvasElement canvas = html.CanvasElement()
    ..style.borderRadius = '10px';

  final context = canvas.getContext('2d') as html.CanvasRenderingContext2D;

  final html.ImageElement imageElement = html.ImageElement()
    ..src = 'data:image/jpeg;base64,$base64Image';

  void drawCornersAndLines(
      html.CanvasRenderingContext2D ctx, List<Map<String, int>> corners) {
    ctx.clearRect(0, 0, canvas.width!, canvas.height!);
    ctx.drawImage(imageElement, 0, 0);

    // ctx.clearRect(
    //     corners[0]['x']!,
    //     corners[0]['y']!,
    //     corners[1]['x']! - corners[0]['x']!,
    //     corners[1]['y']! - corners[0]['y']!);

    // Maybe there is a better way to do it..
    ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
    ctx.fillRect(0, 0, corners[1]['x']!, corners[0]['y']!);
    ctx.fillRect(corners[1]['x']!, 0, canvas.width! - corners[1]['x']!,
        canvas.height!);
    ctx.fillRect(
        0,
        corners[1]['y']!,
        canvas.width! - (canvas.width! - corners[1]['x']!),
        canvas.height! - corners[1]['y']!);
    ctx.fillRect(
        0,
        corners[0]['y']!,
        corners[0]['x']!,
        canvas.height! -
            corners[0]['y']! -
            (canvas.height! - corners[1]['y']!));

    ctx.strokeStyle = 'gray';
    ctx.lineWidth = 2;
    ctx.beginPath();

    ctx.moveTo(corners[0]['x']!, corners[0]['y']!);
    ctx.lineTo(corners[0]['x']!, corners[1]['y']!);
    ctx.lineTo(corners[1]['x']!, corners[1]['y']!);
    ctx.lineTo(corners[1]['x']!, corners[0]['y']!);
    ctx.lineTo(corners[0]['x']!, corners[0]['y']!);

    ctx.stroke();

    for (final corner in corners) {
      ctx.fillStyle = 'white';
      ctx.fillRect(corner['x']! - 5, corner['y']! - 5, 10, 10);
    }
  }

  var corners = [
    {'x': 50, 'y': 50},
    {'x': canvas.width! - 50, 'y': canvas.height! - 50},
  ];

  imageElement.onLoad.listen((event) {
    canvas.width = imageElement.width ?? 800;
    canvas.height = imageElement.height ?? 600;
    corners = [
      {'x': 50, 'y': 50},
      {'x': canvas.width! - 50, 'y': canvas.height! - 50},
    ];
    context.drawImage(imageElement, 0, 0);
    drawCornersAndLines(context, corners);
  });

  canvas.onMouseDown.listen((event) {
    final rect = canvas.getBoundingClientRect();
    final mouseX = event.client.x - rect.left;
    final mouseY = event.client.y - rect.top;

    int? selectedCornerIndex;
    for (int i = 0; i < corners.length; i++) {
      final corner = corners[i];
      final dx = mouseX - corner['x']!;
      final dy = mouseY - corner['y']!;
      if (dx * dx + dy * dy <= 25) {
        // 25 is 5*5 where 5 is the half side length of the corner square
        selectedCornerIndex = i;
        break;
      }
    }

    if (selectedCornerIndex != null) {
      onMouseMove(html.MouseEvent moveEvent) {
        final newMouseX = moveEvent.client.x - rect.left;
        final newMouseY = moveEvent.client.y - rect.top;
        corners[selectedCornerIndex!]['x'] = newMouseX.toInt();
        corners[selectedCornerIndex]['y'] = newMouseY.toInt();
        drawCornersAndLines(context, corners);
      }

      final moveSubscription = html.document.onMouseMove.listen(onMouseMove);

      onMouseUp(html.MouseEvent upEvent) {
        moveSubscription.cancel();
      }

      html.document.onMouseUp.listen(onMouseUp);
    }
  });

  final html.ButtonElement saveButton = html.ButtonElement()
    ..innerText = 'Save'
    ..style.marginTop = '20px'
    ..style.padding = '10px 20px'
    ..style.fontSize = '16px'
    ..style.borderRadius = '5px'
    ..onClick.listen((_) {
      final html.CanvasElement canvas = html.CanvasElement();

      final width = corners[1]['x']! - corners[0]['x']!;
      final height = corners[1]['y']! - corners[0]['y']!;
      canvas.width = width;
      canvas.height = height;

      final html.CanvasRenderingContext2D context =
          canvas.getContext('2d') as html.CanvasRenderingContext2D;

      // Now I plot the image bounded by corners to canvas
      context.drawImageScaledFromSource(imageElement, corners[0]['x']!,
          corners[0]['y']!, width, height, 0, 0, width, height);

      final base64Image = canvas.toDataUrl().split(',').last;

      modal.remove();
      // Process and save the adjusted image if necessary
      completer.complete(
          base64Image); // Replace with actual adjusted image data if needed
    });

  final html.ButtonElement cancelButton = html.ButtonElement()
    ..innerText = 'Cancel'
    ..style.marginTop = '10px'
    ..style.padding = '10px 20px'
    ..style.fontSize = '16px'
    ..style.borderRadius = '5px'
    ..onClick.listen((_) {
      modal.remove();
      completer.complete(null);
    });

  modal.append(canvas);
  modal.append(saveButton);
  modal.append(cancelButton);
  html.document.body?.append(modal);

  return completer.future;
}