122 lines
5.7 KiB
Python
122 lines
5.7 KiB
Python
import base64
|
|
import pyperclip
|
|
import win32clipboard
|
|
from io import BytesIO
|
|
from PIL import Image
|
|
import requests
|
|
import numpy as np
|
|
import cv2
|
|
import time
|
|
import random
|
|
|
|
class base64TOImage:
|
|
def __init__(self, app, logger, browser_controller):
|
|
self.app = app
|
|
self.logger = logger
|
|
self.browser_controller = browser_controller # BrowserController 인스턴스를 전달받음
|
|
|
|
def get_clipboard_data(self):
|
|
"""클립보드의 텍스트 데이터를 가져옵니다."""
|
|
try:
|
|
return pyperclip.paste() # 클립보드의 텍스트 데이터를 가져옴
|
|
except Exception as e:
|
|
self.logger.debug(f"클립보드 데이터를 가져오는 중 오류 발생: {e}")
|
|
return None
|
|
|
|
def set_image_to_clipboard(self, image):
|
|
"""이미지를 클립보드에 넣는 함수 (Windows 전용)"""
|
|
output = BytesIO()
|
|
image.save(output, "BMP")
|
|
data = output.getvalue()[14:] # BMP 헤더 제거
|
|
output.close()
|
|
|
|
# 클립보드에 이미지 데이터 넣기
|
|
win32clipboard.OpenClipboard()
|
|
win32clipboard.EmptyClipboard()
|
|
win32clipboard.SetClipboardData(win32clipboard.CF_DIB, data)
|
|
win32clipboard.CloseClipboard()
|
|
|
|
def base64_to_image(self, base64_data):
|
|
"""Base64 데이터를 이미지로 변환하는 함수"""
|
|
if base64_data.startswith('data:image'):
|
|
header, encoded = base64_data.split(',', 1)
|
|
img_data = base64.b64decode(encoded)
|
|
image = Image.open(BytesIO(img_data))
|
|
return image
|
|
else:
|
|
self.logger.debug("유효하지 않은 Base64 이미지 데이터입니다.")
|
|
return None
|
|
|
|
def download_image_from_url(self, url, max_retries=3):
|
|
"""URL에서 이미지를 다운로드하고 PIL 이미지 객체로 반환"""
|
|
headers = {
|
|
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36",
|
|
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
|
|
"Accept-Language": "en-US,en;q=0.9",
|
|
"Accept-Encoding": "gzip, deflate, br",
|
|
"DNT": "1", # Do Not Track 요청 헤더
|
|
"Connection": "keep-alive",
|
|
"Upgrade-Insecure-Requests": "1",
|
|
"Cache-Control": "max-age=0"
|
|
}
|
|
|
|
retries = 0
|
|
while retries < max_retries:
|
|
try:
|
|
self.logger.debug(f"이미지 URL 다운로드 중: {url}")
|
|
response = requests.get(url, headers=headers, stream=True)
|
|
|
|
# 상태 코드가 200이 아니면 재시도
|
|
if response.status_code == 200:
|
|
# OpenCV로 이미지를 로드하여 변환
|
|
image = np.asarray(bytearray(response.content), dtype="uint8")
|
|
image = cv2.imdecode(image, cv2.IMREAD_COLOR)
|
|
|
|
# OpenCV에서 이미지를 PIL로 변환
|
|
if image is not None:
|
|
pil_image = Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
|
|
return pil_image
|
|
else:
|
|
self.logger.debug(f"이미지 파일 형식이 올바르지 않습니다. 대상 URL: {url}")
|
|
return None
|
|
else:
|
|
self.logger.debug(f"이미지 로딩 실패, HTTP 상태 코드: {response.status_code}. 재시도 {retries + 1}/{max_retries}")
|
|
retries += 1
|
|
time.sleep(random.randint(2, 5)) # 2~5초 대기 후 재시도
|
|
except Exception as e:
|
|
self.logger.debug(f"이미지 로딩 중 오류 발생: {e}. 재시도 {retries + 1}/{max_retries}")
|
|
retries += 1
|
|
time.sleep(random.randint(2, 5)) # 예외 발생 시 대기 후 재시도
|
|
|
|
self.logger.debug("이미지 다운로드 최대 재시도 횟수를 초과했습니다.")
|
|
return None
|
|
|
|
def process_clipboard(self, original_url):
|
|
"""클립보드의 내용을 처리하고, 필요한 경우 이미지 변환 또는 URL 이미지 복사"""
|
|
clipboard_data = self.get_clipboard_data()
|
|
|
|
if clipboard_data.startswith('data:image'):
|
|
# 클립보드에 있는 Base64 데이터를 이미지로 변환
|
|
image = self.base64_to_image(clipboard_data)
|
|
if image:
|
|
self.logger.debug("Base64 이미지 변환 성공, 클립보드에 다시 저장 중...")
|
|
self.set_image_to_clipboard(image)
|
|
self.logger.debug("이미지가 클립보드에 저장되었습니다.")
|
|
else:
|
|
self.logger.debug("Base64 이미지 변환 실패.")
|
|
|
|
elif clipboard_data.strip() == "html > whale-ocr":
|
|
# 'html > whale-ocr' 감지 시 원본 이미지 URL에서 이미지를 다운로드하여 클립보드에 복사
|
|
if original_url:
|
|
image = self.download_image_from_url(original_url)
|
|
if image:
|
|
self.logger.debug("원본 이미지 다운로드 성공, 클립보드에 다시 저장 중...")
|
|
self.set_image_to_clipboard(image)
|
|
self.logger.debug("원본 이미지가 클립보드에 저장되었습니다.")
|
|
else:
|
|
self.logger.debug("원본 이미지 다운로드 실패.")
|
|
else:
|
|
self.logger.debug("원본 이미지 URL을 찾을 수 없습니다.")
|
|
else:
|
|
self.logger.debug("클립보드에 Base64 이미지나 'html > whale-ocr' 데이터가 없습니다.")
|