I am creating a small level designer in Python (using PyGame).
The program is supposed to just let you place down an image, change between images, export to a PNG file, and export image path and coordinates to where it was place in a text document. I have gotten all of these components to work, but I am stuck with one last component, and that is reading the text document back into PyGame, and re-placing all of the images in the correct places with the correct sprites.
The way that I have it currently (Which has been rewritten and Almost works) produces an error whenever I try to read from one of my exported files.
The error of course is:
stamped_surface.blit(image, (xcrds, ycrds))
TypeError: invalid destination position for blit
Here is my code:
import pygame as pg
import threading
import time
import pygame
from random import *
from tkinter.filedialog import askopenfilename
from tkinter.filedialog import asksaveasfile
image_file = "../res/ExampleProject/TankGame/TankGameImg/tileGrass_transitionE.png"
f = open("../Saves/Backups/FailSafe.txt", "a+")
f.write("""
#################################################
# PyEngine #
# FailSafe #
# File #
# By MouseBatteries #
#################################################
""")
pg.init()
xcrds = 17
ycrds = 13
black = (0,0,0)
sw = 1280
sh = 720
screen = pg.display.set_mode((sw, sh))
pg.display.set_caption('thing')
image = pg.image.load(image_file).convert()
start_rect = image.get_rect()
image_rect = start_rect
running = True
stamped_surface = pg.Surface((sw, sh))
while running:
event = pg.event.poll()
keyinput = pg.key.get_pressed()
# Escape Program
if keyinput[pg.K_ESCAPE]:
fname = "../Saves/Design_complete.png"
pg.image.save(stamped_surface, fname)
print("File saved at {} ".format(fname))
quit()
#Save Work In Project File
if keyinput[pg.K_s]:
fname = "../Saves/LevelSave.png"
pg.image.save(stamped_surface, fname)
print("File saved at {} ".format(fname))
#Open New Selectable
if keyinput[pg.K_n]:
image_file = askopenfilename()
image = pg.image.load(image_file).convert()
print("Placable Updated!")
if keyinput[pg.K_e]:
fname = "../Saves/Export.png"
pg.image.save(stamped_surface, fname)
print("File saved at {} ".format(fname))
pg.quit()
#Recreate Terrain From File
if keyinput[pg.K_o]:
fileDest = askopenfilename()
openFile = open(fileDest, "r")
for line in openFile:
li = line.strip()
if li.startswith("Pec:"): #pec stands for "PyEngineCoords"
reimgpath = (line.rstrip())
nopecimgpath = reimgpath.replace("Pec:", "")
print(nopecimgpath)
image = pg.image.load(nopecimgpath).convert()
pg.display.update()
if li.startswith("Crdsx:"):
xposcrds = (line.rstrip())
xcrds = xposcrds.replace("Crdsx:", "")
x = int(xcrds)
print(x)
pg.display.update()
if li.startswith("Crdsy:"):
yposcrds = (line.rstrip())
ycrds = yposcrds.replace("Crdsy:", "")
y = int(ycrds)
print(y)
pg.display.update()
stamped_surface.blit(image, (xcrds, ycrds))
elif event.type == pg.QUIT:
running = False
elif event.type == pg.MOUSEMOTION:
image_rect = start_rect.move(event.pos)
elif event.type == pg.MOUSEBUTTONDOWN:
stamped_surface.blit(image, event.pos)
print("Image Placed!")
print(image_file, event.pos)
f.write("\nPec:" + image_file + "\nCrdsx:")
print(event.pos)
xpos_str = str(pg.mouse.get_pos()[0])
ypos_str = str(pg.mouse.get_pos()[1])
f.write(xpos_str)
f.write("\nCrdsy:")
f.write(ypos_str)
f.flush()
screen.fill(black)
screen.blit(stamped_surface, (0, 0))
screen.blit(image, image_rect)
pg.display.flip()
This program has a file system and certain controls to make things happen, so here they are:
ESC KEY - Auto Exports Program For Reference And Quits Program
S Key - Saves Surface as PNG file.
N Key - Prompts User to select new sprite to use
E Key - Exports Image To PNG with file prompt
O Key - Opens File With Coordinate data and image path data.
Image Of Root File System:
https://i.imgur.com/KouhmjK.png
A Few things you should know:
This program auto-saves every file position to the file that contains Coords and Image Paths.
The file system is relatively simple to work out by looking at the code, but if you need some assistance, please ask.
blits((source, dest, area), ...)) -> (Rect, ...) you are missing out the destination. Read here
And if you are making use of coordinates then use square brackets [x-co,y-co]
like this:
block.blit(image,[0,0])
Related
I want to know, how can I specify RGB values for a program that triggers a hotkey(2) when detecting a change in pixel color of a small area on screen being captured? I want to specify the RGB value so that when the software detects a new specific pixel color, it triggers the hotkey(2).
I have a script (main part of it below) already written that I found online, but I am working on altering it so that it only triggers hotkey 2 when detecting a new specific pixel color being present. I pasted "136, 36, 150" in between the parenthesis found at the end of "rgb_pixel" in line 6.
I used PyInstaller to compile my .py script into an .exe and it loaded up fine. However, when I press another hotkey(1) that toggles the pixel color change detection and hotkey(2) trigger, it closed, giving me this error:
Traceback (most recent call last):
File "main.py", line 126, in <module>
TypeError: rgb_pixel() takes 0 positional arguments but 3 were given
[11192] Failed to execute script 'main' due to unhandled exception!
import colorama
from termcolor import cprint, colored
from pyfiglet import Figlet
from pynput.mouse import Controller, Button
from pynput import mouse
import numpy as np
import d3dshot
import time
import keyboard
import win32gui
import win32api
import os
import ctypes
kernel32 = ctypes.windll.kernel32
kernel32.SetConsoleMode(kernel32.GetStdHandle(-10), 128)
colorama.init()
KEYBIND = "alt"
BOX_LENGTH = 4
SCREEN_X = win32api.GetSystemMetrics(0)
SCREEN_Y = win32api.GetSystemMetrics(1)
X1 = int(SCREEN_X/2 - BOX_LENGTH/2)
Y1 = int(SCREEN_Y/2 - BOX_LENGTH/2)
X2 = int(X1 + BOX_LENGTH)
Y2 = int(Y1 + BOX_LENGTH)
REGION = (X1, Y1, X2, Y2)
cprint("Setting up...")
cprint(" - [¤] Windows", "green")
cprint(f" - [¤] {SCREEN_X}x{SCREEN_Y}", "green")
time.sleep(0.5)
win32gui.GetDoubleClickTime = lambda: 0
mouse = Controller()
d = d3dshot.create(capture_output="numpy")
def rgb_pixel():
return np.average(d.screenshot(region=REGION))
def time_elapsed(start_time):
return str(int((time.time() - start_time)*1000)) + "ms"
f = Figlet(font="ogre")
def clear():
os.system("cls")
def titlescreen():
clear()
print(CACHED_TITLESCREEN)
try:
titlescreen()
if input("Set custom keybind? (yes/no): ")[:1] in "yY":
titlescreen()
print(f"Current keybind: [{colored(KEYBIND, 'green')}]")
print("\nPress [ESC] to continue")
new_key = KEYBIND
while True:
new_key = keyboard.read_key()
if new_key == "esc":
break
elif new_key != KEYBIND:
KEYBIND = new_key
titlescreen()
print(f"Current keybind: [{colored(KEYBIND, 'green')}]")
print("\nPress [ESC] to continue")
titlescreen()
print(f"Current keybind: [{colored(KEYBIND, 'green')}]")
cprint("\nRunning.", "green")
current_pixel = rgb_pixel()
while True:
if keyboard.is_pressed(KEYBIND):
timeS = time.time()
new_pixel = rgb_pixel()
if abs(current_pixel - new_pixel) > 5:
mouse.click(Button.left)
print("[¤] Clicked within " + time_elapsed(timeS))
current_pixel = new_pixel
else:
current_pixel = rgb_pixel()
time.sleep(0.05)
except KeyboardInterrupt:
pass
cprint("\n~ Program exited ;-;", "grey", "on_red")
time.sleep(1)
What this does is that when it detects a change in the pixel color being captured in a specific window, it triggers hotkey(2). This script triggers hotkey(2) when it detects a change in any pixel color. How can I alter it to where it only triggers hotkey(2) when detecting a specific RGB value? For context, I want it to trigger hotkey(2) when it detects (136, 36, 150), and multiple other RGB values similar to it.
import sys
import pygame
import random
#command line
image = sys.argv[1]
#loading the image and importing
inputImage = pygame.image.load(image)
#getting the image's height and width
(width,height) = inputImage.get_size()
#creating the bigger windom of the image by multiplying original size by 6
window = pygame.display.set_mode((width*6,height*6))
for x in range(height):
for y in range(width):
#rgb coordinates in the x and y image
(r,g,b,_) = inputImage.get_at((x,y))
#Calculate required number of circles
n1 = int(r/5)
n2 = int(g/5)
n3 = int(b/5)
#drawing random red circles on the image
while(n1 > 0):
pygame.draw.circle(window,(255,0,0),(random.randint((x*5)-15,(x*5)),random.randint((y*5)-15,(y*5))),1)
n1 = n1-1
#drawing random green circles on the image
while(n2 > 0):
pygame.draw.circle(window,(0,255,0),(random.randint((x*5)-15,(x*5)),random.randint((y*5)-15,(y*5))),1)
n2= n2-1
#drawing random blue circles on the image
while(n3 > 0):
pygame.draw.circle(window,(0,0,255),(random.randint((x*5)-15,(x*5)),random.randint((y*5)-15,(y*5))),1)
n3 = n3-1
#updating the image
pygame.display.update()
pygame.time.delay(5000)
My code sends me an error saying what the title is, so when I try to change the sys.argv line into
image = sys.argv[0]
It gives me a different error saying: pygame.error: Unsupported image format and I am not sure what that means? Am I missing something important?
Also, if you guys can help me as to how to show the pygame window after fixing the code will much appreciated :)
This method does not catch any user errors (which is what you're experiencing).
#command line
image = sys.argv[1]
You need to check a few things here:
Does the sys.argv list actually have a second element (at index [1]).
Test the filename specified actually exists.
Use a try, except block to catch any errors loading the image.
import os.path
# See if we can load the user's image
inputImage = None
if ( len( sys.argv ) >= 1 ):
image_filename = sys.argv[1]
if ( not os.path.exists( image_filename ) ):
sys.stderr.write( "Filename [" + image_filename + "] does not exist\n" )
else:
try:
inputImage = pygame.image.load( image_filename )
except:
sys.stderr.write( "Failed to load [" + image_filename + "] is it an image?\n" )
inputImage = None
else:
sys.stderr.write( "No Image Filename argument specified\n" )
### inputImage is either a valid image, or None
I am trying to display a popup window that will show the results from an API using PySimple GUI call after the user has selected an item, but nothing is showing when the button is being clicked.
import PySimpleGUI as sg
# import PySimpleGUIQt as sg
import os.path
import PIL.Image
import io
#import imutils
import requests
import base64
import json
import base64
from detect_face_video import main
"""
"""
plate='f'
def convert_to_bytes(file_or_bytes, resize=None):
'''
Will convert into bytes and optionally resize an image that is a file or a base64 bytes object.
Turns into PNG format in the process so that can be displayed by tkinter
:param file_or_bytes: either a string filename or a bytes base64 image object
:type file_or_bytes: (Union[str, bytes])
:param resize: optional new size
:type resize: (Tuple[int, int] or None)
:return: (bytes) a byte-string object
:rtype: (bytes)
'''
if isinstance(file_or_bytes, str):
img = PIL.Image.open(file_or_bytes)
else:
try:
img = PIL.Image.open(io.BytesIO(base64.b64decode(file_or_bytes)))
except Exception as e:
dataBytesIO = io.BytesIO(file_or_bytes)
img = PIL.Image.open(dataBytesIO)
cur_width, cur_height = img.size
if resize:
new_width, new_height = resize
scale = min(new_height/cur_height, new_width/cur_width)
img = img.resize((int(cur_width*scale), int(cur_height*scale)), PIL.Image.ANTIALIAS)
with io.BytesIO() as bio:
img.save(bio, format="PNG")
del img
return bio.getvalue()
def update_plate(filename):
SECRET_KEY = 'sk_ed3d203bf4c9a7c2910ec0c0'
with open(filename, 'rb') as image_file:
img_base64 = base64.b64encode(image_file.read())
url = 'https://api.openalpr.com/v3/recognize_bytes?recognize_vehicle=1&country=us&secret_key=%s' % (SECRET_KEY)
r = requests.post(url, data = img_base64)
try:
global plate
plate=r.json()['results'][0]['plate'],
global Brand
Brand= r.json()['results'][0]['vehicle']['make_model'][0]['name'],
global Color
Color= r.json()['results'][0]['vehicle']['color'][0]['name'],
print(plate)
except:
print ('error')
# --------------------------------- Define Layout ---------------------------------
# First the window layout...2 columns
sg.theme('Dark Blue 3')
left_col = [[sg.Text('Folder'), sg.In(size=(25,1), enable_events=True ,key='-FOLDER-'), sg.FolderBrowse()],
[sg.Listbox(values=[], enable_events=True, size=(40,20),key='-FILE LIST-')],
[sg.Text('Resize to'), sg.In(key='-W-', size=(5,1)), sg.In(key='-H-', size=(5,1))],
[sg.Button("Resize", button_color=("white", "blue"), size=(6, 1))]]
# For now will only show the name of the file that was chosen
images_col = [[sg.Text('You choose from the list:')],
[sg.Text(size=(40,1), key='-TOUT-')],
[sg.Image(key='-IMAGE-')]]
# ----- Full layout -----
layout = [[sg.Column(left_col, element_justification='c'), sg.VSeperator(),sg.Column(images_col, element_justification='c')]]
# --------------------------------- Create Window ---------------------------------
window = sg.Window('Multiple Format Image Viewer', layout,resizable=True)
# ----- Run the Event Loop -----
# --------------------------------- Event Loop ---------------------------------
while True:
event, values = window.read()
if event in (sg.WIN_CLOSED, 'Exit'):
break
if event == sg.WIN_CLOSED or event == 'Exit':
break
if event == '-FOLDER-': # Folder name was filled in, make a list of files in the folder
folder = values['-FOLDER-']
try:
file_list = os.listdir(folder) # get list of files in folder
except:
file_list = []
fnames = [f for f in file_list if os.path.isfile(
os.path.join(folder, f)) and f.lower().endswith((".png", ".jpg", "jpeg", ".tiff", ".bmp"))]
window['-FILE LIST-'].update(fnames)
if event == 'Resize':
window['-IMAGE-'].update(data=convert_to_bytes(filename, resize=new_size))
elif event == '-FILE LIST-': # A file was chosen from the listbox
try:
filename = os.path.join(values['-FOLDER-'], values['-FILE LIST-'][0])
window['-TOUT-'].update(filename)
if values['-W-'] and values['-H-']:
new_size = int(values['-W-']), int(values['-H-'])
else:
new_size = None
window['-IMAGE-'].update(data=convert_to_bytes(filename, resize=new_size))
main(filename)
update_plate(filename)
print(plate)
except Exception as E:
print(f'** Error {E} **')
pass # something weird happened making the full filename
# --------------------------------- Close & Exit ---------------------------------
window.close()
Setting keep on top in the Popup call created the window on top for me. Just add
sg.Popup("license plate" , plate , keep_on_top=True)
However, if you click on the window behind, because it also has keep on top set, it will cover your popup.
I have a program that is supposed to take screenshots...
#imports pyqt
from PyQt4.QtGui import QPixmap, QApplication
#declares variables
date = datetime.datetime.now()
counter = 0
#sets directory to be used to save screenshots
directorydate = str(date.year) + str(date.month) + str(date.day) + str(date.hour) +str(date.minute) + str(date.second)
directory = os.path.abspath('Photos%s' % directorydate)
#some weird PyQt thing I don't understand
app = QApplication(sys.argv)
#game loop
while True
counter += 1
#declarations
picdate = str(date.year) + str(date.month) + str(date.day) + str(date.hour) +str(date.minute) + str(date.second) + str(counter) + '.png'
pic = QPixmap.grabWindow(QApplication.desktop().winId())
#saves screenshots to a custom directory
pic.save('Photos%s/' % directorydate + picdate)
#adds screenshots to list and deletes them once 150 have been collected
if counter == 1:
pics = [picdate]
picfirst = pics[0]
if not os.path.exists(directory):
os.makedirs(directory)
else:
pics.append(picdate)
if counter == 150:
os.remove(picfirst)
pics.remove(picfirst)
counter = 0
...then animates them to the pygame window
background = pygame.image.load('Photos%s/' % directorydate + picdate)
displaysurf.blit(background)
#pygame event handling
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
pygame.display.update()
When I try to run it, the shell gives me "error: Couldn't open Photos_____/____.png
I am not sure what the problem is as regardless of compatibility between PyGame and PyQt, once the image is saved as a .png, it should be able to be loaded like any other image. Is it just because it's open already while the code is running?
Any explanations and/or solutions would be appreciated, thank you.
Problem is that you first save pic with counter=1 without checking if directory exists so it's not saved at all.
After that you create directory if the pic counter == 1, so directory is created and all other pics will be saved in it but not first one.
You get error when you try to open that first pic which is not in the directory since it was not saved because directory has not existed.
Solution is to move this code:
if not os.path.exists(directory):
os.makedirs(directory)
here:
#sets directory to be used to save screenshots
directorydate = str(date.year) + str(date.month) + str(date.day) + str(date.hour) +str(date.minute) + str(date.second)
directory = os.path.abspath('Photos%s' % directorydate)
if not os.path.exists(directory):
os.makedirs(directory)
This is my main code:
import turtle
import random
from sys import exit
import canvasvg
import os
import tempfile
import shutil
import cairosvg
red = 125
green = 70
blue = 38
pen = 15
def runChk():
runAgain = input("Would you like to return to menu? Y/N (N will exit) \n")
if runAgain.upper() == "Y":
print("Running...")
turtle.clearscreen()
start()
elif runAgain.upper() == "N":
print("Exiting...")
exit()
else:
print("Invalid response.")
runChk()
def saveImg():
print("Done.")
save = input("Would you like to save this tree? Y/N \n")
if save.upper() == "Y":
filename = input("What would you like to name it? \n")
print("Ignore following warning...")
if not filename.lower().endswith('.png'):
filename += '.png'
target_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'Images', filename)
tmpdir = tempfile.mkdtemp() # create a temporary directory
tmpfile = os.path.join(tmpdir, 'tmp.svg') # name of file to save SVG to
ts = turtle.getscreen().getcanvas()
canvasvg.saveall(tmpfile, ts)
with open(tmpfile) as svg_input, open(target_path, 'wb') as png_output:
cairosvg.svg2png(bytestring=svg_input.read(), write_to=png_output)
shutil.rmtree(tmpdir) # clean up temp file(s)
print("Saved!")
runChk()
elif save.upper() == "N":
runChk()
else:
print("Invalid response. \n")
saveImg()
def tree(branchLen, red, green, blue, pen):
if branchLen > 3:
pen = pen*0.8
turtle.pensize(pen)
if (red > 10 and green < 140):
red = red - 15
green = green + 8
if branchLen > 5:
angle = random.randrange(18, 55)
angleTwo = 0.5*angle
sub = (0.8*(random.randrange(1,20)))
print("Angle 1: ", angle, "Angle 2: ", angleTwo, " Branch length subtracted by ", sub)
turtle.color(red, green, blue)
turtle.forward(branchLen)
turtle.right(angleTwo)
tree(branchLen-sub, red, green, blue, pen)
turtle.left(angle)
tree(branchLen-sub, red, green, blue, pen)
turtle.right(angleTwo)
turtle.backward(branchLen)
def main():
turtle.colormode(255)
turtle.bgcolor(102, 255, 255)
turtle.left(90)
turtle.up()
turtle.speed(0)
turtle.hideturtle()
turtle.backward(440)
turtle.down()
print("Please wait while I draw...")
tree(random.randrange(80, 95),red,green,blue, pen)
turtle.update()
saveImg()
def start():
live = 1
print("What would you like to do?\n")
usr = input("Type 'run' to start a fractal. \nType 'run static' to create a fractal without live drawing (faster). \nOr 'exit' to exit. \n")
if usr.upper() == "RUN":
live = 1
print("Running...")
main()
elif usr.upper() == "RUN STATIC":
live = 0
print("Running...")
turtle.tracer(0)
main()
elif usr.upper() == "EXIT":
print("Exiting...")
exit()
else:
print("Invalid response.")
start()
start()
it is called fractal.py. I copied that and canvasvg to the main python folder. I created a cx_freeze setup as so:
from cx_Freeze import setup, Executable
# NOTE: you can include any other necessary external imports here aswell
includefiles = [] # include any files here that you wish
includes = []
excludes = []
packages = ['turtle', 'random', 'sys', 'canvasvg', 'os', 'tempfile', 'shutil', 'cairosvg']
exe = Executable(
# what to build
script = "fractal.py", # the name of your main python script goes here
initScript = None,
base = None, # if creating a GUI instead of a console app, type "Win32GUI"
targetName = "Fractal Tree.exe", # this is the name of the executable file
copyDependentFiles = True,
compress = True,
appendScriptToExe = True,
appendScriptToLibrary = True,
icon = None # if you want to use an icon file, specify the file name here
)
setup(
# the actual setup & the definition of other misc. info
name = "Fractal Tree", # program name
version = "0.4.2",
description = 'Creates a fractal tree',
author = "TomSoft Programs",
options = {"build_exe": {"excludes":excludes,"packages":packages,
"include_files":includefiles}},
executables = [exe]
)
When I run cmd as python setup.py build, I get no errors. I go to the build folder and find my fractal.exe program. It closes very quickly and I can't get the full error (because of the speedy closing) but I know it says something like:
ReferenceError: 'module' object has no attribute '_fix_up_module'
What can I do to fix this? I'm very new to python and cx_freeze, so I'm sure I'm doing something wrong in setup.py.
For anyone who finds this, it's a bug with cx_freeze. You've done nothing wrong. Download cx_freeze from here, the bug is fixed at this download location.