How to create an animation with the "svgwrite" library in python - python

I'm working on the creation of a bioinformatic tool using the library SVGWRITE.
I need some help with the using of the animate module, (like animateColor, animateMotion...), because even if I read the documentation, also read all the example in the svgwrite package, I couldn't find a way to have some informations about how to properly use it.
The SVG draw I'm creating is composed only with rectangles, what I call exon, this is how I'm creating them :
def drawExon(dwg,lineNumber,start,end,rvb):
"""
A function which draw a new exon on a opened dwg draw
it draw that exon from 'start', to 'end' (x position)
at the line 'lineNumber' (y position) with the color'rvb'
"""
dwg.add(dwg.rect((start,lineNumber*line_height),(end - start,
exon_height),fill=svgwrite.rgb(rvb[0],rvb[1],rvb[2])))
I would like to add a animation of theses rectangles, when I fly over the rectangle, I would like that an ID appear on that rectangle (in a text box above it) and also that the rectangle could change color.
The problem is that I have no idea of how and where to apply the animate module, neither what kind of arguments I have to give...
Well, I tried during the last two hours to do such a thing, I read many things on the following link:
http://svgwrite.readthedocs.org/en/latest/classes/animate.html#animate
But it didn't help me to find a answer.

Heres an example for rotating rectangle and color changing text
import svgwrite
path = [(100,100),(100,200),(200,200),(200,100)]
image = svgwrite.Drawing('test.svg',size=(300,300))
rectangle = image.add(image.polygon(path,id ='polygon',stroke="black",fill="white"))
rectangle.add(image.animateTransform("rotate","transform",id="polygon", from_="0 150 150", to="360 150 150",dur="4s",begin="0s",repeatCount="indefinite"))
text = image.add(image.text('rectangle1',insert=(150,30),id="text"))
text.add(image.animateColor("fill", attributeType="XML",from_="green", to="red",id="text", dur="4s",repeatCount="indefinite"))
image.save()
notice that animateColor dont work in every browsers

Related

How can I change the image layout options on python.docx?

I need to creat a archive with the same pattern that other one, but i need to do this with python. In this another archive i have a image with this following configuration the image and text are alligned, but when i try to put my image with the following code
p = doc.add_paragraph()
r = p.add_run()
r.add_picture(myPath)
r.add_text(myText)
the image stays alligned just to the first line of the text, like in this image allinged just with the first line.
I see that if i go into the word and change the layout options to this With Text Wrapping, the second option everything work exactaly as i want to. But how can I chage this layout options using python?
There is no API support for floating images in python-docx, which seems to be what you are asking about. Run.add_picture() adds a so-called "inline" picture (shape) which is treated like a single glyph (character in the run). So the line height grows to the height of the image and only that single line can abut the image.
One alternative would be to use a table with two cells, place the image in one cell and the text in the other.

Programming a picture maker template in Python possible?

