Pracownia_programowania/venv/Lib/site-packages/pyautogui/screenshotUtil.py

218 lines
8.0 KiB
Python
Raw Permalink Normal View History

2020-02-01 19:54:00 +01:00
# Screenshot-related features of PyAutoGUI
"""
So, apparently Pillow support on Ubuntu 64-bit has several additional steps since it doesn't have JPEG/PNG support out of the box. Description here:
https://stackoverflow.com/questions/7648200/pip-install-pil-e-tickets-1-no-jpeg-png-support
http://ubuntuforums.org/showthread.php?t=1751455
"""
import datetime
import os
import subprocess
import sys
from PIL import Image
from PIL import ImageOps
RUNNING_PYTHON_2 = sys.version_info[0] == 2
scrotExists = False
maimExists = False
try:
if sys.platform not in ('java', 'darwin', 'win32'):
whichProc = subprocess.Popen(['which', 'scrot'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
scrotExists = whichProc.wait() == 0
except:
# if there is no "which" program to find scrot, then assume there is no scrot.
pass
try:
if sys.platform not in ('java', 'darwin', 'win32'):
whichProc = subprocess.Popen(['which', 'maim'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
maimExists = whichProc.wait() == 0
except:
# if there is no "which" program to find maim, then assume there is no maim.
pass
def locateAll(needleImage, haystackImage, grayscale=False, limit=None):
needleFileObj = None
haystackFileObj = None
if isinstance(needleImage, str):
# 'image' is a filename, load the Image object
needleFileObj = open(needleImage, 'rb')
needleImage = Image.open(needleFileObj)
if isinstance(haystackImage, str):
# 'image' is a filename, load the Image object
haystackFileObj = open(haystackImage, 'rb')
haystackImage = Image.open(haystackFileObj)
if grayscale:
needleImage = ImageOps.grayscale(needleImage)
haystackImage = ImageOps.grayscale(haystackImage)
needleWidth, needleHeight = needleImage.size
haystackWidth, haystackHeight = haystackImage.size
needleImageData = tuple(needleImage.getdata()) # TODO - rename to needleImageData??
haystackImageData = tuple(haystackImage.getdata())
needleImageRows = [needleImageData[y * needleWidth:(y+1) * needleWidth] for y in range(needleHeight)] # LEFT OFF - check this
needleImageFirstRow = needleImageRows[0]
assert len(needleImageFirstRow) == needleWidth
assert [len(row) for row in needleImageRows] == [needleWidth] * needleHeight
numMatchesFound = 0
for y in range(haystackHeight):
for matchx in _kmp(needleImageFirstRow, haystackImageData[y * haystackWidth:(y+1) * haystackWidth]):
foundMatch = True
for searchy in range(1, needleHeight):
haystackStart = (searchy + y) * haystackWidth + matchx
if needleImageData[searchy * needleWidth:(searchy+1) * needleWidth] != haystackImageData[haystackStart:haystackStart + needleWidth]:
foundMatch = False
break
if foundMatch:
# Match found, report the x, y, width, height of where the matching region is in haystack.
numMatchesFound += 1
yield (matchx, y, needleWidth, needleHeight)
if limit is not None and numMatchesFound >= limit:
# Limit has been reached. Close file handles.
if needleFileObj is not None:
needleFileObj.close()
if haystackFileObj is not None:
haystackFileObj.close()
# There was no limit or the limit wasn't reached, but close the file handles anyway.
if needleFileObj is not None:
needleFileObj.close()
if haystackFileObj is not None:
haystackFileObj.close()
def locate(needleImage, haystackImage, grayscale=False):
# Note: The gymnastics in this function is because we want to make sure to exhaust the iterator so that the needle and haystack files are closed in locateAll.
points = tuple(locateAll(needleImage, haystackImage, grayscale, 1))
if len(points) > 0:
return points[0]
else:
return None
def locateOnScreen(image, grayscale=False,region=None):
screenshotIm = screenshot(region=region)
retVal = locate(image, screenshotIm, grayscale)
if 'fp' in dir(screenshotIm) and screenshotIm.fp is not None:
screenshotIm.fp.close() # Screenshots on Windows won't have an fp since they came from ImageGrab, not a file.
return retVal
def locateAllOnScreen(image, grayscale=False, limit=None, region=None):
screenshotIm = screenshot(region=region)
retVal = locateAll(image, screenshotIm, grayscale, limit)
if 'fp' in dir(screenshotIm) and screenshotIm.fp is not None:
screenshotIm.fp.close() # Screenshots on Windows won't have an fp since they came from ImageGrab, not a file.
return retVal
def locateCenterOnScreen(image, grayscale=False, region=None):
return center(locateOnScreen(image, grayscale, region))
def _screenshot_win32(imageFilename=None):
im = ImageGrab.grab()
if imageFilename is not None:
im.save(imageFilename)
return im
def _screenshot_osx(imageFilename=None):
if imageFilename is None:
tmpFilename = 'screenshot%s.png' % (datetime.datetime.now().strftime('%Y-%m%d_%H-%M-%S-%f'))
else:
tmpFilename = imageFilename
subprocess.call(['screencapture', '-x', tmpFilename])
im = Image.open(tmpFilename)
if imageFilename is None:
os.unlink(tmpFilename)
return im
def _screenshot_linux(imageFilename=None, region=None):
if not scrotExists:
raise NotImplementedError('"scrot" must be installed to use screenshot functions in Linux. Run: sudo apt-get install scrot')
if imageFilename is None:
tmpFilename = '.screenshot%s.png' % (datetime.datetime.now().strftime('%Y-%m%d_%H-%M-%S-%f'))
else:
tmpFilename = imageFilename
if scrotExists:
if not region:
subprocess.call(['scrot', tmpFilename])
else:
if not maimExists:
raise NotImplementedError('"maim" must be installed to use screenshot functions with region in Linux. Run: sudo apt-get install maim')
left,top,width,height = [str(x) for x in region]
subprocess.call(['maim','-x',left,'-y',top,'-w',width,'-h',height, tmpFilename])
im = Image.open(tmpFilename)
if imageFilename is None:
os.unlink(tmpFilename)
return im
else:
raise Exception('The scrot program must be installed to take a screenshot with PyAutoGUI on Linux. Run: sudo apt-get install scrot')
def _kmp(needle, haystack): # Knuth-Morris-Pratt search algorithm implementation (to be used by screen capture)
# build table of shift amounts
shifts = [1] * (len(needle) + 1)
shift = 1
for pos in range(len(needle)):
while shift <= pos and needle[pos] != needle[pos-shift]:
shift += shifts[pos-shift]
shifts[pos+1] = shift
# do the actual search
startPos = 0
matchLen = 0
for c in haystack:
while matchLen == len(needle) or \
matchLen >= 0 and needle[matchLen] != c:
startPos += shifts[matchLen]
matchLen -= shifts[matchLen]
matchLen += 1
if matchLen == len(needle):
yield startPos
def center(coords):
return (coords[0] + int(coords[2] / 2), coords[1] + int(coords[3] / 2))
def pixelMatchesColor(x, y, expectedRGBColor, tolerance=0):
r, g, b = screenshot().getpixel((x, y))
exR, exG, exB = expectedRGBColor
return (abs(r - exR) <= tolerance) and (abs(g - exG) <= tolerance) and (abs(b - exB) <= tolerance)
def pixel(x, y):
return screenshot().getpixel((x, y))
# set the screenshot() function based on the platform running this module
if sys.platform.startswith('java'):
raise NotImplementedError('Jython is not yet supported by PyAutoGUI.')
elif sys.platform == 'darwin':
screenshot = _screenshot_osx
elif sys.platform == 'win32':
screenshot = _screenshot_win32
from PIL import ImageGrab
else:
screenshot = _screenshot_linux
grab = screenshot # for compatibility with Pillow/PIL's ImageGrab module.