save gtk.DrawingArea to file - python

I want to save gtk.DrawingArea() object contents to jpeg file using PIL. Particularly I want add to this script possibility to make photo. I found how to save image to jpeg. All I need - get pixbuf object from gtk.DrawingArea() object. How can I do this?

If you're not married to the idea of using gstreamer, you can use OpenCV instead. This post gives a great example using pygame.
However, you can get the pixbuf this way (and you don't even need PIL):
def get_picture(self, event, data):
drawable = self.movie_window.window
colormap = drawable.get_colormap()
pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, 0, 8, *drawable.get_size())
pixbuf = pixbuf.get_from_drawable(drawable, colormap, 0,0,0,0, *drawable.get_size())
pixbuf.save(r'somefile.png', 'png')
pixbuf.save(r'somefile.jpeg', 'jpeg')
and then just create a button and bind the command to get_picture.
Of course, if I were writing this program I would actually grab the image to an Image in the first place and then draw it on the gtk.DrawingArea - that would allow you to do all sorts of fun things.

Related

PIL Gif generation not working as expected

What I'm trying to do: Since I'm still quite new to image generation using the PIL library, I decided to experiment with putting images on top of gifs. There were not a lot of proper tutorials or references I could use.
What's going wrong: More often than not, the gif would not be generated. This would give the error IndexError: bytearray index out of range which I'm not sure how to fix. However, sometimes the gif would be generated, but there would be some errors. I have included some of these gifs below.
The code:
#client.command()
async def salt(ctx, user:discord.Member=None):
if user == None:
user = ctx.author
animated_gif = Image.open("salty.gif")
response = requests.get(user.avatar_url)
background = Image.open(BytesIO(response.content))
all_frames = []
# background = background.resize((500, 500))
for gif_frame in ImageSequence.Iterator(animated_gif):
# duplicate background image
new_frame = background.copy()
# need to convert from `P` to `RGBA` to use it in `paste()` as mask for transparency
gif_frame = gif_frame.convert('RGBA')
# paste on background using mask to get transparency
new_frame.paste(gif_frame, mask=gif_frame)
all_frames.append(new_frame)
# save all frames as animated gif
all_frames[0].save("image.gif", save_all=True, append_images=all_frames[1:], duration=50, loop=0)
This is the gif I am using:
Unfortunately animated GIF support in PIL is faulty, and hard to work with at all. The images you are showing suffer from the layers sharing the palette information with the background layer, so they have some of their colors distorted.
I don't know if there is a way to control the palette information for each frame using PIL.
If you want to generate GIFs progamaticaly using Python, I'd, for now, recommend that you use the GIMP Image editor - there you can build your image, either interactively using the program, or programaticaly, using the Python console, and just call the "save as gif" function (pdb.file_gif_save2).
(I will take a look at PILs exact capabilities, and check if I can extend the answer on proper handling of transparency - otherwise, GIMP is the way to go)

ImageTk and PIL do not display png image correctly

I am currently trying to write some kind of mapping tool in python using both the PIL and Tkinter module. So far almost everything works quite fine. During the setup process of the ui a virtual image is created (based upon several input png files), which also seems to have worked well. However, when trying to display this picture inside a canvas using ImageTk.Photo the display shows something that is definitly not the picture. For debugging reasons I had my picture be output by using the show method on the PIL.Image itself.
However what the show method shows and the canvas displays somehow differ - I could not figure out the solution and would appreciate help.
First of all the code excerts (I only show the initialization of the canvas and the displaying of the picture, since the whole code would be extremly long and not provide any more inside I guess).
This is the code excert of the initialization of the canvas (I display a completly black picture until the user loaded all resources neccessary for displaying the picture):
self.tileset_canvas = tkinter.Canvas(root, width=1024, height=1024)
self.tileset_canvas.create_line(0, 0, 80, 80)
self.tileset_raw_image = ImageTk.PhotoImage(PImage.new("RGB", (1024, 1024), "black"))
self.tileset_canvas_image = self.tileset_canvas.create_image(0, 0, image=self.tileset_raw_image)
self.tileset_canvas.grid(row=4, column=6, sticky=tkinter.W)
Furthermore inside another method I change the display of the image:
merged_img = PImage.new("RGB", (128, 512))
merged_img.paste(tsp_img, (0, 0))
merged_img.paste(tss_img, (0, 320))
merged_img = merged_img.resize((1024, 1024)) #Double the view for a better mapping expierience
merged_img = merged_img.convert(mode="RGB")
self.tileset_raw_image = ImageTk.PhotoImage(merged_img)
merged_img.show()
self.tileset_canvas.itemconfig(self.tileset_canvas_image, image=self.tileset_raw_image)
As you can see I also call the show method to see what the picture actually looks like.
This is what the show method outputs, when called on the picture:
However this is what is shown inside the ui:
For anyone that cares, it seems that the image was not just correctly anchored but instead fixed in the middle of the canvas.

How to make simple graphs in python 2.7

