robweber / omni-epd

An EPD (electronic paper display) class abstraction to simplify communications across multiple display types.
GNU General Public License v3.0
77 stars 16 forks source link

Waveshare 3 Ink displays #7

Closed robweber closed 3 years ago

robweber commented 3 years ago

Per @missionfloyd the library currently won't handle Waveshare's 3 ink displays as they require 2 Image objects passed to the display() function in the Waveshare library.

https://github.com/TomWhitwell/SlowMovie/pull/64#issuecomment-824383451

robweber commented 3 years ago

After examining the waveshare code a bit more passing in None for the second image to display b/w only seems like a fairly simple option. Probably best way to handle these for now.

If utilizing the second color is something to support the following steps could probably be used:

  1. perform a P mode transformation on the image to get it down to 3 colors, can use existing image enhancements for this as part of _applyConfig()
  2. Use getcolors() from the Pillow library to identify what 3 colors were used in the transform
  3. Within the _display() method do a second palette filter to separate colors 1+2 and colors 1+3 into separate images. This would correspond to the black image and red image vars the EPD expects.
  4. pass these to display(im1,im2) in the waveshare lib

Without a display to test this on it's hard to say if this would be successful.

robweber commented 3 years ago

This got way more complicated than I expected - apparently there is a lot of variation in the different waveshare classes. Oddly a lot of places where there doesn't even need to be; things like function names being different for no reason or basically the same arg being different between devices.

In any case #8 is my attempt at consolidating it all into something workable. @missionfloyd please take a look and see if this helps with the issues you found. Definitely more work to be done here in terms of allowing access to advanced params but this gets the basics knocked out.

missionfloyd commented 3 years ago

I don't have a 3 color display either, so I can't test it.

robweber commented 3 years ago

Thanks for the feedback, I can make the adjustments tomorrow. I found some example digging on Github of passing the blank image to the 3 color display drivers so I'm assuming that's what's working for people when they don't need the third color. I'm hesitant to implement anything more substantial without hardware to test. I think this will get the bulk of the waveshare devices working, at least for B/W images like we're targeting.

missionfloyd commented 3 years ago

Some of the waveshare drivers (the ones that people have optimized) use the array of zeroes to clear the screen.

I've been messing with pillow, with okay results. out2

from PIL import Image

pal_img = Image.new('P', (1, 1))
pal_img.putpalette((0, 0, 0, 255, 0, 0, 255, 255, 255) + (0,0,0)*253)
img = Image.open("frame.bmp")
img_3color = img.quantize(palette=pal_img)

Then what pimoroni does is use numpy to split the image into the black and red layers.

Edit: I think I've figured it out, using only pillow. All it takes is swapping the palette.

from PIL import Image

pal_img = Image.new('P', (1, 1))
pal_img.putpalette((0, 0, 0, 255, 0, 0, 255, 255, 255) + (0,0,0)*253)
img = Image.open("frame.bmp")
img_3color = img.quantize(palette=pal_img)

img_red = img_3color.copy()
img_red.putpalette((255, 255, 255, 0, 0, 0, 255, 255, 255) + (0,0,0)*253)

img_black = img_3color.copy()
img_black.putpalette((0, 0, 0, 255, 255, 255, 255, 255, 255) + (0,0,0)*253)

img_black black

img_red red

robweber commented 3 years ago

That's awesome. I'm going to leave this open but merge in #8 soon. That will give us b/w and fix issues with most of the waveshare drivers. Then we can layer this in to add the third color for displays that support it via another PR.

Really cool work on this.

robweber commented 3 years ago

12 is merged - should close this out.