Raspberry Pi 筆記(80):使用Python影像函式庫顯示圖形在ST7735 LCD(上)

過去曾寫過如何使用Arduino連接ST7735 LCD顯示器,使用Adafruit_GFX函式庫繪製圖形,可參考 Arduino筆記(65):Adafruit_GFX圖形程式庫用於顯示器,文章內容說明如何使用繪圖指令將線條、方形、圓形等圖案呈現在ST7735 LCD上。本篇將分成上下篇,上篇探討如何將ST7735 LCD連接樹莓派,如何使用Python圖形函式庫Python PIL,將圖形呈現在LCD顯示器上。下篇則要學習如何使用PIL函式庫呈現照片,或更換圖片格式等功能。



[接線圖]

Pi 接腳ST7735 LCD
Pin 4(+5V)VCC
Pin 6(GND)GND
Pin 23 GPIO 11(SCLK)SCL
Pin 19 GPIO 10(MOSI)SDA
Pin 24 GPIO 8(CE0)CS
Pin 18 GPIO 24RS/DC
Pin 22 GPIO 25RES
Pin 2(3.3V)LEDA



[啟動SPI]

ST7735使用SPI介面跟樹莓派介接,在使用前需先開啟樹莓派的SPI介面,可執行 raspi-config 選單開啟 SPI:
$ sudo raspi-config 
選擇 [5. Interfacing Options],再選擇 [P4 SPI]:


下一個 Enable  SPI interface畫面選擇 <yes >


[安裝Python相關套件]

開啟SPI後,先執行系統更新:
$ sudo apt-get update
接著安裝python相關套件:
$ sudo apt-get install build-essential python-dev python-smbus python-pip python-numpy
繼續安裝RPi.GPIO和Adafruit GPIO函式庫:
$ sudo pip install RPi.GPIO
$ sudo pip install Adafruit_GPIO
下載cskau在Github上的 ST7735 程式庫及範例程式:
$ git clone https://github.com/cskau/Python_ST7735
安裝 ST7735 程式庫:
$ cd Python_ST7735
$ sudo python setup.py install

[安裝Python PIL圖形庫]

Python 有一個處理圖片的函式庫,叫做Python Imaging Library,簡稱PIL,本實做也是用這個函式庫繪製圖形,這個函式庫具有繪製線條、圓形等功能,也可以用來處理圖片,例如轉圖片格式、縮放圖片等。如要安裝 PIL函式庫,可以執行以下指令進行安裝。
$ sudo apt-get install python-pil 
Python PIL大約有二十多個 模組(Module),如處理檔案的 ImageFile Module,處理圖片濾鏡的ImageFilter Module,以及本實做要探討的繪圖模組 ImageDraw Module。這個模組主要處理線條、文字及繪製的方形、圓形等圖形。


[ImageDraw圖形基本元素]

繪圖的基本原理是由點構成線、線構成面,在繪圖系統中,通常可以畫出點、線及各種圖形,如圓形、方形及三角型等,以下分別介紹各繪圖函式:

.畫點 Drawing pixels(points)
ImageDraw.point(xy, fill=None)
- xy是一個List,放x,y座標清單,例如:((10, 170), (110, 230))
- fill:填寫顏色值,是一個RGB的色碼表,如(255,255,255)或none。

.畫線 Drawing Lines
ImageDraw.line(xy, fill=None, width=0, joint=None)
- xy是一個List,放x,y座標清單,例如:((10, 170), (110, 230))
- fill:填寫顏色值,是一個RGB的色碼表,如(255,255,255)或none。
- width:線條寬度,以Pixel為單位。
- joint:連接點是否為圓角,可以是"curve" 或 "none"
例如畫一條白色的線:draw.line((10, 130, 110, 130), fill=(255,255,255))

.畫多邊形 Drawing polygon
ImageDraw.polygon(xy, fill=None, outline=None)
- xy是一個List,放x,y座標清單,例如:((10, 170), (110, 230))
- fill:填寫顏色值,是一個RGB的色碼表,如(255,255,255)或none。
- outline:多邊形線條的顏色
例如畫一個三角形:draw.polygon([(10, 90), (10, 120), (70, 105)], outline=(0,0,0), fill=(0,255,255))

.畫方形 Drawing Rectangle
ImageDraw.rectangle(xy, fill=None, outline=None, width=1)
- xy是一個List,放x,y座標清單,定義對角的兩個點形成方形。x1 >= x0、y1 >= y0 例如:
- outline:橢圓線條的顏色 - width:線條寬度,以Pixel為單位。
例如畫一個方形:draw.rectangle((10, 60, 60, 80), outline=(255,255,0), fill=(255,0,255))