I'm looking for a library that enables to "create pictures" (or even videos) with the following functions:
Accepting picture inputs
Resizing said inputs to fit given template / scheme
Positioning the pictures in pre-set up layers or coordinates
A rather schematic approach to look at this:
whereas the red spots are supposed to represent e.g. text, picture (or if possible video) elements.
The end goal would be to give the .py script multiple input pictures and the .py creating a finished version like mentioned above.
Solutions I tried were looking into Python PIL, but I wasn't able to find what I was looking for.
Yes, it is possible to do this with Python.
The library you are looking for is OpenCV([https://opencv.org][1]/).
Some basic OpenCV python tutorials (https://docs.opencv.org/master/d9/df8/tutorial_root.html).
1) You can use imread() function to read images from files.
2) You can use resize() function to resize the images.
3) You can create a empty master numpy array matching the size and depth(color depth) of the black rectangle in the figure you have shown, resize your image and copy the contents into the empty array starting from the position you want.
Below is a sample code which does something close to what you might need, you can modify this to suit your actual needs. (Since your requirements are not clear I have written the code like this so that it can at least guide you.)
import numpy as np
import cv2
import matplotlib.pyplot as plt
# You can store most of these values in another file and load them.
# You can modify this to set the dimensions of the background image.
BG_IMAGE_WIDTH = 100
BG_IMAGE_HEIGHT = 100
BG_IMAGE_COLOR_DEPTH = 3
# This will act as the black bounding box you have shown in your figure.
# You can also load another image instead of creating empty background image.
empty_background_image = np.zeros(
(BG_IMAGE_HEIGHT, BG_IMAGE_WIDTH, BG_IMAGE_COLOR_DEPTH),
dtype=np.int
)
# Loading an image.
# This will be copied later into one of those red boxes you have shown.
IMAGE_PATH = "./image1.jpg"
foreground_image = cv2.imread(IMAGE_PATH)
# Setting the resize target and top left position with respect to bg image.
X_POS = 4
Y_POS = 10
RESIZE_TARGET_WIDTH = 30
RESIZE_TARGET_HEIGHT = 30
# Resizing
foreground_image= cv2.resize(
src=foreground_image,
dsize=(RESIZE_TARGET_WIDTH, RESIZE_TARGET_HEIGHT),
)
# Copying this into background image
empty_background_image[
Y_POS: Y_POS + RESIZE_TARGET_HEIGHT,
X_POS: X_POS + RESIZE_TARGET_WIDTH
] = foreground_image
plt.imshow(empty_background_image)
plt.show()

Digital cursor movement recorded in PDF creation visible in CorelDraw

I am using CairoSVG to turn an SVG into a PDF. I have found a bug where each line of text has a 1 dimensional mark at the end when the PDF is loaded into CorelDraw.
I find this is true even with the simplest and barest of SVGs. I then decided to dig into the python source of CairoSVG to fix the issue at it's root. I have found text.py to be the place where the issue occurs.
https://github.com/Kozea/CairoSVG/blob/master/cairosvg/text.py
Specifically, the for [x, y, dx, dy, r], letter in letters_positions: for loop. I can actually manipulate the mark by doing this after the for loop.
surface.context.move_to( 100, 100 )
surface.context.save()
surface.context.text_path(' ')
surface.context.restore()
Depending on the values I enter, it will move one of the points (in this case the lower right point of the mark). This suggests that when CairoSVG is done with a line of text, the surface will move the cursor to the start of the last letter it was drawing. For some reason, the last time it does this is actually recorded into the PDF, although for most PDF viewers it does not render. I have tried to fine tune this mark so the two points are the same, but because this location is different each time depending on letter and location and more, I can't fine tune this number to make the mark disappear, even when using available width and height variables
Note that surface.context is not a file or function and surface is pprinted as <cairosvg.surface.PDFSurface object at 0x7f647802ec90>, it's some sort of Cairo interface for interacting with the PDF file directly through some sort of PDF API, although I haven't found any documentation on it.
I have tried lots of cheap work arounds, like saving the PDF in another program then opening in Corel, however elements are lost or altered in ways that are not acceptable.
I have also of course tried commenting out this file 1 line at a time, then chunks of code at a time, but with no luck.
I have also looked into other files such as path.py, parser.py, and more, but text.py seems to be the most promising location.
How can I prevent this mark from appearing in my PDF files?
I have found I could get the desired results by going into the CairoSVG code and using a different function to create the text elements onto the PDF.
This collects the letters into a variable.
# Collect entire line instead of letter
text_line_letters = ''
for [x, y, dx, dy, r], letter in letters_positions:
text_line_letters = text_line_letters + letter
# Skip rest of for loop
continue
This uses the new function to creates the actual text onto the PDF.
# Create Text with glyph_path
surface.context.save()
font = surface.context.get_scaled_font()
glyphs, clusters, is_backwards = font.text_to_glyphs(
0, -5, text_line_letters, with_clusters=True)
surface.context.glyph_path(glyphs)
surface.context.restore()
The actual root cause of the issue is unknown, but likely deeper inside the Cairo library itself.
https://github.com/bonzini/cairo/blob/9099c7e7307a39bc630919faa65bba089fd15104/src/cairo.c#L3349

