4Q-s-r-o / signature

Flutter plugin that creates a canvas for writing down a signature
MIT License
252 stars 83 forks source link

svg export can have a reduced size #104

Open ysimonx opened 6 months ago

ysimonx commented 6 months ago

For a single signature, i have a 8Bbytes svg export

If you keep int instead of float in "points" if you remove duplicate "points"

you can reduce a 8KBytes to 2Kbytes

orig output

here is the python code used for this


import re
import xml.etree.ElementTree as ET

svg = '<svg viewBox="0 0 437 183" xmlns="http://www.w3.org/2000/svg">'
svg = svg + '<polyline fill="none" stroke="#f44336" stroke-opacity="1.0" points="121.00,54.93 121.00,54.93 121.00,54.93 121.00,54.93 121.00,54.93 121.00,54.93 121.00,54.93 121.00,54.93 132.80,50.89 150.66,46.17 161.45,40.44 173.58,36.39 186.39,32.35 199.20,27.97 213.02,23.58 229.88,20.55 250.10,17.18 265.94,14.48 286.51,11.79 307.40,9.76 307.40,9.76" stroke-linecap="round" stroke-width="1.0" />'
svg = svg + '<polyline fill="none" stroke="#f44336" stroke-opacity="1.0" points="13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 13.47,70.44 15.16,68.75 19.54,64.71 24.60,59.99 29.65,54.26 33.36,48.19 36.06,42.46 38.42,39.43 41.11,35.72 43.47,32.69 45.83,28.98 48.19,25.61 50.21,22.91 51.90,19.54 53.25,16.84 54.26,13.81 55.27,11.11 55.61,9.43 55.61,6.73 55.27,5.04 54.93,4.03 54.60,3.02 53.92,2.01 52.24,1.00 50.55,1.00 47.85,1.34 44.82,2.35 41.79,4.03 38.42,6.39 35.38,9.76 31.34,14.15 27.63,18.87 23.58,23.92 19.88,29.31 16.51,35.38 13.13,42.12 10.10,48.53 7.74,54.60 5.38,60.66 3.36,66.73 2.35,72.46 1.67,76.84 1.34,81.22 1.00,85.27 1.34,88.64 2.01,91.34 2.69,93.36 4.03,95.38 5.38,97.07 8.08,98.75 11.11,100.78 14.48,102.12 17.85,103.13 22.57,103.81 27.97,104.15 34.03,103.47 39.43,102.46 45.16,101.79 50.89,100.10 55.94,98.08 61.34,96.06 66.73,93.36 70.78,90.66 74.82,88.30 78.19,85.61 81.90,83.25 84.60,80.89 87.29,77.85 88.98,76.51 90.33,74.48 91.34,72.80 92.35,71.79 92.69,71.11 92.69,70.10 93.02,69.43 93.36,69.09 93.36,69.09 93.36,68.75 94.03,68.75 94.03,69.09 94.37,69.09 94.37,69.76 95.04,71.11 95.38,72.12 95.72,73.81 95.72,74.82 95.72,76.84 95.72,78.87 95.72,79.88 96.06,81.22 96.06,82.91 96.39,84.26 96.73,85.27 97.07,86.28 97.40,87.29 97.74,87.63 98.08,88.30 99.09,88.64 100.44,89.31 101.11,89.31 102.80,88.98 103.81,88.64 105.16,87.97 106.17,86.96 107.85,85.27 109.20,83.58 110.21,81.56 110.89,79.88 111.56,78.53 111.90,77.52 112.24,76.84 112.24,76.51 112.24,76.17 112.24,76.84 112.24,78.53 112.24,80.21 112.24,81.90 112.57,83.58 112.57,85.27 112.91,87.29 113.58,88.98 113.92,91.00 114.26,92.69 114.60,94.03 115.61,95.72 116.28,97.07 117.29,98.08 118.30,98.75 120.33,100.10 122.01,100.78 124.37,101.11 127.07,100.78 129.43,100.10 132.12,98.75 135.49,96.73 138.19,94.03 141.22,91.00 144.26,86.62 147.29,82.24 149.99,77.52 152.01,72.46 153.70,68.08 155.38,63.70 157.07,59.65 158.75,54.93 160.44,49.54 162.12,44.48 163.13,40.10 164.48,36.06 165.49,32.35 166.17,28.64 167.18,25.27 167.52,22.24 168.19,20.21 168.53,18.19 168.53,17.18 168.87,16.17 168.87,15.83 168.87,16.51 169.20,17.85 169.20,19.88 169.20,22.91 169.20,26.62 169.20,30.33 169.20,34.71 168.87,39.43 168.19,45.16 167.85,51.56 167.85,57.63 167.85,64.37 167.85,70.44 168.53,77.18 169.54,83.25 170.21,88.30 170.89,92.69 172.57,96.73 173.58,99.76 174.93,102.46 175.94,104.82 177.29,106.51 178.30,107.52 179.99,109.20 182.35,109.88 183.36,110.21 185.72,109.88 187.74,108.87 189.76,107.18 192.12,104.82 195.16,100.10 197.85,95.04 199.88,90.33 202.24,84.93 204.26,79.20 205.61,73.47 206.96,68.42 207.97,64.37 208.98,60.66 209.65,57.63 210.33,54.93 210.33,52.91 210.66,50.55 211.00,49.54 211.34,48.87 211.67,47.52 212.01,46.84 212.01,46.51 212.69,46.17 212.69,46.51 212.69,46.84 213.02,48.19 213.02,49.20 213.36,50.55 213.36,52.24 213.02,53.92 213.02,55.27 212.69,56.96 212.69,58.98 212.01,61.00 212.01,62.69 211.67,64.37 211.34,65.38 211.34,66.39 211.00,67.74 211.00,69.09 211.00,69.43 211.00,70.10 211.34,70.44 211.34,70.78 211.67,71.11 212.01,71.79 213.02,72.46 213.70,73.13 214.71,73.47 216.06,74.48 217.40,75.16 218.75,75.49 220.10,76.17 221.79,76.84 223.47,77.18 224.82,77.52 225.83,77.52 227.18,77.85 228.53,78.53 229.88,78.87 230.89,79.20 232.57,79.54 233.58,80.21 234.26,80.21 235.27,80.55 236.62,80.89 237.63,81.22 238.64,81.22 239.65,81.56 240.66,81.90 241.00,82.24 241.67,82.24 243.36,82.91 244.37,82.91 245.72,83.25 247.07,83.92 248.42,84.60 250.10,85.27 252.12,86.28 253.47,87.29 255.83,88.64 258.19,90.33 260.89,91.34 263.58,92.69 266.28,94.03 268.64,95.04 271.67,95.72 274.37,96.06 277.40,96.73 280.10,96.73 282.80,96.73 286.17,96.06 288.87,95.38 291.90,94.03 293.92,93.36 296.28,92.01 297.97,91.00 298.98,90.33 300.33,88.98 301.34,88.30 303.02,86.96 304.37,85.94 305.04,85.27 305.72,84.93 306.06,84.60 306.39,84.60 307.07,83.92 307.40,83.92 307.40,83.58 307.74,83.58 308.08,83.25 308.42,82.91 308.75,82.91 309.09,82.57 309.43,82.57 309.76,82.57 310.10,82.91 310.44,83.25 310.44,84.26 310.44,85.94 309.76,87.63 309.43,88.98 309.43,90.66 309.43,92.69 309.09,95.38 308.75,98.08 307.74,101.79 307.07,104.82 306.06,108.53 305.72,111.56 305.38,114.93 305.04,118.30 303.70,122.35 302.69,126.39 302.35,130.10 301.67,134.15 301.00,137.85 300.66,141.56 299.99,145.61 299.99,149.31 300.33,153.02 300.66,157.07 301.00,160.10 301.67,163.47 302.35,166.84 303.02,169.88 304.03,171.90 304.71,173.92 305.04,175.94 305.72,177.29 306.39,178.30 307.40,179.65 308.42,180.66 308.75,181.00 309.43,181.34 310.44,182.01 311.45,182.01 312.12,182.01 313.47,181.34 314.15,180.33 315.49,178.64 316.84,175.94 317.85,173.25 318.87,169.54 319.20,166.17 319.88,162.12 321.22,157.07 321.90,152.01 322.57,146.62 323.25,141.90 323.58,136.51 324.26,131.11 324.93,126.06 325.27,120.66 325.61,116.28 326.28,111.90 326.62,107.52 327.63,103.47 328.30,99.76 328.64,96.39 329.31,93.36 329.99,91.00 330.66,88.98 331.00,87.29 331.34,86.62 331.67,86.28 331.67,85.61 332.01,85.61 332.01,85.27 332.35,85.27 332.35,84.93 332.69,84.93 333.02,84.93 333.36,85.27 333.70,85.27 333.70,85.61 334.71,86.62 335.38,87.63 335.72,88.98 336.39,90.33 337.07,91.34 337.40,92.35 337.74,93.70 338.08,94.71 338.42,95.38 339.09,96.39 339.76,97.07 341.11,97.74 342.12,98.42 342.80,98.42 344.15,98.08 345.16,97.74 346.84,96.73 348.19,95.72 349.20,94.71 350.55,93.02 351.90,91.00 352.91,89.31 354.26,87.63 355.27,86.28 356.28,85.27 357.29,83.58 357.63,83.25 357.97,82.57 358.64,81.90 358.98,81.56 359.31,81.56 359.65,81.22 359.99,81.22 360.33,81.22 360.66,81.56 361.00,81.90 361.34,82.24 361.34,82.91 361.67,83.25 362.01,83.25 362.01,83.58 362.35,83.92 362.69,84.26 363.02,84.60 363.70,84.93 364.71,85.27 365.04,84.93 366.06,84.60 366.73,84.26 367.07,83.92 368.42,82.57 369.43,80.89 370.44,79.20 371.45,77.18 372.12,75.49 372.80,73.47 373.13,71.45 373.47,69.76 373.81,68.08 373.81,66.39 373.81,65.04 373.81,63.36 373.81,62.69 373.81,61.34 373.47,59.99 373.47,59.31 373.47,58.64 373.13,58.30 372.80,57.97 372.80,57.63 372.46,57.63 372.12,57.63 371.79,57.63 371.45,57.97 370.78,57.97 370.44,58.30 370.10,58.64 369.76,59.31 369.43,59.65 369.43,60.33 369.09,61.34 369.43,62.35 370.44,63.70 371.11,65.04 372.12,66.06 373.81,67.74 375.49,69.09 377.52,70.10 379.54,70.78 381.22,71.11 383.58,71.11 385.27,71.11 387.63,71.11 389.65,71.11 391.34,70.78 392.69,70.78 393.70,70.78 394.71,70.78 395.38,70.78 395.38,71.11 395.72,71.11 395.72,71.45 395.72,71.79 395.38,72.12 393.70,73.47 391.67,74.48 389.65,75.16 387.63,75.49 386.28,75.83 384.60,76.51 383.25,77.18 381.22,78.19 380.21,78.53 379.20,78.87 378.19,79.54 377.52,80.21 377.18,80.21 376.84,80.21 377.18,80.21 377.85,79.20 379.88,77.52 381.56,76.17 383.58,74.15 385.27,72.12 387.29,70.10 388.64,68.42 390.33,66.06 391.67,64.37 393.02,62.01 394.03,60.66 395.04,58.98 395.38,58.30 395.72,56.96 395.72,56.62 395.72,55.94 395.72,55.61 395.72,55.27 395.38,55.27 395.04,55.27 393.70,55.61 392.35,56.28 391.34,57.29 390.33,59.31 389.31,61.67 389.31,64.03 389.65,67.40 391.00,71.11 393.02,75.16 396.06,79.20 399.09,83.58 402.12,87.97 405.83,91.00 410.21,94.37 414.93,97.40 422.35,100.10 430.44,101.79 433.81,102.80 436.51,103.13 436.51,103.13" stroke-linecap="round" stroke-width="1.0" />'
svg = svg + '</svg>'

