|
| 1 | +#!/usr/bin/python3 |
| 2 | + |
| 3 | +# Persistence-of-vision (POV) example for Adafruit DotStar RGB LED strip. |
| 4 | +# Loads image, displays column-at-a-time on LEDs at very high speed, |
| 5 | +# suitable for naked-eye illusions. |
| 6 | +# See dotstar_simpletest.py for a much simpler example script. |
| 7 | +# See dotstar_image_paint.py for a slightly simpler light painting example. |
| 8 | +# This code accesses some elements of the dotstar object directly rather |
| 9 | +# than through function calls or setters/getters...this is poor form as it |
| 10 | +# could break easily with future library changes, but is the only way right |
| 11 | +# now to do the POV as quickly as possible. |
| 12 | + |
| 13 | +from PIL import Image |
| 14 | +import board |
| 15 | +import adafruit_dotstar as dotstar |
| 16 | + |
| 17 | +NUMPIXELS = 30 # Length of DotStar strip |
| 18 | +FILENAME = 'hello.png' # Image file to load |
| 19 | +ORDER = dotstar.BGR # Change to GBR for older DotStar strips |
| 20 | + |
| 21 | +# First two arguments in strip declaration identify the clock and data pins |
| 22 | +# (here we're using the hardware SPI pins). |
| 23 | +DOTS = dotstar.DotStar(board.SCK, board.MOSI, NUMPIXELS, auto_write=False, |
| 24 | + brightness=0.25, pixel_order=ORDER) |
| 25 | + |
| 26 | +# Load image in RGB format and get dimensions: |
| 27 | +print('Loading...') |
| 28 | +IMG = Image.open(FILENAME).convert('RGB') |
| 29 | +PIXELS = IMG.load() |
| 30 | +WIDTH = IMG.size[0] |
| 31 | +HEIGHT = IMG.size[1] |
| 32 | +print('%dx%d pixels' % IMG.size) |
| 33 | + |
| 34 | +if HEIGHT > NUMPIXELS: |
| 35 | + HEIGHT = NUMPIXELS |
| 36 | + |
| 37 | +# Calculate gamma correction table, makes mid-range colors look 'right': |
| 38 | +GAMMA = bytearray(256) |
| 39 | +for i in range(256): |
| 40 | + # Notice we access DOTS.brightness directly here...the gamma table will |
| 41 | + # handle any brightness-scaling, so we can set the object brightness back |
| 42 | + # to max and it won't need to perform brightness scaling on every write. |
| 43 | + GAMMA[i] = int(pow(float(i) / 255.0, 2.7) * DOTS.brightness * 255.0 + 0.5) |
| 44 | +DOTS.brightness = 1.0 |
| 45 | + |
| 46 | +# Allocate list of bytearrays, one for each column of image. |
| 47 | +# Each pixel REQUIRES 4 bytes (0xFF, B, G, R). |
| 48 | +print('Allocating...') |
| 49 | +COLUMN = [0 for x in range(WIDTH)] |
| 50 | +for x in range(WIDTH): |
| 51 | + COLUMN[x] = bytearray(HEIGHT * 4) |
| 52 | + |
| 53 | +# Convert entire RGB image into column-wise bytearray list. |
| 54 | +# The dotstar_image_paint.py example uses the library's 'setter' operation |
| 55 | +# for each pixel to do any R/G/B reordering. Because we're preparing data |
| 56 | +# directly for the strip, there's a reference to 'ORDER' here to rearrange |
| 57 | +# the color bytes as needed. |
| 58 | +print('Converting...') |
| 59 | +for x in range(WIDTH): # For each column of image |
| 60 | + for y in range(HEIGHT): # For each pixel in column |
| 61 | + value = PIXELS[x, y] # Read RGB pixel in image |
| 62 | + y4 = y * 4 # Position in raw buffer |
| 63 | + COLUMN[x][y4] = 0xFF # Pixel start marker |
| 64 | + y4 += 1 # Pixel color data start |
| 65 | + COLUMN[x][y4 + ORDER[0]] = GAMMA[value[0]] # Gamma-corrected R |
| 66 | + COLUMN[x][y4 + ORDER[1]] = GAMMA[value[1]] # Gamma-corrected G |
| 67 | + COLUMN[x][y4 + ORDER[2]] = GAMMA[value[2]] # Gamma-corrected B |
| 68 | + |
| 69 | +print('Displaying...') |
| 70 | +while True: # Loop forever |
| 71 | + |
| 72 | + # pylint: disable=protected-access |
| 73 | + # (Really shouldn't access _buf directly, but needed for fastest POV) |
| 74 | + for x in range(WIDTH): # For each column of image... |
| 75 | + DOTS._buf[4:4+HEIGHT*4] = COLUMN[x] # Copy column to DotStar buffer |
| 76 | + DOTS.show() # Send data to strip |
0 commit comments