Color LCD(3)

カラー液晶モジュールをRaspberry Piに接続して、最も低レベルな描画を行う所まではできたが、そこから一歩進んで画像ファイルを表示させようと思うと、画像を扱うための処理がかなり必要になってくる。

Pythonの画像処理ライブラリについて調べてみると、PILと呼ばれるモジュールが有名なようだが、かなり前から開発が止まっていて現在はPILからforkされたpillowプロジェクトがそれを引き継いでいるようだ。

pillowはパッケージ管理ツールpipでインストールできる。

$ sudo pip install pillow

使い方をざっと読んでみると、openメソッドで指定したファイルを開き、loadでその画像のピクセル情報を取得できるようだ。

pillowを使って画像ファイルを読み込み、液晶に表示させるプログラムは以下のようになった。読み込んだファイルを128×160のサムネイルに変換してから、1ピクセルずつ読み出して液晶に表示させている。

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

import RPi.GPIO as GPIO
import spidev           # sudo pip install spidev
import time
import sys
from PIL import Image   # sudo pip install pillow

class ST7735:
    def __init__(self):
        self.spi = spidev.SpiDev()
        self.spi.open(0, 0)
        self.spi.max_speed_hz = 16000000
        GPIO.setmode(GPIO.BCM)
        GPIO.setwarnings(False)
        GPIO.setup(24, GPIO.OUT)
        GPIO.setup(25, GPIO.OUT)
        self.reset()
        self.write_cmd(0x11)
        time.sleep(0.12)
        self.write((0xB1, 0x01, 0x2C, 0x2D))
        self.write((0xB2, 0x01, 0x2C, 0x2D))
        self.write((0xB3, 0x01, 0x2C, 0x2D, 0x01, 0x2C, 0x2D))
        self.write((0xB4, 0x07))
        self.write((0xC0, 0xA2, 0x02, 0x84))
        self.write((0xC1, 0xC5))
        self.write((0xC2, 0x0A, 0x00))
        self.write((0xC3, 0x8A, 0x2A))
        self.write((0xC4, 0x8A, 0xEE))
        self.write((0xC5, 0x0E))
        self.write((0x36, 0xC8))
        self.write((0xE0, 0x02, 0x1C, 0x07, 0x12, 0x37, 0x32, 0x29, 0x2D, 0x29, 0x25, 0x2B, 0x39, 0x00, 0x01, 0x03, 0x10))
        self.write((0xE1, 0x03, 0x1D, 0x07, 0x06, 0x2E, 0x2C, 0x29, 0x2D, 0x2E, 0x2E, 0x37, 0x3F, 0x00, 0x00, 0x02, 0x10))
        self.write((0x2A, 0x00, 0x02, 0x00, 0x81))
        self.write((0x2B, 0x00, 0x01, 0x00, 0xA0))
        self.write((0x3A, 0x05))
        self.write_cmd(0x29)
    def reset(self):
        GPIO.output(25, False)
        time.sleep(0.1)
        GPIO.output(25, True)
        time.sleep(0.1)
    def write_cmd(self, cmd):
        GPIO.output(24, False)  # RS=0
        self.spi.xfer2([cmd])
    def write_data(self, data):
        GPIO.output(24, True)   # RS=1
        self.spi.xfer2([data])
    def write(self, cmd):
        if len(cmd) == 0:
            return
        GPIO.output(24, False)  # RS=0
        self.spi.xfer2([cmd[0]])
        GPIO.output(24, True)   # RS=1
        self.spi.xfer2(list(cmd[1:]))
    def write_rgb(self, r, g, b):
        self.write_data(r & 0xF8 | g >> 5)
        self.write_data(g & 0xFC << 3 | b >> 3)
    def fill(self, r, g, b):
        self.write((0x2A, 0x00, 0x02, 0x00, 0x81))
        self.write((0x2B, 0x00, 0x01, 0x00, 0xA0))
        self.write_cmd(0x2C)
        hi = r & 0xF8 | g >> 5
        lo = g & 0xFC << 3 | b >> 3
        GPIO.output(24, True)   # RS=1
        for i in range(20480):
            self.spi.xfer2([hi, lo])
    def image(self, file):
        try:
            im = Image.open(file).convert("RGB")
            im.thumbnail((128, 160))
            pix = im.load()
            self.write((0x2A, 0x00, 0x02, 0x00, 0x81))
            self.write((0x2B, 0x00, 0x01, 0x00, 0xA0))
            self.write_cmd(0x2C)
            GPIO.output(24, True)   # RS=1
            for i in range(160):
                for n in range(128):
                    pixel = pix[n, i]
                    hi = pixel[0] & 0xF8 | pixel[1] >> 5
                    lo = pixel[1] & 0xFC << 3 | pixel[2] >> 3
                    self.spi.xfer2([hi, lo])
        except:
            pass

if __name__ == "__main__":
    lcd = ST7735()
    lcd.fill(0, 0, 0)
    param = sys.argv
    lcd.image(param[1])
    try:
        while True:
            pass
    except KeyboardInterrupt:
        print '\nbreak'
    GPIO.cleanup()

起動時の引数として与えられたファイルを読み込むので、画像ファイルjack.jpgが存在している時

$ sudo python spilcd.py jack.jpg

と指定すれば、以下のように表示される。

2013-12-07 23.47.49

このプログラムに更に手を加えて、URLを処理するモジュールとテキストバッファモジュールを追加すれば、URLを指定してネット上の画像を表示させるようにもできる。
変更箇所だけ以下に記載しておく。

import urllib, cStringIO # 追加

if __name__ == "__main__":
    lcd = ST7735()
    lcd.fill(0, 0, 0)
    param = sys.argv
    file = cStringIO.StringIO(urllib.urlopen(param[1]).read())
    lcd.image(file)
    try:
        while True:
            pass
    except KeyboardInterrupt:
        print '\nbreak'
    GPIO.cleanup()

このプログラムに

$ sudo python spilcd.py http://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png

のように画像のURLを引数として起動すれば

2013-12-07 23.48.36このように表示される。

SPI接続のLCDに描画するだけなら、ワンチップマイコンでも容易くできてしまうが、画像ファイルを読み込んだりネットワーク上の画像を表示させたりが簡単にできてしまう所は、Linuxマイコンボードならではだろう。

広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中