pythonsvgsvgwrite

SVG, forming lines into an image


I'm forming an image in SVG from a bitmap using svgwrite and python where each line is rotated by theta around a common origin into a fan like-pattern. Currently this image is running around 10 MB for 128 lines largely because the excessive amount of floating point retained in the 79000+ line segments (one line segment per pixel).

ScanConverted Image

I'd like to get the image size down significantly by drawing a single line from the origin out to the end-point and then stretch one line 'image' over that SVG line. Is this possible using SVG? Beyond that, I'm open to any suggestion that might get the size down significantly and so I later I can animate the lines in place.


Solution

  • How about this solution (see fiddle):

    1. Slice the image up in the number of strips you need. For the example in the linked fiddle, I used ImageMagick as follows to cut up a 128x128 PNG image into 128 vertical strips:
      convert image.png -crop 1x128 +repage +adjoin strip-%d.png
    2. Convert all the image strips to data URI format and embed them in the SVG. I used this bash one-liner:
      for i in strip-*.png; do echo "data:image/png;base64,$(openssl base64 < $i | tr -d '\n')"; done > data-uris.txt
    3. In the SVG, use the transform() attribute on the image strip elements to rotate them to the required degree.

    For a 128x128 PNG icon of 16.4KB, I end up with an SVG file of 128.1KB. Most of that is the base64-encoded image data (the total size of the 128 PNG strips is already 85.1KB). It could be further reduced a little by rounding of some floats, but I don't think there's a whole lot to be gained.

    There might be another approach possible where you embed the image as a whole, and reference another clipped section of the same image over and over, but I couldn't get that to work.