1-4mb之间是好使的
# 设定图片大小有效
import os
import threading
import logging
from tkinter import Tk, Button, Label, Entry, Text, Scrollbar, filedialog, messagebox
from tkinter.ttk import Progressbar
from PIL import Image, ImageDraw, ImageFont
import numpy as np
def setup_logging(output_dir):
if not os.path.exists(output_dir):
os.makedirs(output_dir)
log_file = os.path.join(output_dir, 'process_log.txt')
logging.basicConfig(filename=log_file, level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
def resize_to_resolution(image_path, output_path, target_resolution, min_size_kb, max_size_kb):
with Image.open(image_path) as img:
img = img.resize(target_resolution, Image.LANCZOS)
img.save(output_path, format='PNG')
ensure_image_size_range(output_path, min_size_kb, max_size_kb)
def embed_image(original_image_path, hidden_image_path, output_path, min_size_kb, max_size_kb):
origin_img = Image.open(original_image_path)
hidden_img = Image.open(hidden_image_path)
origin_data = np.array(origin_img)
hidden_data = np.array(hidden_img)
# 确保隐藏图片的大小小于原图片大小
hidden_data = hidden_data[:origin_data.shape[0], :origin_data.shape[1], :]
# 融合数据
for row in range(hidden_data.shape[0]):
for col in range(hidden_data.shape[1]):
for channel in range(3): # 遍历RGB三个通道
origin_data[row, col, channel] = (origin_data[row, col, channel] & 0xFE) | (
hidden_data[row, col, channel] >> 7)
embedded_image = Image.fromarray(origin_data)
draw_text(embedded_image, "我爱peiniu")
embedded_image.save(output_path, format='PNG')
ensure_image_size_range(output_path, min_size_kb, max_size_kb)
def generate_large_image(size_kb, output_path):
# 生成一个指定大小的随机图像
width = int(np.sqrt(size_kb * 1024 / 3)) # 假设每个像素3字节(RGB)
height = width
random_image_data = np.random.randint(0, 256, (height, width, 3), dtype=np.uint8)
hidden_image = Image.fromarray(random_image_data)
hidden_image.save(output_path, format='PNG')
def draw_text(image, text):
draw = ImageDraw.Draw(image)
font_size = max(10, image.size[0] // 100)
font = ImageFont.truetype("arial.ttf", font_size)
bbox = draw.textbbox((0, 0), text, font=font)
text_width, text_height = bbox[2] - bbox[0], bbox[3] - bbox[1]
position = (image.size[0] - text_width - 10, image.size[1] - text_height - 10) # 右下角
draw.text(position, text, (255, 255, 255), font=font)
def process_images(input_dir, output_dir, min_size_kb, max_size_kb):
setup_logging(output_dir)
if not os.path.exists(output_dir):
os.makedirs(output_dir)
hidden_image_path = os.path.join(output_dir, 'hidden_image.png')
generate_large_image(min_size_kb, hidden_image_path) # 生成一个指定大小的隐藏图片
image_files = [f for f in os.listdir(input_dir) if f.lower().endswith(('.png', '.jpg', '.jpeg'))]
total_files = len(image_files)
log_text.insert('end', f"Processing {total_files} images...\n")
progress_bar["maximum"] = total_files
success_count = 0
error_count = 0
for i, filename in enumerate(image_files):
input_path = os.path.join(input_dir, filename)
temp_path = os.path.join(output_dir, 'temp_' + filename)
output_path = os.path.join(output_dir, filename.replace('.jpg', '.png').replace('.jpeg', '.png')) # 确保输出为PNG格式
try:
file_size_kb = os.path.getsize(input_path) / 1024
if file_size_kb max_size_kb:
reduce_image_size(image_path)
def increase_image_size(image_path):
image = Image.open(image_path)
width, height = image.size
new_size = (int(width * 1.1), int(height * 1.1))
image = image.resize(new_size, Image.LANCZOS)
image.save(image_path, format='PNG')
def reduce_image_size(image_path):
image = Image.open(image_path)
width, height = image.size
new_size = (int(width * 0.9), int(height * 0.9))
image = image.resize(new_size, Image.LANCZOS)
image.save(image_path, format='PNG')
def select_input_dir():
input_dir = filedialog.askdirectory()
input_dir_entry.delete(0, 'end')
input_dir_entry.insert(0, input_dir)
def select_output_dir():
output_dir = filedialog.askdirectory()
output_dir_entry.delete(0, 'end')
output_dir_entry.insert(0, output_dir)
def start_processing():
input_dir = input_dir_entry.get()
output_dir = output_dir_entry.get()
min_size = int(min_size_entry.get())
max_size = int(max_size_entry.get())
if not input_dir or not output_dir or not min_size or not max_size:
messagebox.showerror("Error", "Please fill all fields.")
return
log_text.delete(1.0, 'end')
# 创建一个新的线程来处理图像处理任务
threading.Thread(target=process_images, args=(input_dir, output_dir, min_size, max_size)).start()
# 创建Tkinter窗口
root = Tk()
root.title("Image Processing Tool")
# 输入目录选择
Label(root, text="Input Directory:").grid(row=0, column=0, padx=10, pady=5, sticky='e')
input_dir_entry = Entry(root, width=50)
input_dir_entry.grid(row=0, column=1, padx=10, pady=5)
Button(root, text="Browse", command=select_input_dir).grid(row=0, column=2, padx=10, pady=5)
# 输出目录选择
Label(root, text="Output Directory:").grid(row=1, column=0, padx=10, pady=5, sticky='e')
output_dir_entry = Entry(root, width=50)
output_dir_entry.grid(row=1, column=1, padx=10, pady=5)
Button(root, text="Browse", command=select_output_dir).grid(row=1, column=2, padx=10, pady=5)
# 最小大小输入
Label(root, text="Min Size (KB):").grid(row=2, column=0, padx=10, pady=5, sticky='e')
min_size_entry = Entry(root, width=20)
min_size_entry.grid(row=2, column=1, padx=10, pady=5, sticky='w')
# 最大大小输入
Label(root, text="Max Size (KB):").grid(row=3, column=0, padx=10, pady=5, sticky='e')
max_size_entry = Entry(root, width=20)
max_size_entry.grid(row=3, column=1, padx=10, pady=5, sticky='w')
# 开始处理按钮
Button(root, text="Start Processing", command=start_processing).grid(row=4, column=1, pady=20)
# 进度条
progress_bar = Progressbar(root, orient='horizontal', mode='determinate')
progress_bar.grid(row=5, column=0, columnspan=3, padx=10, pady=5, sticky='we')
# 日志信息显示框
log_text = Text(root, wrap='word', height=10, width=80)
log_text.grid(row=6, column=0, columnspan=3, padx=10, pady=10)
scrollbar = Scrollbar(root, command=log_text.yview)
scrollbar.grid(row=6, column=3, pady=10, sticky='ns')
log_text['yscrollcommand'] = scrollbar.set
# 启动Tkinter主循环
root.mainloop()