How to control the size of a picture using tkinter? - image

I want to control the size of the picture in m_image (say, I want it to be 420x380).
How do I do that?
import tkinter as tk
m_gui = tk.Tk()
m_image = tk.PhotoImage(file = 'pic.gif')
m_canvas = tk.Canvas(m_gui)
m_canvas.create_image(0, 0, image = m_image)
m_canvas.pack()
m_gui.mainloop()
It would be great if you could also give an explanation about the first two parameters of the create_image func.
Thank you

tk is a gui framework, not an image manipulation program. Two solutions:
Use an external image manipulation program to create a .bmp, .gif, or (if using tcl/tk 8.6) .png file with the size you want.
Install pillow (pip install pillow worked for me), use it to do the needed image manipulation, and use its ImageTk module to "create and modify Tkinter BitmapImage and PhotoImage objects from PIL images".

Related

Different images in Image.show() and Image.save() in PIL

I generate a PIL image from a NumPy array. The image showed by show function differs from what is saved by the save function directly called after show. Why might that be the case? How can I solve this issue? I use TIFF file format. Viewing both images in Windows Photos App.
from PIL import Image
import numpy as np
orig_img = Image.open('img.tif'))
dent = Image.open('mask.tif')
img_np = np.asarray(orig_img)
dent_np = np.asarray(dent)
dented = img_np*0.5 + dent_np*0.5
im = Image.fromarray(dented)
im.show('dented')
im.save("dented_2.tif", "TIFF")
Edit: I figured out that the save function saves correctly if the values for pixel in the NumPy array called 'dented' are normalized to 0,1 range. However then show function shows the image completely black.
I suspect the problem is related to the dtype of your variable dented. Try:
print(img_np.dtype, dented.dtype)
As a possible solution, you could use:
im = Image.fromarray(dented.astype(np.uint8))
You don't actually need to go to Numpy to do the maths and then convert back if you want the mean of two images, because you can do that with PIL.
from PIL import ImageChops
mean = ImageChops.add(imA, imB, scale=2.0)

Making interactive plot with python: images with url link

I would like to plot some images I webscraped from a website, and I want to make a interactive plot in Jupyter notebook/Colab where the interactivity is being able to click on the images, which will get you to the url where I got the image.
I get the images and have them as follows:
im = Image.open(requests.get(df_info['Img'][i], stream=True).raw)
Then I found some code using ImageTk that looks like the following. But the problem is when I set the command option, im feeding a function open that requires an argument (the url)
from PIL import ImageTk
import webbrowser
root = Tk()
canvas = Canvas(root, width=600, height=600)
canvas.pack()
def open(url):
webbrowser.open(url)
img_file = Image.open(requests.get(df_info['Img'][0], stream=True))
img_file = img_file.resize((150, 150))
img = ImageTk.PhotoImage(img_file)
b1 = Button(canvas,image=img,command=open).pack()
root.mainloop()
I am not sure I have to use this ImageTk framework, either. It would be great if there was a way to just use matplotlib functions as well. But the key is to have that clickability on the pictures in the Jupyter notebook.
Could someone please help me?

How does python support the display of images on canvas or label widgets?

The question is not if Python supports the display of images, but rather how it supports the display of images. By choice I am using Python 2.7, and this has Tkinter and Image libraries/modules installed. I don't have the pygame module, which seems to readily support the use of images on the graphical user interface.
To open the file or filename on the system, I am using tkFileDialog and this module works as intended. Then, I can combine the output of the tkFileDialog command with the Image module to create an image object (using the open method). Having done this, I can show my graphic using Image's show method, see below:
import Image
import Tkinter
import tkFileDialog as File
root = Tkinter.Tk()
root.title('Image Test')
root.file = File.askopenfile()
root.image = Image.open(root.file)
root.label = Tkinter.Label(image=root.image)
root.label.grid()
Python uses Image Magick to present a zoomed image, if after line 7, I use
root.image.show()
However, when I attempt to load the image to a Tkinter window using the Label (as illustrated in my code) and PhotoImage widgets (which are described to support image display) python throws a TclError and Runtime error, respectively. The messages are: it is "too early to create image" when using PhotoImage, and "image doesn't exist" when using Label (line 8 in my code). Can anyone provide assistance without suggesting that I add modules to my python (version: 2.7) install?
I am looking to work with bitmaps and jpeg/jpg/jpe images. Preferably, I would like to load the image onto the Canvas object using the create_image method. That is, if and only if I can load the image in to a PhotoImage object (no code included). I will settle for a Label with the image, that will eventually be loaded onto a Canvas.
Useful stackoverflow questions, for reference:
•How do I insert a JPEG image into a python Tkinter window?
•How to add an image in Tkinter?
•Cannot construct tkinter.PhotoImage from PIL Image
To everyone else following, it seems as though one can do just about any image file extension by opening their image using the Image module and programmatically saving that to a gif file type. Then, use the PhotoImage module to load the result to a Canvas widget.
import Tkinter, Image, tkFileDialog as File
filename = File.askopenfilename() #choose jpg
image = Image.open(filename)
image.save(fp='somename', format='GIF')
temporarygif = File.askopenfilename() #choose gift
photo = Tkinter.PhotoImage(file=temporarygif)
root = Tkinter.Tk()
root.title('Simple Image Display')
root.canvas = Tkinter. Canvas(root, options)
root.canvas.create_image(0,0,image=photo)
root.canvas.pack()
root.mainloop()
Great head turner.
Problems: the saved gif experiences some loss of color quality. It looks like a 256 color image, and not a full color image.

