commit 28cc4024c4f1e00daa7c867e7030d2d1dcb8caf7 Author: xiadongliang Date: Thu Mar 27 09:47:05 2025 +0800 better diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c9237b4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/__pycache__/ +/venv/ \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..ba4a5e9 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +`python -m venv venv` + +`./venv/Scripts/activate` + +`pipreqs --force` \ No newline at end of file diff --git a/images/d1.jpg b/images/d1.jpg new file mode 100644 index 0000000..2525389 Binary files /dev/null and b/images/d1.jpg differ diff --git a/images/d10.jpeg b/images/d10.jpeg new file mode 100644 index 0000000..029d89b Binary files /dev/null and b/images/d10.jpeg differ diff --git a/images/d2.jpg b/images/d2.jpg new file mode 100644 index 0000000..98546ec Binary files /dev/null and b/images/d2.jpg differ diff --git a/images/d3.jpg b/images/d3.jpg new file mode 100644 index 0000000..cc8b8e1 Binary files /dev/null and b/images/d3.jpg differ diff --git a/images/d4.jpeg b/images/d4.jpeg new file mode 100644 index 0000000..ad00934 Binary files /dev/null and b/images/d4.jpeg differ diff --git a/images/d5.jpeg b/images/d5.jpeg new file mode 100644 index 0000000..440ed1e Binary files /dev/null and b/images/d5.jpeg differ diff --git a/images/d6.jpeg b/images/d6.jpeg new file mode 100644 index 0000000..4f112b8 Binary files /dev/null and b/images/d6.jpeg differ diff --git a/images/d7.jpeg b/images/d7.jpeg new file mode 100644 index 0000000..228a92f Binary files /dev/null and b/images/d7.jpeg differ diff --git a/images/d8.jpeg b/images/d8.jpeg new file mode 100644 index 0000000..b5bc6cc Binary files /dev/null and b/images/d8.jpeg differ diff --git a/images/d9.jpg b/images/d9.jpg new file mode 100644 index 0000000..b4927fb Binary files /dev/null and b/images/d9.jpg differ diff --git a/main.py b/main.py new file mode 100644 index 0000000..d7dd142 --- /dev/null +++ b/main.py @@ -0,0 +1,121 @@ +from PIL import Image, ImageDraw, ImageFont +import os +import math +import random + + +def resize_with_crop(img, target_size): + """Resize an image with cropping to match the target aspect ratio.""" + width, height = img.size + target_width, target_height = target_size + aspect = target_width / target_height + + if width / height > aspect: + new_width = int(height * aspect) + left = (width - new_width) // 2 + img = img.crop((left, 0, left + new_width, height)) + else: + new_height = int(width / aspect) + top = (height - new_height) // 2 + img = img.crop((0, top, width, top + new_height)) + + return img.resize(target_size, Image.Resampling.LANCZOS) + + +def load_small_images(directory, target_size): + """Load and resize small images from a directory.""" + small_images = [] + for filename in os.listdir(directory): + if filename.lower().endswith(('.png', '.jpg', '.jpeg')): + try: + img = Image.open(os.path.join(directory, filename)) + img = resize_with_crop(img, target_size) + small_images.append(img) + except Exception as e: + print(f"无法加载图片: {filename}, 错误: {e}") + return small_images + + +def create_text_image(text, output_size, font_path=None, font_size=1800): + """Create a grayscale image with the target text.""" + temp_img = Image.new('L', output_size, 0) + draw = ImageDraw.Draw(temp_img) + + font = load_font(font_path, font_size) + bbox = draw.textbbox((0, 0), text, font=font, anchor="lt") + + text_x = (output_size[0] - (bbox[2] - bbox[0])) // 2 + text_y = (output_size[1] - (bbox[3] - bbox[1])) // 2 + + draw.text((text_x, text_y), text, fill=255, font=font) + return temp_img + + +def load_font(font_path, font_size): + """Load a font, falling back to default if unavailable.""" + try: + return ImageFont.truetype(font_path or "simhei.ttf", font_size) + except: + try: + return ImageFont.truetype("msyh.ttc", font_size) + except: + print("警告: 未找到中文字体,可能无法正确显示中文") + return ImageFont.load_default() + + +def paste_small_images(small_images, rows, cols, small_img_size, temp_img, output_img): + """Paste small images onto the output image based on the text mask.""" + for y in range(rows): + for x in range(cols): + box = ( + x * small_img_size[0], + y * small_img_size[1], + (x + 1) * small_img_size[0], + (y + 1) * small_img_size[1] + ) + sample_x = box[0] + small_img_size[0] // 2 + sample_y = box[1] + small_img_size[1] // 2 + + if sample_x < temp_img.width and sample_y < temp_img.height: + small_img = random.choice(small_images) + small_img = prepare_small_image(small_img, box, temp_img.getpixel((sample_x, sample_y))) + output_img.paste(small_img, box, small_img if small_img.mode == "RGBA" else None) + + +def prepare_small_image(small_img, box, pixel_value): + """Prepare a small image for pasting, applying transparency if needed.""" + small_img = small_img.resize((box[2] - box[0], box[3] - box[1])) + if pixel_value <= 128: + small_img = small_img.convert("RGBA") + alpha = small_img.split()[3].point(lambda p: p * 0.6) + small_img.putalpha(alpha) + return small_img + + +def create_character_mosaic(target_text, small_images_dir, output_path, output_size=(7680, 4320), small_img_size=(60, 60)): + """Main function to create a character mosaic.""" + small_images = load_small_images(small_images_dir, (100, 100)) + if not small_images: + raise ValueError("没有找到可用的图片") + + temp_img = create_text_image(target_text, output_size) + cols = math.ceil(output_size[0] / small_img_size[0]) + rows = math.ceil(output_size[1] / small_img_size[1]) + + output_img = Image.new('RGB', (cols * small_img_size[0], rows * small_img_size[1])) + paste_small_images(small_images, rows, cols, small_img_size, temp_img, output_img) + + output_img.save(output_path) + print(f"图片已保存到: {output_path}") + + +if __name__ == "__main__": + target_text = "WIN" + small_images_dir = "images" + output_path = "youbang_poster.jpg" + + if not os.path.exists(small_images_dir): + os.makedirs(small_images_dir) + print(f"请将小图片放入 {small_images_dir} 目录中") + else: + create_character_mosaic(target_text, small_images_dir, output_path) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..92973cc --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +Pillow==11.1.0 \ No newline at end of file diff --git a/youbang_poster.jpg b/youbang_poster.jpg new file mode 100644 index 0000000..37e0c74 Binary files /dev/null and b/youbang_poster.jpg differ