pythonpython-3.xsvgvector-graphicsquickdraw

How to arrange objects in rows and columns and export in .svg


I'm new to Python, and I am trying to access Google's QuickDraw Database and arrange an amount of images (vector lines) as per the user's input of columns and rows, then export in .svg file format. So far, I have only managed to save each image as .gif and display it. How can I arrange them in a say 3x3 grid and in .svg format?

Here is the code I've got so far:

from PIL import Image, ImageDraw
from quickdraw.data import QuickDrawData

rows = int(input("How many rows do you want? "))
columns = int(input("How many columns do you want? "))
rows_columns = rows * columns
name_var = 0

for image in range(0,rows_columns):
    
    qd = QuickDrawData()
    duck = qd.get_drawing("duck")
    duck_image = Image.new("RGB", (255,255), color = (255,255,255))
    duck_drawing = ImageDraw.Draw(duck_image)

    for stroke in duck.strokes:

        for coordinate in range(len(stroke)-1):
            x1 = stroke[coordinate][0]
            y1 = stroke[coordinate][1]
            x2 = stroke[coordinate+1][0]
            y2 = stroke[coordinate+1][1]
            duck_drawing.line((x1,y1,x2,y2), fill=(0,0,0), width=2)

    duck_image.show()
    name_var += 1
    duck.image.save(f"my_duck{name_var}.gif")

This is ideally what the outcome should look like and in .svg file format.


Solution

  • You will need a python library that can output SVG files.

    Unfortunately I don't have the time to provided a detailed answer with a code snippet that just runs but hopefully I can provide some directions.

    There are mulitple python modules to write SVG files: svgwrite is one of them (docs, examples).

    Based on the example snippet:

    import svgwrite
    
    dwg = svgwrite.Drawing('test.svg', profile='tiny')
    dwg.add(dwg.line((0, 0), (10, 0), stroke=svgwrite.rgb(10, 10, 16, '%')))
    dwg.add(dwg.text('Test', insert=(0, 0.2), fill='red'))
    dwg.save()
    

    you should be able to do something like:

    from PIL import Image, ImageDraw
    from quickdraw.data import QuickDrawData
    import svgwrite
    
    dwg = svgwrite.Drawing('test.svg', profile='tiny')
    
    rows = int(input("How many rows do you want? "))
    columns = int(input("How many columns do you want? "))
    rows_columns = rows * columns
    name_var = 0
    
    for image in range(0,rows_columns):
        
        qd = QuickDrawData()
        duck = qd.get_drawing("duck")
        duck_image = Image.new("RGB", (255,255), color = (255,255,255))
        duck_drawing = ImageDraw.Draw(duck_image)
    
        for stroke in duck.strokes:
    
            for coordinate in range(len(stroke)-1):
                x1 = stroke[coordinate][0]
                y1 = stroke[coordinate][1]
                x2 = stroke[coordinate+1][0]
                y2 = stroke[coordinate+1][1]
                duck_drawing.line((x1,y1,x2,y2), fill=(0,0,0), width=2)
                # you many need to offset dwg.line using row/col grid index and drawing size
                dwg.add(dwg.line((x1, y1), (x2, y2), stroke=svgwrite.rgb(10, 10, 16, '%')))
    
        duck_image.show()
        name_var += 1
        duck.image.save(f"my_duck{name_var}.gif")
    # save svg of all ducks (grid)
    dwg.save()
        
    
    

    Bare in mind the code above isn't tested, but hopefull it illustrates the point. If you're new to the module I recommend a step by step approach:

    1. a basic test script writing a basic svg (e.g. example snippet): ensure the module is installed correctly and works
    2. a basic script using quickdraw and svgwrite to draw a single duck
    3. a script that draws a grid of ducks

    The idea is if any steps fail, it will be easier to debug/fix in isolation.

    I suspect you might also need to work out the dimensions/bounding box of each duck and scale/align to a same sized rectangle for the grid then offset each line coordinates. In theory you might be able to draw each duck as a group, then simply SVG translate each group so it's aligned as a grid (instead of all ducks overlapping)

    Additionally you might find sketch-rnn interesting since it uses the quickdraw dataset. In particular checkout David Ha's Sketch-RNN Colab notebook or his sketch-rnn/utils.py script. Even though the QuickDraw stroke format is slightly different from the sketch-rnn stroke format, there are still plenty of similarities and the links above include utility functions to draw an svg grid. They need adapting to QuickDraw's format.

    If you're not constrained to Python alone and are comfortable with a bit of JavaScript the QuickDraw dataset README already inlcudes a link to a d3.js SVG demo