Overlaying coloured pixels on top of an image using Python Imaging Library

Okay, first thing first. This is a near duplicate of this question.
However, the issue I am facing is slightly different in a critical way.
In my application, I read a generic file name in, load said image, and display it. Where it gets tricky is I have overlay the appearance of being 'highlighted'. To do this, I was using the Image.blend() function, and blending it with a straight yellow image.
However, when dealing with blend, I was fighting the error that the two images are not compatible to be blended. To solve this, I opened the sample image I had in paint, and just pasted yellow over the whole thing, and saved it as a copy.
It just occurred to me that this will fail when a different type of image is read in by file name. Remember this needs to be generic.
So my question is: Instead of making a copy of the image manually, can I get python to generate one by copying the image and modifying it so it is solid yellow? Note: I do not need to save it after, so just making it happen is enough.
Unfortunately, I am not allowed to share my code, but hopefully the following will give an idea of what I need:
from PIL import Image
desiredWidth = 800
desiredHeight = 600
primaryImage = Image.open("first.jpg").resize((desiredWidth, desiredHeight), Image.ANTIALIAS)
# This is the thing I need fixed:
highlightImage = Image.open("highlight.jpg").resize((desiredWidth, desiredHeight), Image.ANTIALIAS)
toDisplay = Image.blend(primaryImage, highlightImage, 0.3)
Thanks to anyone who can help.
Sounds like you want to make a new image:
fill_color = (255,255,0) #define the colour as (R,G,B) tuple
highlightImage = Image.new(primaryImage.mode, #same mode as the primary
primaryImage.size, #same size as the primary
fill_color)#and the colour defined above
this creates a new image with the same mode and size as the already opened image, but with a solid colour. Cheers.
Also if you are using Pillow instead of original PIL you can even get the color by name:
from PIL.ImageColor import getcolor
overlay = 'yellow'
fill_color = getcolor(overlay, primaryImage.mode)

Use Python / PIL or similar to shrink whitespace

Any ideas how to use Python with the PIL module to shrink select all? I know this can be achieved with Gimp. I'm trying to package my app as small as possible, a GIMP install is not an option for the EU.
Say you have 2 images, one is 400x500, other is 200x100. They both are white with a 100x100 textblock somewhere within each image's boundaries. What I'm trying to do is automatically strip the whitespace around that text, load that 100x100 image textblock into a variable for further text extraction.
It's obviously not this simple, so just running the text extraction on the whole image won't work! I just wanted to query about the basic process. There is not much available on Google about this topic. If solved, perhaps it could help someone else as well...
Thanks for reading!
If you put the image into a numpy array, it's simple to find the edges which you can use PIL to crop. Here I'm assuming that the whitespace is the color (255,255,255), you can adjust to your needs:
from PIL import Image
import numpy as np
im = Image.open("test.png")
pix = np.asarray(im)
pix = pix[:,:,0:3] # Drop the alpha channel
idx = np.where(pix-255)[0:2] # Drop the color when finding edges
box = map(min,idx)[::-1] + map(max,idx)[::-1]
region = im.crop(box)
region_pix = np.asarray(region)
To show what the results look like, I've left the axis labels on so you can see the size of the box region:
from pylab import *
subplot(121)
imshow(pix)
subplot(122)
imshow(region_pix)
show()
The general algorithmn would be to find the color of the top left pixel, and then do a spiral scan inwards until you find a pixel not of that color. That will define one edge of your bounding box. Keep scanning until you hit one more of each edge.
http://blog.damiles.com/2008/11/basic-ocr-in-opencv/
might be of some help. You can use the simple bounding box method described in that tutorial or #Tyler Eaves spiral suggestion which works equally as well

Categories