--- layout: post title: 圖片轉Ascii Art小工具 date: 2019-9-26 21:00:00 +0800 categories: [用Python搞點事] tags: blog, python, small_tool --- #### 本文概述 需具備能力: 了解python基礎語法 能學到甚麼: 使用PIL套件處理圖片、檔案讀寫 使用軟體: python3、PIL、Notepad++ {% endnote %} ## 介紹 這次要帶大家用Python寫一個將圖片轉換成Ascii Art的小工具。 ### 先來個Demo **這是原圖** ![](https://i.imgur.com/bBpb2at.jpg) **經過我們的工具轉換後** ![](https://i.imgur.com/uVceeF1.png) 嗯? 你說你不知道我在幹嘛嗎? 我們把它放大點來看。 ![](https://i.imgur.com/wy77UDr.png) 這個是柴柴拳頭的部分XD 我們這次就是要用Python做一個可以把圖片轉換成這樣,由一個一個文字符號組成的"Ascii Art"。 ## 什麼是Ascii Art 所謂的Ascii Art,意旨使用Ascii的符號所創作的圖片,也就是用一個個小小的文字,拼湊成一張圖片的一種創作手法。這邊放幾張好看的Ascii Art來給各位欣賞。 ![](https://s3.amazonaws.com/media-p.slid.es/uploads/922060/images/6046202/pasted-from-clipboard.png) ![](https://s3.amazonaws.com/media-p.slid.es/uploads/922060/images/6046204/pasted-from-clipboard.png) ![]() 但是一個字一個字去敲,敲成一張圖片,這樣實在很麻煩。假設你想要一張100 x 100大小的圖片就要敲10000個字,而且還要考慮每個字放在哪裡才能組合成特定形狀,真的會打到眼花撩亂。 因此,我們可以自製工具,透過讀取圖片中一個個像素的方式,將像素傳換為文字,藉此達到我們要的效果。 ## 何謂套件 套件是別人寫好的工具,我們可以用這些工具提供給我們的api(application programming interface)來完成我們想做的事情。 ## PIL套件介紹 PIL(Python Image Library)是一套處理圖片的套件,他可以調整圖片的大小、亮度、對比、色調、裁切圖片、旋轉圖片、加濾鏡、附加文字......等等,雖然沒有專業的圖像編輯軟體來的強大,但可以批次處理圖片,而且彈性較大。 ## 圖片檔概念 圖像檔案保存的方式是這樣的,假設有一張200x100的圖片檔,顏色編碼為RGB,這是什麼意思呢? 200x100指的是像素,這張圖片的寬有200個像素、高有100,也就是說這張圖片總共有20000個像素 那每個像素究竟存了什麼值? 這邊看到RGB,代表每個像素存取的是RGB三個顏色的值,每個顏色一個Byte(8bit) ## 設計想法 * 目標: 製作一個圖片轉成文字檔的小工具 * 核心流程: 將圖片轉為黑白,讀取每個像素,是黑的就填上@符號,是白的就填上_符號 ## 實作 :::info 完整程式碼: 在開始之前先確定電腦有裝好python3、pip、Notepad++ notepad++載點: https://notepad-plus-plus.org/download/v7.6.6.htmlNotepad++ 選這個zip package 32-bit x86 ::: 1. 安裝並引入PIL套件 使用pip(python的套件管理系統)進行安裝,這邊注意要用pillow作為名稱 ```bash= C:\Users\Sam> pip install pillow ``` 在python檔案開頭使用這行程式碼可將PIL當中的Image模組引入 ```python= from PIL import Image ``` 2. 開啟圖片 ```python= img = Image.open(imgName) ``` 3. 顯示圖片資訊,如果色彩模式不是RGB則轉換為RGB ```python= print("圖片資訊: 大小為{}x{}, 格式為{}, 色彩模式為{}".format(img.size[0], img.size[1], img.format, img.mode)) if img.mode != 'RGB': print("圖片顏色編碼不是RGB,進行轉換") img = img.convert('RGB') print("轉換完成") ``` * img.size是一個紀錄圖片大小的tuple,img.size[0]是寬、img.size[1]是高 * img.mode是一個字串,紀錄圖片的編碼,常見的有這些 * RGB: 三色,R紅、G綠、B藍(3x8bits) * RGBA: 跟RGB一樣,只是多了Alpha值,也就是透明度(4x8bits) * CMYK: 四色,C青、M洋紅、Y黃、K黑色(4x8bits) * 1: 黑白(1bit) * L: 256色灰階(8bits) * P: 256色彩色(8bits) > 參考: https://pillow.readthedocs.io/en/3.1.x/handbook/concepts.html#modes 4. 調整圖片大小 ```python= zoom = 0 # 縮小比率 if width >= maxSize: zoom = width / maxSize width = int(width / zoom) height = int(height / zoom) height = int(height / 2) # 除2讓比例看起來比較正確 img = img.resize((width, height)) print("圖片寬於{},已縮小為{}x{}".format(maxSize, img.size[0], img.size[1])) ``` 5. 將圖片轉為黑白 ```python= img = img.convert('1') ``` 6. 開啟文字文件 ```python= txt = open(namestr, 'w') ``` 7. 從上至下、從左至右讀取每個pixel的值 轉換成黑白顏色編碼後,每個pixel的值,不是1就是0,我們從上而下、由左而右讀取每個pixel,如果是1則在文字檔中寫入@代表黑色部分,如果是0則寫入_代表白色部分。 ```python= for y in range(height): for x in range(width): pixel = img.getpixel((x, y)) # print('x= ', x, 'y= ', y, 'pixel= ', pixel) if pixel != 0: txt.write('_') else: txt.write('@') txt.write('\n') ``` 8. 關閉文字文件 ```python= txt.close() ``` > 參考資料: [Python趣味实用小工具](http://www.demodashi.com/demo/12918.html)