GI_AchievementParser/utils.py

105 lines
4.1 KiB
Python

import io
import os.path
import sys
import threading
import timeit
import psutil
import pytesseract
from PIL import Image, ImageChops
from pywinauto.win32structures import RECT
def find_process(name: str):
matching = [x for x in psutil.process_iter() if x.name() == name]
if len(matching) == 0:
return None
return matching[0]
def scale_coords_to_resolution(coords: tuple, resolution: tuple):
x, y = coords
base_x, base_y = x / 2560, y / 1440
return int(base_x * resolution[0]), int(base_y * resolution[1])
def scale_box_to_resolution(box: RECT, window_rect: RECT):
left, top, right, bottom = int(box.left), int(box.top), int(box.right), int(box.bottom)
base_left, base_top, base_right, base_bottom = left / 2560, top / 1440, right / 2560, bottom / 1440
low_res_left = int(base_left * window_rect.width()) + int(window_rect.left)
low_res_top = int(base_top * window_rect.height()) + int(window_rect.top)
low_res_right = int(base_right * window_rect.width()) + low_res_left
low_res_bottom = int(base_bottom * window_rect.height()) + low_res_top
return RECT(low_res_left, low_res_top, low_res_right, low_res_bottom)
def bold_color_mask(image: Image.Image, target_color=(85, 85, 85), threshold=50):
# Create a mask for the gradient effect
start_mask = timeit.default_timer()
mask = Image.new("L", image.size)
for x in range(image.width):
for y in range(image.height):
pixel = image.getpixel((x, y))
color_difference = sum((a - b) ** 2 for a, b in zip(pixel, target_color))
if color_difference <= threshold ** 2:
mask.putpixel((x, y), 0)
else:
mask.putpixel((x, y), 255)
end_mask = timeit.default_timer()
# Apply the mask to the original image
composited = ImageChops.composite(Image.new("RGB", image.size, (255, 255, 255)), image, mask)
end_composite = timeit.default_timer()
# print(f"Mask: {end_mask - start_mask}, Composite: {end_composite - end_mask}")
return composited
def generate_achievement_boxes(achievement: RECT, status: RECT | None, height_adjust: int,
key: str = "end_achievement", count: int = 6, inversed: bool = False) -> dict:
box_coords = {}
for adjust_count in range(0, count):
generated_achievement_y = int(achievement.top) - (adjust_count * height_adjust)
if inversed:
generated_achievement_y = int(achievement.top) + (adjust_count * height_adjust)
box_coords[f"{key}_{adjust_count}"] = RECT(achievement.left, generated_achievement_y,
achievement.right,
achievement.bottom) # it's actually width and height
if status is not None:
generated_status_y = int(status.top) - (adjust_count * height_adjust)
if inversed:
generated_status_y = int(status.top) + (adjust_count * height_adjust)
box_coords[f"{key}_{adjust_count}_status"] = RECT(status.left, generated_status_y,
status.right, status.bottom)
return box_coords
def scan_image(image: str | bytes) -> str:
data = image
if isinstance(image, str):
with open(image, 'rb') as file:
data = file.read()
default_tesseract_path = "C:\\Program Files\\Tesseract-OCR\\tesseract.exe"
if not os.path.exists(default_tesseract_path):
raise Exception(f"Can't find tesseract at {default_tesseract_path}")
else:
pytesseract.pytesseract.tesseract_cmd = default_tesseract_path
fake_file = io.BytesIO(data)
return pytesseract.image_to_string(Image.open(fake_file), lang='eng')
def get_asset_path():
assets = {
'gc_achievements.json': 'assets\\gc_achievements.json',
'gc_categories.json': 'assets\\gc_categories.json',
}
if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):
return {k: os.path.join(sys._MEIPASS, v) for k, v in assets.items()}
return assets