最近在 GitHub 看到一個挺有意思的 Python 程序(img2html: Convert a image to HTML)。html
它能將圖片的每一個像素用文字代替,最後生成一個HTML文檔,在瀏覽器中能夠顯示出圖像,只不過圖像全是由文字組成的。git
實現這樣的效果並不複雜,只不過是用標籤代替像素而已,接下來我會演示如何用 PIL/Pillow 庫去實現這樣的效果。github
PIL(Python Imaging Library) 是 Python 平臺的圖像處理標準庫。不過 PIL 暫不支持 Python3,能夠用 Pillow 代替,API是相同的。數組
若是你安裝了 pip 的話能夠直接輸入 pip install PIL 命令安裝 Pillow。瀏覽器
或者在 PyCharm 中打開 [File] >> [settings] >> [project github] >> [project interpreter] 添加標準庫:網絡
↑ 搜索 Pillow 包,選中 Pillow,點擊 Install Package 安裝ide
from PIL import Image img = Image.open('source.jpg') # 打開圖片 width, height = img.size # 圖片尺寸 img.thumbnail((width / 2, height / 2)) # 縮略圖 img = img.crop((0, 0, width / 2, width / 2)) # 圖片裁剪 img = img.convert(mode='L') # 圖片轉換 img = img.rotate(180) # 圖片旋轉 img.save('output.jpg') # 保存圖片
↑ PIL 經常使用模塊:Image, ImageFilter, ImageDraw, ImageFont, ImageEnhance, ImageFilter...字體
圖片轉換成網頁的過程,能夠分紅五個步驟。首先要選擇一個合適的HTML模板,控制好字體的大小和字符間的間距。ui
而後經過 Python 的 網絡訪問模塊,根據URL獲取圖片。接着使用 PIL 模塊載入二進制圖片,將圖片壓縮到合適的尺寸。url
遍歷圖片的每個像素,獲得該像素的顏色值,應用到HTML的標籤上。最後把字符串信息輸出到文件中,生成HTML文檔。
TEMPLATE = ''' <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>{title}</title> <style> body {{ line-height: 1em; letter-spacing: 0; font-size: 0.6rem; background: black; text-align: center; }} </style> </head> <body> {body} </body> </html> '''
↑ 大括號表明一個佔位符,最後會被替換成實際內容,雙大括號中的內容則不會被替換。
from urllib import request url = 'https://pic.cnblogs.com/avatar/875028/20160405220401.png' binary = request.urlopen(url).read()
↑ 經過 URL 獲得 byte 數組形式的圖片。
from PIL import Image from io import BytesIO img = Image.open(BytesIO(binary)) img.thumbnail((100, 100)) # 圖片壓縮
↑ byte 類型的 圖片須要經過 BytesIO 轉換爲 string 類型,才能被 PIL 處理。
piexl = img.load() # 獲取像素信息 width, height = img.size # 獲取圖像尺寸 body, word = '', '博客園' font = '<font color="{color}">{word}</font>' for y in range(height): for x in range(width): r, g, b = piexl[x, y] # 獲取像素RGB值 body += font.format( color='#{:02x}{:02x}{:02x}'.format(r, g, b), word=word[((y * width + x) % len(word))] ) body += '\n<br />\n'
↑ 使用<font>標籤包裹文字,並根據相應像素的RGB值,設置<font>標籤的color屬性。
html = TEMPLATE.format(title=word, body=body) fo = open('index.html', 'w', encoding='utf8') fo.write(html) fo.close()
↑ 向HTML模板中填充處理完成的數據,使用文件流將字符串以utf8格式輸出到文檔。
wo把上面五個步驟封裝了起來,這樣一來就能夠很方便的調用了。
from io import BytesIO from PIL import Image from PIL import ImageFilter from urllib import request TEMPLATE = ''' <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>{title}</title> <style> body {{ line-height: 1em; letter-spacing: 0; font-size: 0.6rem; background: black; text-align: center; min-width: {size}em; }} </style> </head> <body> {body} </body> </html> ''' class Converter(object): def __init__(self, word='田', size=100): self.word, self.size = word, size self.font = '<font color="{color}">{word}</font>' # 讀取url內容 def __network(self, url): return request.urlopen(url).read() # 處理圖片信息 def __handle(self, binary): img = Image.open(BytesIO(binary)) # 打開製圖片 img.thumbnail((self.size, self.size)) # 壓縮圖片 img.filter(ImageFilter.DETAIL) # 圖片加強 return img # 分析圖片像素 def __analysis(self, img): body = '' piexls = img.load() width, height = img.size for y in range(height): for x in range(width): r, g, b = piexls[x, y] body += self.font.format( color='#{:02x}{:02x}{:02x}'.format(r, g, b), word=self.word[((y * width + x) % len(self.word))] ) body += '\n<br />\n' return body # 寫入文件內容 def __writefile(self, file, str): fo = open(file, 'w', encoding='utf8') try: fo.write(str) except IOError: raise Exception finally: fo.close() # 生成html文檔 def buildDOC(self, url, output): try: binary = self.__network(url) img = self.__handle(binary) html = TEMPLATE.format( title=self.word, body=self.__analysis(img), size=self.size ) # 向模板中填充數據 self.__writefile(output, html) except Exception as err: print('Error:', err) return False else: print('Successful!') return True
導入 img2html.Converter,調用 buildDOC(url, out) 方法
from img2html import Converter conv = Converter('卷福', 120) url = 'http://www.sznews.com/ent/images/attachement/jpg/site3/20140215/001e4f9d7bf91469078115.jpg' out = 'index.html' conv.buildDOC(url, out)
↑ 程序會在當前目錄生成 index.html 文件,須要用瀏覽器打開後才能夠看到效果。
原始圖片 |
輸出HTML |
![]() |
![]() |