I would like to make simple graphs for my web page in python/django, but I do not know, which library (and how) to use.
I DO NOT WANT CHARTS, I SEEK A WAY TO CREATE IMAGE FROM PRIMITIVES LIKE RECTANGLES.
Each such graph is probabely generated and used only one time, as next time the values would differ.
I can simply compute the positions of all rectangles, lines or texts in it, so I would like something lightweight to just create pictre from that, which I would return as img/png (or so) mime style
like <img src="http://my.web.www/my/page/graph" > where the parameters to show would be decidied by session and database.
I can compute all the sizes beforehand, so I would like something simple like
img=Image(PNG,598,89) # style, x, y
img.add_text('1.3.', 10,10)
img.add_rectagle(20,10, 70,20, CYAN, BLACK)
....
return img.render()
Can you direct me, how to do it?
Thanks beforehand
navit nailed it :)
# from django.utils.httpwrappers import HttpResponse
from PIL import Image, ImageDraw
import os,sys
im = Image.new('RGB',(598,89),'white')
draw = ImageDraw.Draw(im)
draw.rectangle((0,0,im.size[0]-1,im.size[1]-1), outline='blue')
draw.rectangle((25,10,590,20), fill='white', outline='black')
draw.rectangle((25,10,70,20), fill='rgb(255,0,0)', outline='black')
draw.rectangle((70,10,90,20), fill='green', outline='black')
draw.text((1,10),'1.3.',fill='black')
del draw
# write to stdout
im.save(sys.stdout, "PNG")
# draw.flush()
# response = HttpResponse(mimetype="image/png")
# image.save(response, "PNG")
# return response
You should check Pillow out. Here is a sample how it works:
from PIL import Image, ImageDraw
im = Image.open("lena.pgm")
draw = ImageDraw.Draw(im)
draw.line((0, 0) + im.size, fill=128)
draw.line((0, im.size[1], im.size[0], 0), fill=128)
del draw
# write to stdout
im.save(sys.stdout, "PNG")
Serving a file from Pillow to your client should be straightforward. Let me know if you have a question.
edit: found these examples to get you started.
http://matplotlib.org/ permits to generate plenty of great graphs. You should be able to save it as an image and integrate it to your webpage
What about plotly? Never used in a project, but by reading the examples it seems very powerful and easy to use. It has a static image export (as most graphic libraries probably have).

Kivy take screenshot with clear background

I'm working on a Kivy app that lets the user position images and text labels on a template. When they're done, the resulting image is cropped to fit the template.
I need all the empty space in the image to be clear, as I will be printing the image and don't want to waste ink. Kivy, however, fills all the empty space with black. Is there a way for Kivy's export_to_png() function to use a transparent background instead of a black one?
I could be wrong, but it looks like the transparent colour is hardcoded.
Looking at the source code it seems that ClearColor is hard-coded as black.
def export_to_png(self, filename, *args):
'''Saves an image of the widget and its children in png format at the
specified filename. Works by removing the widget canvas from its
parent, rendering to an :class:`~kivy.graphics.fbo.Fbo`, and calling
:meth:`~kivy.graphics.texture.Texture.save`.
.. note::
The image includes only this widget and its children. If you want
to include widgets elsewhere in the tree, you must call
:meth:`~Widget.export_to_png` from their common parent, or use
:meth:`~kivy.core.window.WindowBase.screenshot` to capture the whole
window.
.. note::
The image will be saved in png format, you should include the
extension in your filename.
.. versionadded:: 1.9.0
'''
if self.parent is not None:
canvas_parent_index = self.parent.canvas.indexof(self.canvas)
self.parent.canvas.remove(self.canvas)
fbo = Fbo(size=self.size, with_stencilbuffer=True)
with fbo:
ClearColor(0, 0, 0, 1)
ClearBuffers()
Scale(1, -1, 1)
Translate(-self.x, -self.y - self.height, 0)
I guess you could try updating the Widget module code to accept a parameter to set the ClearColor.

Python Image object to WxPython

I just want to display python image object in wxpython panel.
What i am trying to accomplish is taking screenshot using python ImageGrab or autopy and showing it in wxpython panel. My screenshot program running every second so there is no point save the image for wx.
import pyscreenshot as ImageGrab
imgobj = ImageGrab.grab()
print imgobj
# Convert into wximage
myWxImage = wx.EmptyImage( imgobj.size[0], imgobj.size[0] )
myWxImage.SetData( imgobj.convert( 'RGB' ).tostring())
Output
<Image.Image image mode=RGB size=1366x768 at 0x20B98F0>
ValueError:Invalid data buffer size.
It's not easy to tell without a full traceback, but I think the issue might be this typo:
myWxImage = wx.EmptyImage( imgobj.size[0], imgobj.size[0] )
Should be:
myWxImage = wx.EmptyImage( imgobj.size[0], imgobj.size[1] )
Also you could make your code simpler with:
myWxImage = wx.ImageFromBuffer(imgobj.size[0], imgobj.size[1], imgobj.convert('RGB').tostring())
I assume your problem is that you are passing the image width as new height to wx...
And btw instead you could use
myWxImage = wx.ImageFromBuffer( imgobj.size[0], imgobj.size[1], imgobj.tostring() )

Categories

Resources