200 lines
6.5 KiB
Python
200 lines
6.5 KiB
Python
import os
|
|
import sys
|
|
import tkinter as tk
|
|
from PIL import Image, ImageEnhance, ImageTk
|
|
from tkinter import filedialog, messagebox
|
|
from io import BytesIO
|
|
|
|
|
|
def save_image(image, output_image_path):
|
|
if image.mode == 'RGBA':
|
|
image = image.convert('RGB')
|
|
ext = os.path.splitext(output_image_path)[1].lower()
|
|
if ext in ['.jpg', '.jpeg']:
|
|
image.save(output_image_path, format='JPEG')
|
|
elif ext == '.png':
|
|
image.save(output_image_path, format='PNG')
|
|
else:
|
|
image.save(output_image_path)
|
|
root.quit()
|
|
root.destroy()
|
|
|
|
|
|
def compress_image(image, quality=85):
|
|
buffer = BytesIO()
|
|
if image.mode == 'RGBA':
|
|
image = image.convert('RGB')
|
|
image.save(buffer, format="JPEG", quality=quality)
|
|
buffer.seek(0)
|
|
return Image.open(buffer)
|
|
|
|
|
|
def adjust_sharpness(image, sharpness_factor=2.0):
|
|
enhancer = ImageEnhance.Sharpness(image)
|
|
return enhancer.enhance(sharpness_factor)
|
|
|
|
|
|
def resize_image(image, max_width, max_height):
|
|
ratio = min(max_width / image.width, max_height / image.height)
|
|
new_width = int(image.width * ratio)
|
|
new_height = int(image.height * ratio)
|
|
return image.resize((new_width, new_height), Image.LANCZOS), new_width, new_height
|
|
|
|
|
|
def update_image():
|
|
global img_tk
|
|
img = processed_image.copy()
|
|
|
|
# Apply compression
|
|
quality = compress_scale.get()
|
|
img = compress_image(img, int(quality))
|
|
|
|
# Apply sharpness
|
|
sharpness = clarity_scale.get() / 50.0 # scale from 0-100 to 0-2
|
|
img = adjust_sharpness(img, sharpness)
|
|
|
|
# Update the displayed image
|
|
img_tk = ImageTk.PhotoImage(img)
|
|
canvas_export.delete("current_image") # Delete the previous image
|
|
canvas_export.create_image(0, 0, anchor=tk.NW, image=img_tk, tags="current_image") # Add the new image with a tag
|
|
|
|
# Draw crop rectangle
|
|
canvas_export.delete("rect")
|
|
canvas_export.create_rectangle(start_x, start_y, end_x, end_y, outline='red', tag="rect")
|
|
|
|
|
|
def on_canvas_click(event):
|
|
global start_x, start_y
|
|
start_x = event.x
|
|
start_y = event.y
|
|
canvas_export.delete("rect")
|
|
|
|
|
|
def on_canvas_drag(event):
|
|
global start_x, start_y, end_x, end_y
|
|
end_x = event.x
|
|
end_y = event.y
|
|
canvas_export.delete("rect")
|
|
canvas_export.create_rectangle(start_x, start_y, end_x, end_y, outline='red', tag="rect")
|
|
|
|
|
|
def on_canvas_release(event):
|
|
global end_x, end_y
|
|
end_x = event.x
|
|
end_y = event.y
|
|
|
|
|
|
def crop_and_process_image(filename):
|
|
if processed_image is None:
|
|
messagebox.showwarning("Warning", "Please select an image first!")
|
|
return
|
|
|
|
# Get the coordinates of the selected region
|
|
x1 = min(start_x, end_x)
|
|
y1 = min(start_y, end_y)
|
|
x2 = max(start_x, end_x)
|
|
y2 = max(start_y, end_y)
|
|
|
|
cropped_img = processed_image.crop((x1, y1, x2, y2))
|
|
compress_quality = compress_scale.get()
|
|
sharpness_factor = clarity_scale.get() / 50.0 # scale from 0-100 to 0-2
|
|
cropped_img = compress_image(cropped_img, int(compress_quality))
|
|
cropped_img = adjust_sharpness(cropped_img, sharpness_factor)
|
|
|
|
base_name, extension = os.path.splitext(filename)
|
|
suggested_filename = base_name + "_processed" + extension
|
|
|
|
output_path = filedialog.asksaveasfilename(
|
|
title="Choose a file",
|
|
initialfile=suggested_filename,
|
|
filetypes=(("JPEG files", "*.jpg;*.jpeg"), ("PNG files", "*.png"), ("All files", "*.*"))
|
|
)
|
|
|
|
if output_path:
|
|
save_image(cropped_img, output_path)
|
|
messagebox.showinfo("Info", f"Image processed and saved to {output_path}")
|
|
|
|
|
|
def create_export_window(filename):
|
|
global original_image, processed_image, compress_scale, clarity_scale, canvas_export, start_x, start_y, end_x, end_y, canvas_frame, root, img_tk
|
|
root = tk.Tk()
|
|
root.title("Image Export Window")
|
|
root.configure(bg="#004c66")
|
|
root.iconbitmap('./icon/icon.ico')
|
|
|
|
# Convert the image buffer to a PIL Image
|
|
original_image = Image.open(filename)
|
|
|
|
# Resize the image to fit the canvas
|
|
processed_image, new_width, new_height = resize_image(original_image, 800, 600)
|
|
|
|
# Initialize cropping variables
|
|
start_x = 0
|
|
start_y = 0
|
|
end_x = new_width
|
|
end_y = new_height
|
|
|
|
# Set the root window geometry based on the image size
|
|
root.geometry(f"{new_width + 20}x{new_height + 200}")
|
|
|
|
# Set up the canvas frame
|
|
canvas_frame = tk.Frame(root, bg='white')
|
|
canvas_frame.pack(pady=10, fill=tk.BOTH, expand=True)
|
|
|
|
# Set up the canvas
|
|
canvas_export = tk.Canvas(canvas_frame, width=new_width, height=new_height, bg='white')
|
|
canvas_export.pack(fill=tk.BOTH, expand=True)
|
|
|
|
# Bind canvas events
|
|
canvas_export.bind("<Button-1>", on_canvas_click)
|
|
canvas_export.bind("<B1-Motion>", on_canvas_drag)
|
|
canvas_export.bind("<ButtonRelease-1>", on_canvas_release)
|
|
|
|
# Display the initial image
|
|
img_tk = ImageTk.PhotoImage(processed_image)
|
|
canvas_export.image = img_tk
|
|
canvas_export.create_image(0, 0, anchor=tk.NW, image=img_tk)
|
|
|
|
# Set up compression scale
|
|
compress_label = tk.Label(root, text="Compression", bg="yellow")
|
|
compress_label.pack(anchor='w', padx=10)
|
|
|
|
compress_scale = tk.Scale(root, from_=0, to=100, orient=tk.HORIZONTAL, bg="yellow",
|
|
command=lambda x: update_image())
|
|
compress_scale.set(85) # Set default value
|
|
compress_scale.pack(fill='x', padx=10)
|
|
|
|
# Set up clarity scale
|
|
clarity_label = tk.Label(root, text="Clarity", bg="yellow")
|
|
clarity_label.pack(anchor='w', padx=10)
|
|
|
|
clarity_scale = tk.Scale(root, from_=0, to=100, orient=tk.HORIZONTAL, bg="yellow", command=lambda x: update_image())
|
|
clarity_scale.set(50) # Set default value
|
|
clarity_scale.pack(fill='x', padx=10)
|
|
|
|
# Set up button frame
|
|
button_frame = tk.Frame(root, bg="#004c66")
|
|
button_frame.pack(pady=10)
|
|
|
|
# Set up confirm button
|
|
confirm_button = tk.Button(button_frame, text="Confirm", command=lambda: crop_and_process_image(filename),
|
|
bg="yellow")
|
|
confirm_button.pack(side='left', padx=10)
|
|
|
|
# Set up cancel button
|
|
cancel_button = tk.Button(button_frame, text="Cancel", command=root.destroy, bg="yellow")
|
|
cancel_button.pack(side='right', padx=10)
|
|
|
|
root.mainloop()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
if len(sys.argv) < 2:
|
|
# Assuming the image file path is passed directly for testing
|
|
img_path = filedialog.askopenfilename(title="Select an Image", filetypes=(("Image files", "*.jpg;*.jpeg;*.png"), ("All files", "*.*")))
|
|
if img_path:
|
|
create_export_window(img_path)
|
|
else:
|
|
tmp_file_path = sys.argv[1]
|
|
create_export_window(tmp_file_path)
|