Image2ASCII

一个 python 读取图片并转换为字符画的GUI程序, 待优化

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
import tkinter as tk
from tkinter import messagebox
from PIL import ImageTk, Image
import os


# 定义字符映射表
# 不懂区间的灰度值对应不同的字符
CHARS = '@%#*+=-:. '

class ImageViewer:
    def __init__(self):
        self.window = tk.Tk()
        self.window.title("主窗口")
        self.source_file_path = ''
        self.create_widgets()

    def create_widgets(self):
        # 图像文件路径
        self.entry = tk.Entry(self.window, width=50)
        self.entry.pack(pady=10)

        self.button_open_image = tk.Button(
            self.window, text="打开图像", command=self.open_image)
        self.button_open_image.pack(pady=5)

        self.image_label = tk.Label(self.window)
        self.image_label.pack()

        self.button_convert = tk.Button(
            self.window, text="转换为灰度图", command=self.convert_to_grayscale)
        self.button_convert.pack()

        self.button_convert = tk.Button(
            self.window, text="转换为字符画", command=self.convert_to_ascii)
        self.button_convert.pack()

        self.text_ascii = tk.Text(self.window, width=200, height=200)
        self.text_ascii.pack()

    def show_image(self):
        photo = ImageTk.PhotoImage(self.image)
        self.image_label.configure(image=photo)
        self.image_label.image = photo

    def show_ascii(self):
        self.text_ascii.delete('1.0', tk.END)
        self.text_ascii.insert(tk.END, self.ascii_str)

    def open_image(self):
        self.source_file_path = self.entry.get().strip('"')
        try:
            # pillow读取图片
            self.image = Image.open(self.source_file_path)
            self.image.thumbnail((400, 400))
            self.show_image()
        except Exception as e:
            if self.source_file_path == "":
                messagebox.showwarning(title='警告', message=f"请输入文件路径")
            elif not os.path.exists(self.source_file_path):
                messagebox.showwarning(
                    title='警告', message=f"文件 {self.source_file_path} 不存在")
            print(f"无法打开图像文件: {e}")

    def convert_to_grayscale(self):
        """图片转换为灰度图"""
        self.image = self.image.convert('L')
        self.show_image()

    def convert_to_ascii(self, width=200, chars=CHARS):
        # 调整图像尺寸
        w, h = self.image.size
        print(self.image.size)
        aspect_ratio = h / w

        # 字符的宽高比, 因为ASCII字符都是半角的(大部分字体), 所以需要再除以 2
        new_height = int(width * aspect_ratio / 2)
        # 调整大小
        resized_image = self.image.resize((width, new_height))
        print(resized_image.size)

        ascii_str = ''
        # 根据像素点的灰度值转换为字符画
        for y in range(new_height):
            for x in range(width):
                # 获取像素的亮度值
                brightness = resized_image.getpixel((x-1, y-1))
                # 根据亮度值映射到字符集中的字符
                char_index = int(brightness / 256 * len(chars))
                ascii_str += chars[char_index]
        # 添加换行符
        ascii_str += '\n'

        self.ascii_str = ascii_str
        self.show_ascii()

    def run(self):
        self.window.mainloop()


def main():
    # 创建ImageViewer对象并运行
    viewer = ImageViewer()
    viewer.run()