# Credits:
# https://github.com/adafruit/Adafruit_CircuitPython_EPD/blob/master/examples/epd_bitmap.py
# https://badge.team/files/21364

import os
import display

FILENAME = "picture.bmp"

def display_error(message):
	with display.open() as d:
		d.clear().print(message).update()


class BMPError(Exception):
	def __init__(self, message):
		super().__init__(message)
		display_error(message)


class BMP:
	def __init__(self, filename, disp, flip=True):
		try:
			with open(filename, "rb") as f:
				# Read and check magic numbers
				if f.read(2) != b"BM":
					raise BMPError("Invalid bitmap file")

				file_size = self.read_le(f.read(4))
				f.read(4) # Read & ignore creator bytes

				self.image_offset = self.read_le(f.read(4)) # Start of image data
				header_size = self.read_le(f.read(4))
				self.width = self.read_le(f.read(4))
				self.height = self.read_le(f.read(4))
				self.flip = flip

				print(
					"Size: {}\nImage offset: {}\nHeader size: {}".format(
						file_size, self.image_offset, header_size
					)
				)
				print("Width: {}\nHeight: {}".format(self.width, self.height))

				if self.read_le(f.read(2)) != 1:
					raise BMPError("Not singleplane")

				depth = self.read_le(f.read(2)) # bits per pixel

				print("Bit depth: {}".format(depth))

				if depth != 24:
					raise BMPError("BMP is not 24-bit")

				if self.read_le(f.read(2)) != 0:
					raise BMPError("Compressed file (unsupported)")

				print("Image OK")

				self.row_size = (self.width * 3 + 3) & ~3 # 32-bit line boundary
		except OSError:
			display_error("Couldn't open file '{}'".format(filename))
			return

		print("Loading...")
		disp.print("Loading...", font=display.FONT12)
		disp.update()

		with open(filename, "rb") as f:
			for y in range(self.height):
				if self.flip: # Bitmap is stored bottom-to-top order (normal BMP)
					pos = self.image_offset + (self.height - 1 - y) * self.row_size
				else:
					pos = self.image_offset + y * self.row_size

				f.seek(pos)

				for x in range(self.width):
					pixel = [f.read(1), f.read(1), f.read(1)]
					pixel = [int.from_bytes(n, "little") for n in pixel]
					disp.pixel(x, y, col=pixel[::-1]) # Colors are in BGR format

		print("Done.")

	def read_le(self, b):
		return int.from_bytes(b, "little")


if __name__ == "__main__":
	d = display.open()

	d.clear()
	BMP(FILENAME, d)
	d.update()
	d.close()