Converting a PIL Image to an autopy bitmap?(and back) - python

Recently I started working with PIL together with AutoPy to automate some tasks. One of the core functions AutoPy is needed for is its suprisingly fast (though buggy, but there are fixes for that - the build and installation from source can be annoying, and if you get the error Unable to find vcvarsall.bat, just google it).
But just now I ran into a problem I can't find a fix for. PIL and AutoPy use fundamentally diffrent formats for their screenshots. For AutoPy I couldnt get it to work with multiple screens, but for PIL i easily could. Now I need to convert these Images into a format AutoPy accepts - and that in a reasonable amount of time.
A theoratically possible solution:
def test():
Img = Image.open("example.png")
Img.save("test.png")
Img2.open("test.png")
Going by my testing, this takes roughly around 0.5 seconds to complete. Far more than the 0.1 seconds I'd need.

I dug around the documentation to find a bitmap image conversion tool.
pil_im = Image.open("test.png")
pil_im = pil_im.convert(mode ="1")
#this is to prevent a value error in the tobitmap function
pil_im = pil_im.tobitmap(im)
I had a similar problem earlier where a pyautogui screenshot was not considered the same as a recently opened png. pil_im.copy() created an image to compare with without all the formatting.

Related

Optimize the process of importing multiple images from the internet, tkinter

I'm writing a recipe program and as part of it, I want to make a series of buttons with different images (for each recipe). I am using the Edamam recipe search api (here) which gives me urls to all the images I need.
The way I my code operates is as follows:
for each recipe:
data = urlopen(image_url)
image = ImageTk.PhotoImage(data=data.read()) # Convert to a tkinter PhotoImage object
b = Button(root, command = lambda i=recipe_url:callback(i), image = image) # callback() opens the webpage for a given url
b.image = image # To prevent garbage collection from removing the image
b.pack()
Obviously this is a simplified version and I've removed or renamed things for it to make sense without looking at the entire program. However, it addresses the performance issue which is the process of downloading and converting images.
The relevant information I can think of is:
20 images need to be converted each time
It takes around 18 seconds for the entire process to run
I am using the smallest sized images available (sizes of large, medium, small, and thumbnail are available)
The relevant modules I'm using are PIL, urllib, and tkinter
My question is how can I increase the speed of this component without compromising on functionality.
Let me know if there's any other information I need to add and thank you in advance for the help.
Thanks to #Alexander for the tip off on multiprocessing, I tried implementing it but I couldn't really wrap my head around it, so I used multithreading instead and now it is far more efficient. Each thread contains the code for one button and then the loop simply defines and then starts the threads:
x = threading.Thread(target=image_conversion, args=(item,))
x.start()

Use python to grab the screen(screenshot) But image is blurry, unsharp

Environment:
win10 PC notbook
python 3.9
PyQt5==5.15.4 pywin32==304 opencv-python==4.5.5.64 Pillow==9.1.0
Question:
I am trying to grab my whole screen by python. The function is easy, but I get a strange question.
The screenshot image is always blurry and unsharp.
screenshot by windows10 self: windows10 self (PNG)
screenshot by my codes: my codes (PNG)
My Codes as follows:
import cv2
import os
from PIL import ImageGrab
import numpy as np
if os.path.exists('xx.jpg'):
os.remove('xx.jpg')
captureImage = ImageGrab.grab()
width,height = captureImage.size
img = cv2.cvtColor(np.asarray(captureImage), cv2.COLOR_RGB2BGR)
cv2.imwrite('./xx.jpg',img)
cv2.waitKey(0)
I have try alternative method to achieve screenshot function, just like pyqt5/mss/pywin32/pyautogui, but every method leads to the same question.
And I google lots of articles, I found that my screen has scaled to 125%(as recommended), as follow:
PNG:
So I revise it to 100%, the screenshot is sharp. But 125% is normal and comfortable vision.
Then I doubt if it's DPI. But I try these codes, it does not work.
from ctypes import windll
user32 = windll.user32
user32.SetProcessDPIAware()
I am so crazy and curious that how those screenshot software resolve it. After all, we can not ensure every user has the 100% scale and has normal dpi.
I will be grateful if u could give me solutions or advices.
Solution:
Thanks to Christoph Rackwitz.
I had grab a PNG screen and update it and the two PNG image still same. But it's really different in my PC before upload.
I test a lot and I found that I open my codes screenshot by iQIYI Player. But I open windows10 self screenshot by windows Player.
It's the Reason!!!My codes is right and everything is right except iQIYI Player Software. Maybe it's the software bug.
Thanks again.

