'running python script drawing svg image based on html inputs inside flask app

Assuming I've got a flask app I would like to call a python script, which would take the values of some inputs within the page (texts, selects, etc.) and then create the .svg image based on these parameters (using cairo lib). And finally it would have to reload the img element so it points to updated version of .svg image. I would like to know what would be the best way to handle that as I see some problem that may occur. If the physical file would be created and more than one person will use the app there will be collision (all the users would try to change the same file).

[EDIT from 2022.04.18]
As there was no answers in the meantime I tried to solve this problem by myself. I decided to generate a numpy array and then Pil Image object. Then replace it with some jQuery Ajax call. Almost all is working now,but unfortunately I encountered problem with the array size. My simplified function for that is:

def generateIMG():
   width, height = 255, 255
   surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
   buf = surface.get_data()
   context = cairo.Context(surface)
   context.rectangle(0,0,100,200)
   context.set_source_rgb(0,0,1)
   context.fill()
   data = numpy.ndarray(shape=(width, height), dtype=numpy.uint32, buffer=buf)
   print(f"format: {surface.get_format()}")
   print(f"width: {surface.get_width()}")
   print(f"height: {surface.get_height()}")
   print(f"stride: {surface.get_stride()}")
   print(f"buf len: {len(buf)}")
   return data

It is same as in pycairo website section "Integration with other Libraries" but with some drawing (blue rectangle) added and with some prints to see what is happening.

In my flask route I've got:

#some other code above
data = generateIMG()
img = Image.fromarray(data)
img.save(mem_bytes, 'PNG')
mem_bytes.seek(0)
img_base64 = base64.b64encode(mem_bytes.getvalue()).decode('ascii')
mime = "image/jpeg"
uri = "data:%s;base64,%s"%(mime, img_base64)
return render_template('drawing.html', plot=uri)

If my code is as above, just black square background is drawn (with size 255 by 255). len(buf) prints the value of 260 100 which is equal to 255 x 255 x 4 (as ARGB needs 4 bytes), so it is exactcly same as required. However picture is not printed at all (just black background).

When I change to shape=(width, height, 4) and dtype=numpy.uint32 there is error: "TypeError: buffer is too small for requested array", which of course was expected.

When shape=(width, height, 4) and dtype=numpy.uint8 there is red square instead of blue. So colour is wrong (which was expected), but the shape is proper - so it prints the picture but with loss of informaton about colour.

And when I change to: base64.b32encode() it displays icon of crushed image.

So what should I change to get a proper picture? Shall I reshape the numpy array so it is 4 times bigger? I expect it should work without that, but with some small change to the code. Any help appreciated.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source