├── gift.new ├── .deepsource.toml ├── README.md ├── LICENSE └── main.py /gift.new: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Relentless-Machine/Ascii-Art/HEAD/gift.new -------------------------------------------------------------------------------- /.deepsource.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | 3 | [[analyzers]] 4 | name = "python" 5 | 6 | [analyzers.meta] 7 | runtime_version = "3.x.x" -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ascii-Art 2 | 这个程序实际上是给我朋友们的新年礼物。 3 | 4 | 这个程序是将图片转换为字符画。当然还有一个功能,我的朋友们可以体验一下,点击那个按钮就可以,我就不在这里说了。 5 | 6 | 还有,如果直接使用,请在release里面下载压缩文件。下载后将压缩文件解压,在文件夹里面运行那个EXE文件就可以了。 7 | 8 | 最后这个程序还有不完善的地方,希望大家谅解。 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Relentless-Machine 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from PIL import Image, ImageDraw, ImageFont, ImageTk 2 | import numpy as np 3 | import tkinter as tk 4 | from tkinter import filedialog 5 | import random 6 | 7 | 8 | def get_char(gray_pix): 9 | char_list = '''@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,"^`'. ''' 10 | length = len(char_list) 11 | unit = 256.0 / length 12 | return char_list[int(((length - 1) * gray_pix) / 256.0)] 13 | 14 | 15 | class BlessingWindow(tk.Toplevel): 16 | def __init__(self, master): 17 | super().__init__(master) 18 | self.title("Blessing Window") 19 | 20 | self.blessing_label = tk.Label(self, text="") 21 | self.blessing_label.pack(padx=20, pady=20) 22 | 23 | self.show_random_blessing() 24 | 25 | def show_random_blessing(self): 26 | blessings = self.read_blessings_from_file() 27 | if blessings: 28 | random_blessing = random.choice(blessings) 29 | self.blessing_label.config(text=random_blessing) 30 | 31 | @staticmethod 32 | def read_blessings_from_file(): 33 | try: 34 | with open("gift.new", "r", encoding="utf-16be") as file: 35 | blessings = [line.strip() for line in file.readlines()] 36 | return blessings 37 | except FileNotFoundError: 38 | return [] 39 | 40 | 41 | class ImageToASCIIConverter: 42 | def __init__(self, master): 43 | self.master = master 44 | self.master.title("Image to ASCII Art Converter") 45 | 46 | self.label = tk.Label(master, text="Select an image:") 47 | self.label.pack(pady=5) 48 | 49 | self.canvas = tk.Canvas(master, bg="white") 50 | self.canvas.pack(fill=tk.BOTH, expand=True) 51 | 52 | self.browse_button = tk.Button(master, text="Browse", command=self.choose_image) 53 | self.browse_button.pack(pady=10) 54 | 55 | self.convert_button = tk.Button(master, text="Convert to ASCII", command=self.convert_to_ascii) 56 | self.convert_button.pack(pady=10) 57 | 58 | self.display_button = tk.Button(master, text="Display Image", command=self.display_text_image) 59 | self.display_button.pack(pady=10) 60 | 61 | self.show_blessing_button = tk.Button(master, text="Show Blessing", command=self.show_blessing) 62 | self.show_blessing_button.pack(pady=10) 63 | 64 | self.info_label = tk.Label(master, text="") 65 | self.info_label.pack(pady=10) 66 | 67 | self.exit_button = tk.Button(master, text="Exit", command=self.master.destroy, fg="red") 68 | self.exit_button.pack(pady=10) 69 | 70 | self.blessing_window = None 71 | 72 | def choose_image(self): 73 | file_path = filedialog.askopenfilename(filetypes=[("Image files", "*.png;*.jpg;*.jpeg;*.gif")]) 74 | if file_path: 75 | self.img_path = file_path 76 | self.display_image() 77 | 78 | def display_image(self): 79 | image = Image.open(self.img_path) 80 | 81 | window_width = self.master.winfo_width() 82 | window_height = self.master.winfo_height() 83 | 84 | image.thumbnail((window_width, window_height)) 85 | 86 | tk_image = ImageTk.PhotoImage(image) 87 | 88 | self.canvas.delete("all") 89 | self.canvas.create_image(0, 0, anchor=tk.NW, image=tk_image) 90 | self.canvas.image = tk_image 91 | 92 | def convert_and_display(self): 93 | if hasattr(self, 'img_path'): 94 | img = Image.open(self.img_path) 95 | img_width = img.size[0] 96 | img_height = img.size[1] 97 | img = img.resize((int(img_width * 0.75), int(img_height * 0.5)), Image.NEAREST) 98 | img_gray = np.array(img.convert('L'), 'f') 99 | 100 | text = " " 101 | for i in range(int(img_height * 0.5)): 102 | for j in range(int(img_width * 0.75)): 103 | text = text + get_char(img_gray[i, j]) 104 | text = text + '\n' 105 | 106 | text_name = "ascii_art.txt" 107 | with open(text_name, "w") as f: 108 | f.write(text) 109 | 110 | self.info_label.config(text=f"ASCII art saved to {text_name}") 111 | print(f"ASCII art saved to {text_name}") 112 | return text_name 113 | 114 | def convert_to_ascii(self): 115 | if hasattr(self, 'img_path'): 116 | return self.convert_and_display() 117 | 118 | def display_text_image(self): 119 | try: 120 | text_name = self.convert_to_ascii() 121 | if text_name: 122 | with open(text_name, "r") as f: 123 | ascii_text = f.read().splitlines() 124 | 125 | img = self.ascii_to_image(ascii_text) 126 | self.display_image_with_ascii(img) 127 | 128 | except FileNotFoundError: 129 | self.info_label.config(text="ASCII art file not found.") 130 | 131 | def display_image_with_ascii(self, img): 132 | window_width = self.master.winfo_width() 133 | window_height = self.master.winfo_height() 134 | 135 | img.thumbnail((window_width, window_height)) 136 | 137 | tk_image = ImageTk.PhotoImage(img) 138 | 139 | self.canvas.delete("all") 140 | self.canvas.create_image(0, 0, anchor=tk.NW, image=tk_image) 141 | self.canvas.image = tk_image 142 | 143 | def show_blessing(self): 144 | if self.blessing_window: 145 | self.blessing_window.destroy() 146 | 147 | self.blessing_window = BlessingWindow(self.master) 148 | 149 | @staticmethod 150 | def ascii_to_image(ascii_text): 151 | char_width = 6 152 | char_height = 12 153 | font_size = 12 154 | 155 | img_width = len(ascii_text[0]) * char_width 156 | img_height = len(ascii_text) * char_height 157 | 158 | img = Image.new('RGB', (img_width, img_height), color='white') 159 | draw = ImageDraw.Draw(img) 160 | font = ImageFont.load_default() 161 | 162 | for i, line in enumerate(ascii_text): 163 | draw.text((0, i * char_height), line, fill='black', font=font) 164 | 165 | return img 166 | 167 | 168 | if __name__ == "__main__": 169 | root = tk.Tk() 170 | app = ImageToASCIIConverter(root) 171 | root.geometry("800x600") 172 | root.mainloop() 173 | --------------------------------------------------------------------------------