Python: Using Pyscreenshot image to get RGB values (Linux)

I'm on python 3.5 on a Ubuntu machine. I'm writing a script where I want to grab the screen and search for certain pixel colors in the image.
Since it's not windows, PIL.ImageGrab doesn't work and after some research I started using pyscreenshot.
The following works:
import pyscreenshot as ImageGrab
im = ImageGrab.grab(bbox(1,1,100,100))
Now my problem is that the type of im is PIL.PngImagePlugin.PngImageFile which doesn't have the method .getpixel like PIL.Image does.
While I could save it to a file and load it again with PIL that seems super ugly and not efficient. How do I make a PIL.Image out of this?
I thought something along the lines of
im = Image.new(ImageGrab.grab(bbox(1,1,100,100)))
but that's obviously not it ;)
(Sidenote: If there are other/easier ways than pyscreenshot to get screenshots on Ubuntu, that's fine too)

Is it possible to save in a file an animation created with Tkinter?

I wanted to use Python to create animations (video) containing text and simple moving geometric objects (lines, rectangles, circles and so on).
In the book titled "Python 2.6 Graphics Cookbook" I found examples using Tkinter library. First, it looked like what I need. I was able to create simple animation but then I realized that in the end I want to have a file containing my animation (in gif or mp4 format). However, what I have, is an application with GUI running on my computer and showing me my animation.
Is there a simple way to save the animation that I see in my GUI in a file?
There is no simple way.
The question Programmatically generate video or animated GIF in Python? has answers related strictly to creating these files with python (ie: it doesn't mention tkinter).
The question How can I convert canvas content to an image? has answers related to saving the canvas as an image
You might be able to take the best answers from those two questions and combine them into a single program.
I've accomplished this before, but not in a particularly pretty way.
Tl;dr save your canvas as an image at each step of the iteration, use external tools to convert from image to gif
This won't require any external dependencies or new packages except having imagemagick already installed on your machine
Save the image
I assume that you're using a Tkinter canvas object. If you're posting actual images to the tk widgets, it will probably be much easier to save them; the tk canvas doesn't have a built-in save function except as postcript. Postscript might actually be fine for making the animation, but otherwise you can
Concurrently draw in PIL and save the PIL image https://www.daniweb.com/software-development/python/code/216929/saving-a-tkinter-canvas-drawing-python
Take a screenshot at every step, maybe using imagegrab http://effbot.org/imagingbook/imagegrab.htm
Converting the images to to an animation
Once the images are saved, I used imagemagick to dump them into either a gif, or into a mpg. You can run the command right from python using How to run imagemagick in the background from python or something similar. It also means that the process is implictely run on a separate thread, so it won't halt your program while it happens. You can query the file to find out when the process is done.
The command
convert ../location/*.ps -quality 100 ../location/animation.gif
should do the trick.
Quirks:
There are some small details, and the process isn't perfect. Imagemagick reads files in order, so you'll need to save the files so that alphabetical and chronological line up. Beware that the name
name9.ps
Is alphabetically greater than
name10.ps
From imagemagick's point of view.
If you don't have imagemagick, you can download it easily (its a super useful command-line tool to have) on linux and mac, and cygwin comes with it on windows. If you're worried about portability... well... PIL isn't standard either
There is a way of doing that, with the "recording screen method", this was explained in other question: "how can you record your screen in a gif?".
Click the link -->LICEcap : https://github.com/lepht/licecap
They say that it's free software for Mac (OS X) and Windows
You could look at Panda3D, but it could be a little over killed for what you need.
I would say you can use Blender3d too but i'm not really sure of how it works. Someone more experimented then me could tell you more about this.

Python/pygame - turning images into video

I am using the Pygame module in python to take pictures with my webcam. The problem is that I would like to export a video file (don't care what type) to use elsewhere. Since pygame cannot export video directly, I guess that there is two ways to do it:
Somehow stitch the photos Pygame creates into a video. (my preferred method)
Use an external library.
I only need 4 frames per second, and I don't care about the picture quality.
How can I make a video with python / pygame?
I have the same problem and am searching the solution.
I found this
This seems work well though I didn't try yet.
Hope this helps.

Categories