I'm trying to open image (jpg) from the buffer (get as blob from Oracle database) as Gtk.Image() and add it to a Gtk window, but I get error "Expected Gtk.Widget, but got PIL.JpegImagePlugin.JpegImageFile". I can show the image with show(), I can window.add jpeg file from path on the disc, and then show the window, but when I try to add jpg from buffer I get the error. Here is what I produced:
my_source=Here_I_get_BLOB_img_from_database()
newimage=Gtk.Image()
newimage=my_source.read()
image=io.BytesIO(newimage)
dt=Image.open(image)
newwindow = Gtk.Window(modal=True)
In this point actually I have jpg in buffer and I can do:
dt.show() # to display the image in system imageviewer
Or save dt as jpg, or add to newwindow a result of image.set_from_file("path with jpg extension") but don't know how to do this:
newwindow.add(dt)
Or anything with similar effect. How to do this in simplest way?
What worked for me was -
Gtk.Image to load img from buffer has Pixbuf object, which for example can be loaded from stream. So:
from gi.repository import (...) GdkPixbuf, GLib, Gio
(...)
my_source=Here_I_get_BLOB_img_from_database()
newimage=my_source.read()
glib=GLib.Bytes.new(newimage)
stream = Gio.MemoryInputStream.new_from_bytes(glib)
pixbuf = GdkPixbuf.Pixbuf.new_from_stream(stream, None)
image=Gtk.Image().new_from_pixbuf(pixbuf)
my_window = Gtk.Window(modal=True, title="Image")
my_window.add(image)
image.show()
my_window.show()
Related
Now, I have a python game that has sprites, and it obtains the images from files in its directory. I want to make it such that I do not even need the files. Somehow, to pre-store the image in a variable so that i can call it from within the program, without the help of the additional .gif files
The actual way i am using the image is
image = PIL.Image.open('image.gif')
So it would be helpful if you could be precise about how to replace this code
Continuing #eatmeimadanish's thoughts, you can do it manually:
import base64
with open('image.gif', 'rb') as imagefile:
base64string = base64.b64encode(imagefile.read()).decode('ascii')
print(base64string) # print base64string to console
# Will look something like:
# iVBORw0KGgoAAAANS ... qQMAAAAASUVORK5CYII=
# or save it to a file
with open('testfile.txt', 'w') as outputfile:
outputfile.write(base64string)
# Then make a simple test program:
from tkinter import *
root = Tk()
# Paste the ascii representation into the program
photo = 'iVBORw0KGgoAAAANS ... qQMAAAAASUVORK5CYII='
img = PhotoImage(data=photo)
label = Label(root, image=img).pack()
This is with tkinter PhotoImage though, but I'm sure you can figure out how to make it work with PIL.
Here is how you can open it using PIL. You need a bytes representation of it, then PIL can open a file like object of it.
import base64
from PIL import Image
import io
with open("picture.png", "rb") as file:
img = base64.b64encode(file.read())
img = Image.open(io.BytesIO(img))
img.show()
I have a function that gets a page from a PDF file via pyPdf2 and should convert the first page to a png (or jpg) with Pillow (PIL Fork)
from PyPDF2 import PdfFileWriter, PdfFileReader
import os
from PIL import Image
import io
# Open PDF Source #
app_path = os.path.dirname(__file__)
src_pdf= PdfFileReader(open(os.path.join(app_path, "../../../uploads/%s" % filename), "rb"))
# Get the first page of the PDF #
dst_pdf = PdfFileWriter()
dst_pdf.addPage(src_pdf.getPage(0))
# Create BytesIO #
pdf_bytes = io.BytesIO()
dst_pdf.write(pdf_bytes)
pdf_bytes.seek(0)
file_name = "../../../uploads/%s_p%s.png" % (name, pagenum)
img = Image.open(pdf_bytes)
img.save(file_name, 'PNG')
pdf_bytes.flush()
That results in an error:
OSError: cannot identify image file <_io.BytesIO object at 0x0000023440F3A8E0>
I found some threads with a similar issue, (PIL open() method not working with BytesIO) but I cannot see where I am wrong here, as I have pdf_bytes.seek(0) already added.
Any hints appreciated
Per document:
write(stream) Writes the collection of pages added to this object out
as a PDF file.
Parameters: stream – An object to write the file to. The object must
support the write method and the tell method, similar to a file
object.
So the object pdf_bytes contains a PDF file, not an image file.
The reason why there are codes like above work is: sometimes, the pdf file just contains a jpeg file as its content. If your pdf is just a normal pdf file, you can't just read the bytes and parse it as an image.
And refer to as a more robust implementation: https://stackoverflow.com/a/34116472/334999
[![enter image description here][1]][1]
import glob, sys, fitz
# To get better resolution
zoom_x = 2.0 # horizontal zoom
zoom_y = 2.0 # vertical zoom
mat = fitz.Matrix(zoom_x, zoom_y) # zoom factor 2 in each dimension
filename = "/xyz/abcd/1234.pdf" # name of pdf file you want to render
doc = fitz.open(filename)
for page in doc:
pix = page.get_pixmap(matrix=mat) # render page to an image
pix.save("/xyz/abcd/1234.png") # store image as a PNG
Credit
[Convert PDF to Image in Python Using PyMuPDF][2]
https://towardsdatascience.com/convert-pdf-to-image-in-python-using-pymupdf-9cc8f602525b
I am using python( my version is 2.7 ). I want to add an image to GUI (Tkinter) and then convert into executable format using pyinstaller.
I did followed as on SO, and also as said on ActiveState
When i mention the image's path on the code, it works only if i run it directly. If i convert it to exe it doesnt open.
Changing the code as mentioned from other solutions, like by converting it into encoded string, it runs fine on linux. But on windows it throws error
code:
from Tkinter import *
from PIL import ImageTk, Image
logo = '''
----- encoded string -----
'''
root = Tk()
logoimage = Tkinter.PhotoImage(master=root, data=logo)
Label(root, image=logoimage).pack()
root.mainloop()
Change 1:
The above code works on linux. On windows i get error on the line logoimage = Tkinter.PhotoImage(master=root, data=logo) as
NameError: name 'Tkinter' is not defined
Change 2:
So i tries changing the line as logoimage = ImageTk.PhotoImage(master=root, data=logo). The error i get is
File "C:\Python27\lib\site-packages\PIL\ImageTk.py", line 88, in __init__
image = Image.open(BytesIO(kw["data"]))
File "C:\Python27\lib\site-packages\PIL\Image.py", line 2330, in open
% (filename if filename else fp))
IOError: cannot identify image file <_io.BytesIO object at 0x00000000024BB150>
Exception AttributeError: "'PhotoImage' object has no attribute '_PhotoImage__photo'" in <bound method PhotoImage.__del__ of <PIL.ImageTk.PhotoImage object at 0x00000000024D49E8>> ignored
Change 3:
But, if i change the line as iconImage= ImageTk.PhotoImage(Image.open('path_to_image.png')). It works only if i run directly. If i convert it to executable, then console opens for 2-3 seconds and displaying error something like Unable to locate the image file
Doing the decoding and converting explicitly may be more robust than what you're currently doing. This code works on Python 2.6.6 on Linux.
import io, base64
from Tkinter import *
from PIL import ImageTk, Image
#A simple 64x64 PNG fading from orange in the top left corner
# to red in the bottom right, encoded in base64
logo_b64 = '''
iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAIA
AAAlC+aJAAAA/0lEQVR4nO3Zyw7CMAxEUdP//+W2rCqBoJA2noclS1kn9yjLeex7xKY76+
wNS+l6KSCjXgdIqhcB8uoVgNR6OiC7ngsA1BMBmHoWAFZPASDr8QBwPRiAr0cCKPUwAKse
AyDWAwDc+mwAvT4VoKjPA4jqkwC6+gyAtD7WSYC6fu4HDOonAB71dwE29bcATvXXAWb1Fw
F+9VcAlvXDANf6MYBx/QDAu/4fwL7+J6BC/TmgSP0JoE79N0Cp+g9Atfp3QMH6F0DN+gNQ
tj62WErXB2PgQNZLAb3U6wC91OsAvdTrAL3U6wC91OsAvdTrAL3U6wC91OsAvdTrAL3Uz7
z+BNmX4gqbppsaAAAAAElFTkSuQmCC
'''
#Decode the PNG data & "wrap" it into a file-like object
fh = io.BytesIO(base64.b64decode(logo_b64))
#Create a PIL image from the PNG data
img = Image.open(fh, mode='r')
#We must open the window before calling ImageTk.PhotoImage
root = Tk()
photo = ImageTk.PhotoImage(image=img)
Label(root, image=photo).pack()
Label(root, text='An embedded\nbase64-encoded PNG').pack()
root.mainloop()
For reference, here's what that embedded PNG looks like.
from Tkinter import *
#...
logoimage = Tkinter.PhotoImage(master=root, data=logo)
If you dump the Tkinter module straight into the global scope using import *, then you shouldn't prefix class and function names with the module name. Either remove the prefix, or remove the import *.
import Tkinter
#...
logoimage = Tkinter.PhotoImage(master=root, data=logo)
Or
from Tkinter import *
#...
logoimage = PhotoImage(master=root, data=logo)
I suspect you're not getting the error in Linux because your version of Python imports common modules automatically. Effectively, there's an invisible import Tkinter at the top of all your scripts.
I am writing a script which will get an image from a link. Then the image will be resized using the PIL module and the uploaded to Imgur using pyimgur. I dont want to save the image on disk, instead manipulate the image in memory and then upload it from memory to Imgur.
The Script:
from pyimgur import Imgur
import cStringIO
import requests
from PIL import Image
LINK = "http://pngimg.com/upload/cat_PNG106.png"
CLIENT_ID = '29619ae5d125ae6'
im = Imgur(CLIENT_ID)
def _upload_image(img, title):
uploaded_image = im.upload_image(img, title=title)
return uploaded_image.link
def _resize_image(width, height, link):
#Retrieve our source image from a URL
fp = requests.get(link)
#Load the URL data into an image
img = cStringIO.StringIO(fp.content)
im = Image.open(img)
#Resize the image
im2 = im.resize((width, height), Image.NEAREST)
#saving the image into a cStringIO object to avoid writing to disk
out_im2 = cStringIO.StringIO()
im2.save(out_im2, 'png')
return out_im2.getvalue()
When I run this script I get this error: TypeError: file() argument 1 must be encoded string without NULL bytes, not str
Anyone has a solution in mind?
It looks like the same problem as this, and the solution is to use StringIO.
A common tip for searching such issues is to search using the generic part of the error message/string.
I open page with python, gtk, and webkit. Now - how to save image from that page without downloading it again from the internet?
Here is a python program that will save a rendered web page to an image: http://pastie.org/4572412
This should be the section of primary interest to you:
size = self.browser.mainFrame().contentsSize()
if width > 0:
size.setWidth(width)
self.browser.setViewportSize(size)
# Render the virtual browsers viewport to an image.
image = QImage(self.browser.viewportSize(), QImage.Format_ARGB32)
paint = QPainter(image) #Have the painters target be our image object
self.browser.mainFrame().render(paint) #Render browser window to painter
paint.end()
image = image.scaledToWidth(width) #ensure the image is your desired width
extension = os.path.splitext(filename)[1][1:].upper() #save the file as your desired image extension
if extension not in self.image_extensions:
raise ValueError("'filename' must be a valid extension: {0}".format(self.image_extensions))
image.save(filename, extension)
Hope this helps!