MBulli

New implementation for calculateScanWindowRelativeToTextureInPercentage()

  1 +import 'dart:math';
  2 +
1 import 'package:flutter/rendering.dart'; 3 import 'package:flutter/rendering.dart';
2 4
3 /// the [scanWindow] rect will be relative and scaled to the [widgetSize] not the texture. so it is possible, 5 /// the [scanWindow] rect will be relative and scaled to the [widgetSize] not the texture. so it is possible,
@@ -14,57 +16,75 @@ Rect calculateScanWindowRelativeToTextureInPercentage( @@ -14,57 +16,75 @@ Rect calculateScanWindowRelativeToTextureInPercentage(
14 Size textureSize, 16 Size textureSize,
15 Size widgetSize, 17 Size widgetSize,
16 ) { 18 ) {
17 - double fittedTextureWidth;  
18 - double fittedTextureHeight; 19 + /// map the texture size to get its new size after fitted to screen
  20 + final fittedTextureSize = applyBoxFit(fit, textureSize, widgetSize);
  21 +
  22 + // Get the correct scaling values depending on the given BoxFit mode
  23 + double sx = fittedTextureSize.destination.width / textureSize.width;
  24 + double sy = fittedTextureSize.destination.height / textureSize.height;
19 25
20 switch (fit) { 26 switch (fit) {
  27 + case BoxFit.fill:
  28 + // nop
  29 + // Just use sx and sy
  30 + break;
21 case BoxFit.contain: 31 case BoxFit.contain:
22 - final widthRatio = widgetSize.width / textureSize.width;  
23 - final heightRatio = widgetSize.height / textureSize.height;  
24 - final scale = widthRatio < heightRatio ? widthRatio : heightRatio;  
25 - fittedTextureWidth = textureSize.width * scale;  
26 - fittedTextureHeight = textureSize.height * scale; 32 + final s = min(sx, sy);
  33 + sx = s;
  34 + sy = s;
27 break; 35 break;
28 -  
29 case BoxFit.cover: 36 case BoxFit.cover:
30 - final widthRatio = widgetSize.width / textureSize.width;  
31 - final heightRatio = widgetSize.height / textureSize.height;  
32 - final scale = widthRatio > heightRatio ? widthRatio : heightRatio;  
33 - fittedTextureWidth = textureSize.width * scale;  
34 - fittedTextureHeight = textureSize.height * scale; 37 + final s = max(sx, sy);
  38 + sx = s;
  39 + sy = s;
35 break; 40 break;
36 -  
37 - case BoxFit.fill:  
38 - fittedTextureWidth = widgetSize.width;  
39 - fittedTextureHeight = widgetSize.height; 41 + case BoxFit.fitWidth:
  42 + sy = sx;
40 break; 43 break;
41 -  
42 case BoxFit.fitHeight: 44 case BoxFit.fitHeight:
43 - final ratio = widgetSize.height / textureSize.height;  
44 - fittedTextureWidth = textureSize.width * ratio;  
45 - fittedTextureHeight = widgetSize.height;  
46 - break;  
47 -  
48 - case BoxFit.fitWidth:  
49 - final ratio = widgetSize.width / textureSize.width;  
50 - fittedTextureWidth = widgetSize.width;  
51 - fittedTextureHeight = textureSize.height * ratio; 45 + sx = sy;
52 break; 46 break;
53 -  
54 case BoxFit.none: 47 case BoxFit.none:
  48 + sx = 1.0;
  49 + sy = 1.0;
  50 + break;
55 case BoxFit.scaleDown: 51 case BoxFit.scaleDown:
56 - fittedTextureWidth = textureSize.width;  
57 - fittedTextureHeight = textureSize.height; 52 + final s = min(sx, sy);
  53 + sx = s;
  54 + sy = s;
58 break; 55 break;
59 } 56 }
60 57
61 - final offsetX = (widgetSize.width - fittedTextureWidth) / 2;  
62 - final offsetY = (widgetSize.height - fittedTextureHeight) / 2; 58 + // Fit the texture size to the widget rectangle given by the scaling values above
  59 + final textureWindow = Alignment.center.inscribe(
  60 + Size(textureSize.width * sx, textureSize.height * sy),
  61 + Rect.fromLTWH(0, 0, widgetSize.width, widgetSize.height),
  62 + );
  63 +
  64 + // Transform the scan window from widget coordinates to texture coordinates
  65 + final scanWindowInTexSpace = Rect.fromLTRB(
  66 + (1 / sx) * (scanWindow.left - textureWindow.left),
  67 + (1 / sy) * (scanWindow.top - textureWindow.top),
  68 + (1 / sx) * (scanWindow.right - textureWindow.left),
  69 + (1 / sy) * (scanWindow.bottom - textureWindow.top),
  70 + );
  71 +
  72 + // Clip the scan window in texture coordinates with the texture bounds.
  73 + // This prevents percentages outside the range [0; 1].
  74 + final clippedScanWndInTexSpace = scanWindowInTexSpace
  75 + .intersect(Rect.fromLTWH(0, 0, textureSize.width, textureSize.height));
63 76
64 - final left = (scanWindow.left - offsetX) / fittedTextureWidth;  
65 - final top = (scanWindow.top - offsetY) / fittedTextureHeight;  
66 - final right = (scanWindow.right - offsetX) / fittedTextureWidth;  
67 - final bottom = (scanWindow.bottom - offsetY) / fittedTextureHeight; 77 + // Compute relative rectangle coordinates with respect to the texture size, i.e. scan image
  78 + final percentageLeft = clippedScanWndInTexSpace.left / textureSize.width;
  79 + final percentageTop = clippedScanWndInTexSpace.top / textureSize.height;
  80 + final percentageRight = clippedScanWndInTexSpace.right / textureSize.width;
  81 + final percentageBottom = clippedScanWndInTexSpace.bottom / textureSize.height;
68 82
69 - return Rect.fromLTRB(left, top, right, bottom); 83 + // This rectangle can be send to native code and used to cut out a rectangle of the scan image
  84 + return Rect.fromLTRB(
  85 + percentageLeft,
  86 + percentageTop,
  87 + percentageRight,
  88 + percentageBottom,
  89 + );
70 } 90 }