How do I get specific pixels of the tkinter canvas? - python

I have an issue with the Tkinter Canvas, saving it to an image, but more importantly, getting a specific pixel of the Tkinter Canvas. All I need is for that specific X, Y coordinate, I want its color value. By 'color value', any value I can use to draw a pixel with the python imaging library would work.
Here's what I tried to do to make it work:
I first tried to use python imaging library's image grabbing class to get the Canvas Image, but that didn't work as expected.
I then tried to convert the Tkinter Canvas to an image by with the "eps" file, but that didn't work, and GhostScript didn't work either.
Next, I searched to see if there was any way to get the pixel at a certain coordinate on a Tkinter canvas to no avail. That's where I posted this.
Next, here's the code I tried for step 2:
screen = w
#staticmethod
def image():
w.postscript(file=".canvas_script.eps")
img = Image.open(".canvas_script.eps")
return img
# GhostScript Error
Expected Result: My expected result is to get the color of any certain point, or at least to get a color of the point that I can convert to another color tuple or value. Then, to put draw that on a python imaging library image.
Actual Result: I found no method on the internet when I researched that solved my question, and no method in the documentation.
If anyone can help me get the color from a specific coordinate of the Tkinter Canvas, say (0, 0), please do. Thanks!

How do I get specific pixels of the tkinter canvas?
You can't. The canvas isn't a pixel oriented widget. The best you can do is use some other library to create a screenshot of the canvas, and then use the image to give you the values that you want.

Related

Magnify image based on rectangle points selected on image

I am working on a code in python and I came across a figure in a report that I would like to replicate.
Basically I would like to create a 'bounding' box onto the original image, and then subsequently crop and display the part of the image that has the bounding box on it. (basically to 'magnify' that section)
I've been googling but I can't seem to find the correct function to use so that I can achieve this. Currently, opencv is used to read my image, but if there is a function in matplotlib that does this, then you can suggest that too.
Thank you for your help!

How to get and set pixel's color value using graphics.py in python3

I'm implementing Boundary Fill Algorithm for polygons in python.How to get and set the color of a pixel?
I'm using graphics.py file.
Zelle graphics provides operators to manipulate pixels of images as documented in the code:
The library also provides a very simple class for pixel-based image
manipulation, Pixmap. A pixmap can be loaded from a file and displayed
using an Image object. Both getPixel and setPixel methods are provided
for manipulating the image.
But not higher level objects like polygons.
This answer to Get color of coordinate of figure drawn with Python Zelle graphics shows how to get the fill color of an object like a polygon located at a given (x, y) coordinate using the tkinter underpinnings of Zelle graphics. I doubt this technique can be used to set the color of a pixel of a polygon, however.

Fastest way to draw a pixel on tkinter

Note: You really only need to read the checklist and understand that I want to do this in Tkinter, the rest of the information is for clarification
The complete code is here: https://gist.github.com/SnugBug/1cc5ea67d11487d69aae8549107372ef
I need to be able to manipulate pixels. The goal is to be able to:
Control which pixels are drawn first
Change the color and position of each pixel
Update everything as a whole, so that if a pixel changes the change shows up
Clear everything as a whole
The question is, what's the fastest way to check off this list in tkinter? I tried creating an image with PIL, then loading it into tkinter, but I cannot update the image or clear it. The other thing I tried is using tkinter's PhotoImage class, as shown below:
#The function definitions are in the GIST.
#This snippet should be enough information to understand the problem, however.
for i in range(0,3600):
rot = [0,i,0]
Tx,Ty,Tz,Zm = [0,0,200,200]
x,y,z = [10,10,10]
for m,n in itertools.product(range(-50,50,2),range(-50,50,2)):
x,y,z = rotate([m,n,0],rot)
img.put("#ffffff", (int(WIDTH/2 + ((x+Tx)*Zm/(z+Tz))), int(HEIGHT/2 - ((y+Ty)*Zm/(z+Tz)))))
canvas.update()
img.blank()
#the confusing math in the `img.put` call is just 3D math
This way is extremely slow. The next way I tried is even slower. It's drawing a line like this:
canvas.create_line(x,y,x+1,y+1, ...)
Which creates a line of length 1, showing a single pixel. This is excruciatingly slow.
If the separate image method is the fastest, could you include a working snippet in your answer? I cannot figure out the separate image method. I have PIL installed, that's what I was using to attempt it. I lost the python file so I cannot include the code I used to attempt the separate image method.
What I mean by the separate image method: create an image using PIL, drawing on it using PIL, then making that show up on a tkinter screen. This doesn't meet everything on the checklist, however (from what I understand).
If the separate image method is not the fastest, please tell me a way I can check off everything in the checklist some other way. I have a few questions I looked at for help and some sites. They're below
Why is Photoimage put slow?
Any of these answers don't work for me because it only creates squares. I need to be able to make any shape.
python tkinter: how to work with pixels?
This answer doesn't work because it's too slow.
How to load .bmp file into BitmapImage class Tkinter python This could be helpful
http://zetcode.com/gui/tkinter/drawing/ None of these methods work because I cannot manipulate the order each pixel is drawn, and the color of each individual pixel. If you are familiar with 3D terminology, I need this for a Z-Buffer
If there are any confusions or you need something clarified, please tell me below in the comment section. I am open minded, so if you have a deep understanding of my question and have another idea on how to solve it, I would love to hear it.
If you are using Windows, then the fastest way to put an image on a frame is by ImageWin. The tkinter process of first transforming from PIL image to a tkphotoimage is very slow.
from PIL import Image, ImageWin
from win32gui import GetDC
from tkinter import Tk
root = Tk()
im = Image.open(<file path>)
ImageWin.Dib(im).draw(
GetDC(ImageWin.HWND(root.winfo_id())),
(0,0,100,100)
)

