<gh_stars>0
#!/usr/bin/python3

# Persistence-of-vision (POV) example for Adafruit DotStar RGB LED strip.
# Loads image, displays column-at-a-time on LEDs at very high speed,
# suitable for naked-eye illusions.
# See dotstar_simpletest.py for a much simpler example script.
# See dotstar_image_paint.py for a slightly simpler light painting example.
# This code accesses some elements of the dotstar object directly rather
# than through function calls or setters/getters...this is poor form as it
# could break easily with future library changes, but is the only way right
# now to do the POV as quickly as possible.

import board
from PIL import Image
import adafruit_dotstar as dotstar

NUMPIXELS = 30         # Length of DotStar strip
FILENAME = 'hello.png' # Image file to load
ORDER = dotstar.BGR    # Change to GBR for older DotStar strips

# First two arguments in strip declaration identify the clock and data pins
# (here we're using the hardware SPI pins).
DOTS = dotstar.DotStar(board.SCK, board.MOSI, NUMPIXELS, auto_write=False,
                       brightness=0.25, pixel_order=ORDER)

# Load image in RGB format and get dimensions:
print('Loading...')
IMG = Image.open(FILENAME).convert('RGB')
PIXELS = IMG.load()
WIDTH = IMG.size[0]
HEIGHT = IMG.size[1]
print('%dx%d pixels' % IMG.size)

if HEIGHT > NUMPIXELS:
    HEIGHT = NUMPIXELS

# Calculate gamma correction table, makes mid-range colors look 'right':
GAMMA = bytearray(256)
for i in range(256):
    # Notice we access DOTS.brightness directly here...the gamma table will
    # handle any brightness-scaling, so we can set the object brightness back
    # to max and it won't need to perform brightness scaling on every write.
    GAMMA[i] = int(pow(float(i) / 255.0, 2.7) * DOTS.brightness * 255.0 + 0.5)
DOTS.brightness = 1.0

# Allocate list of bytearrays, one for each column of image.
# Each pixel REQUIRES 4 bytes (0xFF, B, G, R).
print('Allocating...')
COLUMN = [0 for x in range(WIDTH)]
for x in range(WIDTH):
    COLUMN[x] = bytearray(HEIGHT * 4)

# Convert entire RGB image into column-wise bytearray list.
# The dotstar_image_paint.py example uses the library's 'setter' operation
# for each pixel to do any R/G/B reordering.  Because we're preparing data
# directly for the strip, there's a reference to 'ORDER' here to rearrange
# the color bytes as needed.
print('Converting...')
for x in range(WIDTH):                             # For each column of image
    for y in range(HEIGHT):                        # For each pixel in column
        value = PIXELS[x, y]                       # Read RGB pixel in image
        y4 = y * 4                                 # Position in raw buffer
        COLUMN[x][y4] = 0xFF                       # Pixel start marker
        y4 += 1                                    # Pixel color data start
        COLUMN[x][y4 + ORDER[0]] = GAMMA[value[0]] # Gamma-corrected R
        COLUMN[x][y4 + ORDER[1]] = GAMMA[value[1]] # Gamma-corrected G
        COLUMN[x][y4 + ORDER[2]] = GAMMA[value[2]] # Gamma-corrected B

print('Displaying...')
while True:                                 # Loop forever

    # pylint: disable=protected-access
    # (Really shouldn't access _buf directly, but needed for fastest POV)
    for x in range(WIDTH):                  # For each column of image...
        DOTS._buf[4:4+HEIGHT*4] = COLUMN[x] # Copy column to DotStar buffer
        DOTS.show()                         # Send data to strip
