/ examples / epd_bitmap.py
epd_bitmap.py
  1  import digitalio
  2  import busio
  3  import board
  4  from adafruit_epd.epd import Adafruit_EPD
  5  from adafruit_epd.il0373 import Adafruit_IL0373
  6  from adafruit_epd.il91874 import Adafruit_IL91874  # pylint: disable=unused-import
  7  from adafruit_epd.il0398 import Adafruit_IL0398  # pylint: disable=unused-import
  8  from adafruit_epd.ssd1608 import Adafruit_SSD1608  # pylint: disable=unused-import
  9  from adafruit_epd.ssd1675 import Adafruit_SSD1675  # pylint: disable=unused-import
 10  
 11  
 12  # create the spi device and pins we will need
 13  spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
 14  ecs = digitalio.DigitalInOut(board.D10)
 15  dc = digitalio.DigitalInOut(board.D9)
 16  srcs = digitalio.DigitalInOut(board.D7)  # can be None to use internal memory
 17  rst = digitalio.DigitalInOut(board.D11)  # can be None to not use this pin
 18  busy = digitalio.DigitalInOut(board.D12)  # can be None to not use this pin
 19  
 20  # give them all to our driver
 21  print("Creating display")
 22  # display = Adafruit_SSD1608(200, 200, spi,        # 1.54" HD mono display
 23  # display = Adafruit_SSD1675(122, 250, spi,        # 2.13" HD mono display
 24  # display = Adafruit_IL91874(176, 264, spi,        # 2.7" Tri-color display
 25  # display = Adafruit_IL0373(152, 152, spi,         # 1.54" Tri-color display
 26  # display = Adafruit_IL0373(128, 296, spi,         # 2.9" Tri-color display
 27  # display = Adafruit_IL0398(400, 300, spi,         # 4.2" Tri-color display
 28  display = Adafruit_IL0373(
 29      104,
 30      212,
 31      spi,  # 2.13" Tri-color display
 32      cs_pin=ecs,
 33      dc_pin=dc,
 34      sramcs_pin=srcs,
 35      rst_pin=rst,
 36      busy_pin=busy,
 37  )
 38  
 39  # IF YOU HAVE A FLEXIBLE DISPLAY (2.13" or 2.9") uncomment these lines!
 40  # display.set_black_buffer(1, False)
 41  # display.set_color_buffer(1, False)
 42  
 43  display.rotation = 0
 44  
 45  FILENAME = "blinka154mono.bmp"
 46  
 47  
 48  def read_le(s):
 49      # as of this writting, int.from_bytes does not have LE support, DIY!
 50      result = 0
 51      shift = 0
 52      for byte in bytearray(s):
 53          result += byte << shift
 54          shift += 8
 55      return result
 56  
 57  
 58  class BMPError(Exception):
 59      pass
 60  
 61  
 62  def display_bitmap(epd, filename):  # pylint: disable=too-many-locals, too-many-branches
 63      try:
 64          f = open("/" + filename, "rb")
 65      except OSError:
 66          print("Couldn't open file")
 67          return
 68  
 69      print("File opened")
 70      try:
 71          if f.read(2) != b"BM":  # check signature
 72              raise BMPError("Not BitMap file")
 73  
 74          bmpFileSize = read_le(f.read(4))
 75          f.read(4)  # Read & ignore creator bytes
 76  
 77          bmpImageoffset = read_le(f.read(4))  # Start of image data
 78          headerSize = read_le(f.read(4))
 79          bmpWidth = read_le(f.read(4))
 80          bmpHeight = read_le(f.read(4))
 81          flip = True
 82  
 83          print(
 84              "Size: %d\nImage offset: %d\nHeader size: %d"
 85              % (bmpFileSize, bmpImageoffset, headerSize)
 86          )
 87          print("Width: %d\nHeight: %d" % (bmpWidth, bmpHeight))
 88  
 89          if read_le(f.read(2)) != 1:
 90              raise BMPError("Not singleplane")
 91          bmpDepth = read_le(f.read(2))  # bits per pixel
 92          print("Bit depth: %d" % (bmpDepth))
 93          if bmpDepth != 24:
 94              raise BMPError("Not 24-bit")
 95          if read_le(f.read(2)) != 0:
 96              raise BMPError("Compressed file")
 97  
 98          print("Image OK! Drawing...")
 99  
100          rowSize = (bmpWidth * 3 + 3) & ~3  # 32-bit line boundary
101  
102          for row in range(bmpHeight):  # For each scanline...
103              if flip:  # Bitmap is stored bottom-to-top order (normal BMP)
104                  pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize
105              else:  # Bitmap is stored top-to-bottom
106                  pos = bmpImageoffset + row * rowSize
107  
108              # print ("seek to %d" % pos)
109              f.seek(pos)
110              rowdata = f.read(3 * bmpWidth)
111              for col in range(bmpWidth):
112                  b, g, r = rowdata[3 * col : 3 * col + 3]  # BMP files store RGB in BGR
113                  if r < 0x80 and g < 0x80 and b < 0x80:
114                      epd.pixel(col, row, Adafruit_EPD.BLACK)
115                  elif r >= 0x80 and g >= 0x80 and b >= 0x80:
116                      pass  # epd.pixel(row, col, Adafruit_EPD.WHITE)
117                  elif r >= 0x80:
118                      epd.pixel(col, row, Adafruit_EPD.RED)
119      except OSError:
120          print("Couldn't read file")
121      except BMPError as e:
122          print("Failed to parse BMP: " + e.args[0])
123      finally:
124          f.close()
125      print("Finished drawing")
126  
127  
128  # clear the buffer
129  display.fill(Adafruit_EPD.WHITE)
130  display_bitmap(display, FILENAME)
131  display.display()