.畫圓或橢圓 Drawing Circle/Ellipse
ImageDraw.ellipse(xy, fill=None, outline=None, width=1)
- xy是一個List,放x,y座標清單,定義邊界框的兩點。x1 >= x0、y1 >= y0 例如:
- fill:填寫顏色值,是一個RGB的色碼表,如(255,255,255)或none。
- outline:橢圓線條的顏色 - width:線條寬度,以Pixel為單位。
例如畫一個圓形:draw.ellipse((10, 10, 40, 40), outline=(0,255,0), fill=(0,0,255))

.顯示文字 Drawing Text
ImageDraw.text(xy, text, fill=None, font=None, anchor=None, spacing=4, align='left', direction=None, features=None, language=None, stroke_width=0, stroke_fill=None)[source]
- xy是一個List,放文字左上角的x,y座標
- fill:文字的顏色值,是一個RGB的色碼表,如(255,255,255)或none。
- font:文字的顏色值,是 ImageFont的 instance.。
- spacing:假使文字傳遞多行multiline_text(),設定行間的距離,以pixel為單位。
- align:假使文字傳遞多行multiline_text(),可設定為
- direction:文字顯示的方向,可以是從右到左"rtl" (right to left),從左到右 "ltr" (left to right) or 從上到下 "ttb" (top to bottom)三種。

.顯示多行文字 Drawing Text
ImageDraw.multiline_text(xy, text, fill=None, font=None, anchor=None, spacing=4, align='left', direction=None, features=None, language=None)
-請參考上述ImageDraw.text參數說明。

[程式]

# !/usr/bin/python
# coding:utf-8

from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont

import time
import ST7735 as TFT
import Adafruit_GPIO as GPIO
import Adafruit_GPIO.SPI as SPI

# 定義LCD的長寬
WIDTH = 128
HEIGHT = 160
SPEED_HZ = 4000000

# Raspberry Pi 設定
DC = 24
RST = 25
SPI_PORT = 0
SPI_DEVICE = 0

# 建立 TFT LCD 顯示類別
disp = TFT.ST7735(
    DC,
    rst=RST,
    spi=SPI.SpiDev(
        SPI_PORT,
        SPI_DEVICE,
        max_speed_hz=SPEED_HZ))
# 初始化顯示
disp.begin()

# 清除畫面為全黑色
disp.clear((0, 0, 0))

# 建立一個 PIL Draw 物件,繪製在顯示緩衝區.
draw = disp.draw()

# 畫一個藍色圓形
draw.ellipse((10, 10, 40, 40), outline=(0,255,0), fill=(0,0,255))
# 畫一個黃色橢圓形
draw.ellipse((90,10, 120, 90), outline=(0,255,0), fill=(255,255,0))

# 畫一個紫色的方形及黃色外框
draw.rectangle((10, 60, 60, 80), outline=(255,255,0), fill=(255,0,255))

# 畫兩條線
draw.line((10, 130, 110, 130), fill=(255,255,255))
draw.line((10, 140, 110, 140), fill=(255,255,255))

# 畫一個多邊形(三點是三角形)
draw.polygon([(10, 90), (10, 120), (70, 105)], outline=(0,0,0), fill=(0,255,255))

# 將緩衝寫入硬體顯示
disp.display()

# 暫停10秒
time.sleep(10)

# 以紅色清除螢幕
disp.clear((255, 0, 0))

# 載入預設的字型
# font = ImageFont.load_default()

# 更換字型ttf檔,可到 https://fonts.google.com/ 尋找你想呈現的字型
# 參數的16是字型的大小
font = ImageFont.truetype('/home/pi/font/NotoSansTC-Bold.otf', 16)

# 定義一個函數,用來旋轉文字
def draw_rotated_text(image, text, position, angle, font, fill=(255,255,255)):
    # 設定文字寬度和高度
    draw = ImageDraw.Draw(image)
    width, height = draw.textsize(text, font=font)

    # 建立一個背景透明的新影像物件儲存文字
    textimage = Image.new('RGBA', (width, height), (0,0,0,0))

    # Render the text.
    textdraw = ImageDraw.Draw(textimage)
    textdraw.text((0,0), text, font=font, fill=fill)

    # 旋轉文字影像
    rotated = textimage.rotate(angle, expand=1)

    # 將文字貼到影像
    image.paste(rotated, position, rotated)

# 逆時針轉 90 度
draw_rotated_text(disp.buffer, 'Hello Maker...', (10, 10), 90, font, fill=(255,255,255))
draw_rotated_text(disp.buffer, 'Demo Text In ST7735...', (40, 10), 90, font, fill=(255,255,255))

# 將緩衝寫入硬體顯示
disp.display()

[執行結果]



停10秒後,出現以下圖形畫面:

2 留言

  1. 作者已經移除這則留言。

    回覆刪除
  2. Pin 2(3.3V).....LEDA is not correct. it should Pin 1(3.3V)....LEDA. No matter how, the wiring circuit is fine

    回覆刪除

    回覆刪除

張貼留言

較新的 較舊