python tkinter canvas 'transparent'

I think transparent is the right word I'm looking for. Hopefully my description will explain it properly no matter what.
I have a graph of time based data going back decades. Pretty much simply setup to show one day per x-pixel, unless zoomed in closer. I would like to have a box, maybe along the lines of 5x100, appear on top of the graph so when I move the mouse over the graph the box will move and keep pace with the mouse. Anotherwords showing what was happening in the 5 furthest days 'x number of days prior'. Anotherwords when computing an average going forward what are the next values to be falling off as new data arrives. Naturally I want the underlying graphed data to be displayed with the transparent box on top of it outlining the days in question. This may get crazy enough to be a much wider box with two areas that are colored light grey or something like that to show the areas in question but the colored areas are separated by numerous days(could be multiple transparent windows that are tracked together as well. Is this feasible with tkinter? From the research I've been doing it's questionable if using
root.attributes('alpha', .30)
would work or not. It doesn't sound like I could do something like as it would end up making the graph transparent to whatever is underneath it.
self.Graph.create_line()
self.Box.attributes('alpha', .30)
If I understand correctly I have to use
attributes
right at the root level versus the individual 'window' level so the above (severely chopped down) code wouldn't work...or would it. I haven't had a chance to try anything out yet to see what happens...that will be later on this evening. Kinda hoping to save myself a little time by asking now and you never know who else may need the help sometime.
If I understand what you're trying to do, it's going to be pretty hard.
Setting window attributes works just fine to make a window transparent. You've got a minor problem in the code—attributes start with a hyphen—but otherwise you've got it right:
self.Box.attributes("-alpha", .30)
However, it sounds like you want that Box to be an embedded part of the graph window, not its own top-level window that can be dragged around by the user, etc. Unfortunately, Tkinter does not have any notion of child windows, and it doesn't expose nearly enough of the native stuff you'd need to fake them by creating an immobile window and manually moving it to track the movements of another window. So, you don't have a window, which means you don't have window transparency.
The obvious thing for Box to be is some kind of widget, like a Frame or Canvas. But widgets don't have transparency.
Box could instead be just a collection of elements drawn onto the same Canvas as the Graph. That seems promising… but none of the Canvas methods handle alpha transparency. (Some of them do handle all-or-nothing transparency, but that doesn't help.)
One thing that does handle transparency is PhotoImage. So, if you draw Box off-screen, get the resulting contents as a PhotoImage, add the alpha (e.g., via PIL), then create_image the result… close, but no cigar. Depending on the settings of the underlying Tk library, Tkinter may just draw the pixmap with 1-bit transparency or ignore transparency completely. (Experiment with loading alpha-transparent PNG files in PIL and drawing them on a Canvas.) So, unless you want an app that looks right on some systems, doesn't draw the Box at all on others, and draws it opaque on others, this is a dead end.
So, what's left? Only manual compositing: Draw the Graph and the Box on separate off-screen windows, get the pixmaps, use PIL to compose them, and create_image the result.
At which point you're probably better off just using something like PIL's ImageDraw or a more powerful library to construct the pixmap in the first place. Or, of course, using a more powerful GUI library than Tk, like Qt or wx.
Maybe this can give you some ideas to play with:
from tkinter import *
root = Tk()
c = Canvas(root, width=640, height=480, bd=0, highlightthickness=0)
c.create_line(0,240,640,240, fill='blue')
c.pack()
#pil image with transparency
try:
from PIL import Image, ImageTk
except ImportError:
pass
else:
pim = Image.new('RGBA', (5,100), (0,255,0,64))
photo = ImageTk.PhotoImage(pim)
c.create_image(200,200, image=photo, anchor='nw')
#blank standard photoimage with red vertical borders
im = PhotoImage(width=7, height=480)
dat = ('red',)*480
im.put(dat, to=(0,0))
im.put(dat, to=(6,0))
box = c.create_image(0, 0, image=im, anchor='nw')
def on_motion(event):
left,top = c.coords(box)
dx = event.x - (left+7)
c.move(box, dx, 0)
c.bind('<Motion>', on_motion)
root.mainloop()

Problem with saving image

I have a problem with saving an image. I have following part of code:
self.canvas.postscript(file = filename, colormode = "color")
It works good, but when I set background color in canvas constructor (f.e. bg='red'),
finally image doesn't have this background color. It is still white.
Could anybody help me ?
Sounds like you're using Tkinter: is that right?
I believe the problem is that the bg argument is a general property shared by all widgets. It's really a part of how the widget is drawn on the screen and not a part of the image you're constructing in your canvas. I think the easiest thing for you to do is to draw a red box in your canvas for your background - that will then be included as part of the image saved in your postscript file.

Categories

Resources