How to use XBM image data in Python without referencing external file

Apologies if this is a duplicate; I've been searching with every combination of keywords I can think of but I can't find an article that addresses this.
I'm building a Python Tkinter application (Python 2.7.x, Win 7) which includes buttons with image data (drawn from XBM files). For example,
self._ResetIcon = tk.BitmapImage(file='ResetIcon.xbm')
self._Reset = tk.Button(self,
width=20, height=20,
image=self._ResetIcon,
command=self._reset)
Now I'm 99.9% sure there's a way to include the XBM image data as a declaration of some kind directly in the Python module itself, rather than pulling it from the external file. But I can't find anything online that describes how to do it.
Is there a way to do this?
Did some more digging via Google and found it.
http://effbot.org/tkinterbook/bitmapimage.htm
An X11 bitmap image consists of a C fragment that defines a width, a
height, and a data array containing the bitmap. To embed a bitmap in a
Python program, you can put it inside a triple-quoted string:
BITMAP = """
#define im_width 32
#define im_height 32
static char im_bits[] = {
0xaf,0x6d,0xeb,0xd6,0x55,0xdb,0xb6,0x2f,
0xaf,0xaa,0x6a,0x6d,0x55,0x7b,0xd7,0x1b,
0xad,0xd6,0xb5,0xae,0xad,0x55,0x6f,0x05,
0xad,0xba,0xab,0xd6,0xaa,0xd5,0x5f,0x93,
0xad,0x76,0x7d,0x67,0x5a,0xd5,0xd7,0xa3,
0xad,0xbd,0xfe,0xea,0x5a,0xab,0x69,0xb3,
0xad,0x55,0xde,0xd8,0x2e,0x2b,0xb5,0x6a,
0x69,0x4b,0x3f,0xb4,0x9e,0x92,0xb5,0xed,
0xd5,0xca,0x9c,0xb4,0x5a,0xa1,0x2a,0x6d,
0xad,0x6c,0x5f,0xda,0x2c,0x91,0xbb,0xf6,
0xad,0xaa,0x96,0xaa,0x5a,0xca,0x9d,0xfe,
0x2c,0xa5,0x2a,0xd3,0x9a,0x8a,0x4f,0xfd,
0x2c,0x25,0x4a,0x6b,0x4d,0x45,0x9f,0xba,
0x1a,0xaa,0x7a,0xb5,0xaa,0x44,0x6b,0x5b,
0x1a,0x55,0xfd,0x5e,0x4e,0xa2,0x6b,0x59,
0x9a,0xa4,0xde,0x4a,0x4a,0xd2,0xf5,0xaa
};
"""
To create X11 bitmaps, you can use the X11 bitmap editor provided with
most Unix systems, or draw your image in some other drawing program
and convert it to a bitmap using e.g. the Python Imaging Library.
The BitmapImage class can read X11 bitmaps from strings or text files:
bitmap = BitmapImage(data=BITMAP)
bitmap = BitmapImage(file="bitmap.xbm")

Python 3.4: Where is the image library?

I am trying to display images with only builtin functions, and there are plenty of Tkinter examples online. However, none of the libraries work:
import Image # none of these exist.
import tkinter.Image
import _tkinter.Image
etc
However, tkinter does exist, a hellow-world with buttons worked fine.
I am on a MacBook pro 10.6.8 and using PyCharm.
Edit: The best way so far (a little slow but tolerable):
Get the pixel array as a 2D list (you can use a third-party .py to load your image).
Now you make a data array from the pixels like this (this is the weirdest format I have seen, why not a simple 2D array?). This may be sideways, so you may get an error for non-square images. I will have to check.
Imports:
from tkinter import *
import tkinter
data = list() # the image is x pixels by y pixels.
y = len(pixels)
x = len(pixels[0])
for i in range(y):
col_str.append('{')
for j in range(x):
data.append(pixels[i][j]+" ")
data.append("} ")
data = "".join(data)
Now you can create an image and use put:
# PhotoImage is builtin (tkinter).
# It does NOT need PIL, Pillow, or any other externals.
im = PhotoImage(width=x, height=y)
im.put(col_str)
Finally, attach it to the canvas:
canvas = tkinter.Canvas(width=x, height=y)
canvas.create_image(x/2, y/2, image=GLOBAL_IMAGE) # x/2 and y/2 are the center.
tK.mainloop() # enter the main loop and it will be drawn.
Image must be global or else it may not show up because the garbage collector gets greedy.
PIL hasn't been updated since 2009, with Python 3 support being terminally stuck at "later."
Instead, try pillow, which has forked PIL and provides Python 3 support.

Resources