Adafruit_Python_LED_Backpack/Adafruit_LED_Backpack/Matrix8x16.py
2017-02-11 16:37:56 -08:00

175 lines
7.5 KiB
Python
Executable file

# Copyright (c) 2017 Adafruit Industries
# Author: Carter Nelson
# Modified from Matrix8x8 by Tony DiCola
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
from . import HT16K33
from PIL import Image
import time
class Matrix8x16(HT16K33.HT16K33):
"""Single color 8x16 matrix LED backpack display."""
def __init__(self, **kwargs):
"""Initialize display. All arguments will be passed to the HT16K33 class
initializer, including optional I2C address and bus number parameters.
"""
super(Matrix8x16, self).__init__(**kwargs)
def set_pixel(self, x, y, value):
"""Set pixel at position x, y to the given value. X and Y should be values
of 0 to 7 and 0 to 15, resp. Value should be 0 for off and non-zero for on.
"""
if x < 0 or x > 7 or y < 0 or y > 15:
# Ignore out of bounds pixels.
return
self.set_led((7 - x) * 16 + y, value)
def set_image(self, image):
"""Set display buffer to Python Image Library image. Image will be converted
to 1 bit color and non-zero color values will light the LEDs.
"""
imwidth, imheight = image.size
if imwidth != 8 or imheight != 16:
raise ValueError('Image must be an 8x16 pixels in size.')
# Convert image to 1 bit color and grab all the pixels.
pix = image.convert('1').load()
# Loop through each pixel and write the display buffer pixel.
for x in xrange(8):
for y in xrange(16):
color = pix[(x, y)]
# Handle the color of the pixel, off or on.
if color == 0:
self.set_pixel(x, y, 0)
else:
self.set_pixel(x, y, 1)
def create_blank_image(self):
return Image.new("RGB", (8, 16))
def horizontal_scroll(self, image, padding=True):
"""Returns a list of images which appear to scroll from left to right
across the input image when displayed on the LED matrix in order.
The input image is not limited to being 8x16. If the input image is
larger than this, then all columns will be scrolled through but only
the top 16 rows of pixels will be displayed.
Keyword arguments:
image -- The image to scroll across.
padding -- If True, the animation will begin with a blank screen and the
input image will scroll into the blank screen one pixel column at a
time. Similarly, after scrolling across the whole input image, the
end of the image will scroll out of a blank screen one column at a
time. If this is not True, then only the input image will be scroll
across without beginning or ending with "whitespace."
(Default = True)
"""
image_list = list()
width = image.size[0]
# Scroll into the blank image.
if padding:
for x in range(8):
section = image.crop((0, 0, x, 16))
display_section = self.create_blank_image()
display_section.paste(section, (8 - x, 0, 8, 16))
image_list.append(display_section)
#Scroll across the input image.
for x in range(8, width + 1):
section = image.crop((x - 8, 0, x, 16))
display_section = self.create_blank_image()
display_section.paste(section, (0, 0, 8, 16))
image_list.append(display_section)
#Scroll out, leaving the blank image.
if padding:
for x in range(width - 7, width + 1):
section = image.crop((x, 0, width, 16))
display_section = self.create_blank_image()
display_section.paste(section, (0, 0, 7 - (x - (width - 7)), 16))
image_list.append(display_section)
#Return the list of images created
return image_list
def vertical_scroll(self, image, padding=True):
"""Returns a list of images which appear to scroll from top to bottom
down the input image when displayed on the LED matrix in order.
The input image is not limited to being 8x16. If the input image is
largerthan this, then all rows will be scrolled through but only the
left-most 8 columns of pixels will be displayed.
Keyword arguments:
image -- The image to scroll down.
padding -- If True, the animation will begin with a blank screen and the
input image will scroll into the blank screen one pixel row at a
time. Similarly, after scrolling down the whole input image, the end
of the image will scroll out of a blank screen one row at a time.
If this is not True, then only the input image will be scroll down
without beginning or ending with "whitespace." (Default = True)
"""
image_list = list()
height = image.size[1]
# Scroll into the blank image.
if padding:
for y in range(16):
section = image.crop((0, 0, 8, y))
display_section = self.create_blank_image()
display_section.paste(section, (0, 8 - y, 8, 16))
image_list.append(display_section)
#Scroll across the input image.
for y in range(16, height + 1):
section = image.crop((0, y - 16, 8, y))
display_section = self.create_blank_image()
display_section.paste(section, (0, 0, 8, 16))
image_list.append(display_section)
#Scroll out, leaving the blank image.
if padding:
for y in range(height - 15, height + 1):
section = image.crop((0, y, 8, height))
display_section = self.create_blank_image()
display_section.paste(section, (0, 0, 8, 7 - (y - (height - 15))))
image_list.append(display_section)
#Return the list of images created
return image_list
def animate(self, images, delay=.25):
"""Displays each of the input images in order, pausing for "delay"
seconds after each image.
Keyword arguments:
image -- An iterable collection of Image objects.
delay -- How many seconds to wait after displaying an image before
displaying the next one. (Default = .25)
"""
for image in images:
# Draw the image on the display buffer.
self.set_image(image)
# Draw the buffer to the display hardware.
self.write_display()
time.sleep(delay)