root = ET.fromstring(svg)
ET.register_namespace("", "http://www.w3.org/2001")
ET.register_namespace("","http://www.w3.org/2000/svg")

newx_prec=-1
newy_prec=-1

for child in root.iter():
    if (child.tag.endswith("polyline")):
        tabPointsDest=[]
        sPoints=child.get("points")
        tabPoints=sPoints.split(" ")
        for point in tabPoints:
            x,y=point.split(",")
            newx= str(round(float(x)))
            newy = str(round(float(y)))
            # print(newx, newy)
            if (newx != newx_prec):
                if (newy != newy_prec):
                    s=newx+","+newy
                    tabPointsDest.append(s)
                    newx_prec=newx
                    newy_prec=newy
        new_attrib=" ".join(tabPointsDest)
        child.set("points",new_attrib)

s=ET.tostring(root, 'utf-8')
print(s.decode())
ysimonx commented 6 months ago

here is the code to remove too much close points and to convert float to int in dart


import 'package:xml/xml.dart';
...
final String stringSVG = _controller.toRawSVG()!;
final String stringSVGReduced =
        optimiseSVG(stringSVG, float2int: true, minDistanceBetweenPoints: 3);

 String optimiseSVG(String stringSVG,
      {bool float2int = false, int minDistanceBetweenPoints = 0}) {
    final document = XmlDocument.parse(stringSVG);
    var svgroot = document.root;

    for (XmlElement child in svgroot.childElements) {
      if (child.localName == "svg") {
        for (XmlElement childsvg in child.childElements) {
          if (childsvg.localName == "polyline") {
            List attrs = childsvg.attributes;
            for (XmlAttribute attr in attrs) {
              if (attr.localName == "points") {
                String value = attr.value;
                List<String> points = value.split(" ");
                List<String> filteredPoints = [];
                dynamic x_prec = -1;
                dynamic y_prec = -1;

                for (String point in points) {
                  List<String> xy = point.split(",");
                  double doublex = double.parse(xy[0]);
                  double doubley = double.parse(xy[1]);
                  dynamic x;
                  dynamic y;
                  if (float2int) {
                    x = doublex.round();
                    y = doubley.round();
                  } else {
                    x = doublex;
                    y = doubley;
                  }
                  if ((x - x_prec).abs() > minDistanceBetweenPoints ||
                      (y - y_prec).abs() > minDistanceBetweenPoints) {
                    String s = "${x},${y}";
                    filteredPoints.add(s);
                    x_prec = x;
                    y_prec = y;
                  }
                }
                childsvg.setAttribute("points", filteredPoints.join(" "));
              }
            }
          }
        }
      }
    }
    return document.toString();
  }
MartinHlavna commented 4 months ago

Hi, thanks, we will analyze this.