Allow usage without display and SPI when setting render->False

Generated images will be available in the images folder
This commit is contained in:
aceisace 2022-03-31 18:36:50 +02:00
parent cd02d2fbab
commit f10fe8a988
2 changed files with 705 additions and 711 deletions

View File

@ -10,210 +10,210 @@ from PIL import Image
from inkycal.custom import top_level from inkycal.custom import top_level
import glob import glob
class Display: class Display:
"""Display class for inkycal """Display class for inkycal
Creates an instance of the driver for the selected E-Paper model and allows Creates an instance of the driver for the selected E-Paper model and allows
rendering images and calibrating the E-Paper display rendering images and calibrating the E-Paper display
args: args:
- epaper_model: The name of your E-Paper model. - epaper_model: The name of your E-Paper model.
"""
def __init__(self, epaper_model):
"""Load the drivers for this epaper model"""
if 'colour' in epaper_model:
self.supports_colour = True
else:
self.supports_colour = False
try:
driver_path = f'inkycal.display.drivers.{epaper_model}'
driver = import_module(driver_path)
self._epaper = driver.EPD()
self.model_name = epaper_model
except ImportError:
raise Exception('This module is not supported. Check your spellings?')
except FileNotFoundError:
raise Exception('SPI could not be found. Please check if SPI is enabled')
def render(self, im_black, im_colour = None):
"""Renders an image on the selected E-Paper display.
Initlializes the E-Paper display, sends image data and executes command
to update the display.
Args:
- im_black: The image for the black-pixels. Anything in this image that is
black is rendered as black on the display. This is required and ideally
should be a black-white image.
- im_colour: For E-Paper displays supporting colour, a separate image,
ideally black-white is required for the coloured pixels. Anything that is
black in this image will show up as either red/yellow.
Rendering an image for black-white E-Paper displays:
>>> sample_image = PIL.Image.open('path/to/file.png')
>>> display = Display('my_black_white_display')
>>> display.render(sample_image)
Rendering black-white on coloured E-Paper displays:
>>> sample_image = PIL.Image.open('path/to/file.png')
>>> display = Display('my_coloured_display')
>>> display.render(sample_image, sample_image)
Rendering coloured image where 2 images are available:
>>> black_image = PIL.Image.open('path/to/file.png') # black pixels
>>> colour_image = PIL.Image.open('path/to/file.png') # coloured pixels
>>> display = Display('my_coloured_display')
>>> display.render(black_image, colour_image)
""" """
epaper = self._epaper def __init__(self, epaper_model):
"""Load the drivers for this epaper model"""
if self.supports_colour == False: if 'colour' in epaper_model:
print('Initialising..', end = '') self.supports_colour = True
epaper.init() else:
print('Updating display......', end = '') self.supports_colour = False
epaper.display(epaper.getbuffer(im_black))
print('Done')
elif self.supports_colour == True: try:
if not im_colour: driver_path = f'inkycal.display.drivers.{epaper_model}'
raise Exception('im_colour is required for coloured epaper displays') driver = import_module(driver_path)
print('Initialising..', end = '') self._epaper = driver.EPD()
epaper.init() self.model_name = epaper_model
print('Updating display......', end = '')
epaper.display(epaper.getbuffer(im_black), epaper.getbuffer(im_colour))
print('Done')
print('Sending E-Paper to deep sleep...', end = '') except ImportError:
epaper.sleep() raise Exception('This module is not supported. Check your spellings?')
print('Done')
def calibrate(self, cycles=3): except FileNotFoundError:
"""Calibrates the display to retain crisp colours raise Exception('SPI could not be found. Please check if SPI is enabled')
Flushes the selected display several times with it's supported colours, def render(self, im_black, im_colour=None):
removing any previous effects of ghosting. """Renders an image on the selected E-Paper display.
Args: Initlializes the E-Paper display, sends image data and executes command
- cycles: -> int. The number of times to flush the display with it's to update the display.
supported colours.
It's recommended to calibrate the display after every 6 display updates Args:
for best results. For black-white only displays, calibration is less - im_black: The image for the black-pixels. Anything in this image that is
critical, but not calibrating regularly results in grey-ish text. black is rendered as black on the display. This is required and ideally
should be a black-white image.
Please note that calibration takes a while to complete. 3 cycles may - im_colour: For E-Paper displays supporting colour, a separate image,
take 10 mins on black-white E-Papers while it takes 20 minutes on coloured ideally black-white is required for the coloured pixels. Anything that is
E-Paper displays. black in this image will show up as either red/yellow.
"""
epaper = self._epaper Rendering an image for black-white E-Paper displays:
epaper.init()
display_size = self.get_display_size(self.model_name) >>> sample_image = PIL.Image.open('path/to/file.png')
>>> display = Display('my_black_white_display')
white = Image.new('1', display_size, 'white') >>> display.render(sample_image)
black = Image.new('1', display_size, 'black')
print('----------Started calibration of ePaper display----------')
if self.supports_colour == True:
for _ in range(cycles):
print('Calibrating...', end= ' ')
print('black...', end= ' ')
epaper.display(epaper.getbuffer(black), epaper.getbuffer(white))
print('colour...', end = ' ')
epaper.display(epaper.getbuffer(white), epaper.getbuffer(black))
print('white...')
epaper.display(epaper.getbuffer(white), epaper.getbuffer(white))
print(f'Cycle {_+1} of {cycles} complete')
if self.supports_colour == False:
for _ in range(cycles):
print('Calibrating...', end= ' ')
print('black...', end = ' ')
epaper.display(epaper.getbuffer(black))
print('white...')
epaper.display(epaper.getbuffer(white)),
print(f'Cycle {_+1} of {cycles} complete')
print('-----------Calibration complete----------')
epaper.sleep()
@classmethod Rendering black-white on coloured E-Paper displays:
def get_display_size(cls, model_name):
"""Returns the size of the display as a tuple -> (width, height)
Looks inside drivers folder for the given model name, then returns it's >>> sample_image = PIL.Image.open('path/to/file.png')
size. >>> display = Display('my_coloured_display')
>>> display.render(sample_image, sample_image)
Args:
- model_name: str -> The name of the E-Paper display to get it's size.
Returns: Rendering coloured image where 2 images are available:
(width, height) ->tuple, showing the size of the display
You can use this function directly without creating the Display class: >>> black_image = PIL.Image.open('path/to/file.png') # black pixels
>>> colour_image = PIL.Image.open('path/to/file.png') # coloured pixels
>>> display = Display('my_coloured_display')
>>> display.render(black_image, colour_image)
"""
>>> Display.get_display_size('model_name') epaper = self._epaper
"""
if not isinstance(model_name, str):
print('model_name should be a string')
return
else:
driver_files = top_level+'/inkycal/display/drivers/*.py'
drivers = glob.glob(driver_files)
drivers = [i.split('/')[-1].split('.')[0] for i in drivers]
drivers.remove('__init__')
drivers.remove('epdconfig')
if model_name not in drivers:
print('This model name was not found. Please double check your spellings')
return
else:
with open(top_level+'/inkycal/display/drivers/'+model_name+'.py') as file:
for line in file:
if 'EPD_WIDTH=' in line.replace(" ", ""):
width = int(line.rstrip().replace(" ", "").split('=')[-1])
if 'EPD_HEIGHT=' in line.replace(" ", ""):
height = int(line.rstrip().replace(" ", "").split('=')[-1])
return width, height
@classmethod if not self.supports_colour:
def get_display_names(cls): print('Initialising..', end='')
"""Prints all supported E-Paper models. epaper.init()
print('Updating display......', end='')
epaper.display(epaper.getbuffer(im_black))
print('Done')
Fetches all filenames in driver folder and prints them on the console. elif self.supports_colour:
if not im_colour:
raise Exception('im_colour is required for coloured epaper displays')
print('Initialising..', end='')
epaper.init()
print('Updating display......', end='')
epaper.display(epaper.getbuffer(im_black), epaper.getbuffer(im_colour))
print('Done')
Returns: print('Sending E-Paper to deep sleep...', end='')
Printed version of all supported Displays. epaper.sleep()
print('Done')
Use one of the models to intilialize the Display class in order to gain def calibrate(self, cycles=3):
access to the E-Paper. """Calibrates the display to retain crisp colours
You can use this function directly without creating the Display class: Flushes the selected display several times with it's supported colours,
removing any previous effects of ghosting.
Args:
- cycles: -> int. The number of times to flush the display with it's
supported colours.
It's recommended to calibrate the display after every 6 display updates
for best results. For black-white only displays, calibration is less
critical, but not calibrating regularly results in grey-ish text.
Please note that calibration takes a while to complete. 3 cycles may
take 10 minutes on black-white E-Papers while it takes 20 minutes on coloured
E-Paper displays.
"""
epaper = self._epaper
epaper.init()
display_size = self.get_display_size(self.model_name)
white = Image.new('1', display_size, 'white')
black = Image.new('1', display_size, 'black')
print('----------Started calibration of ePaper display----------')
if self.supports_colour:
for _ in range(cycles):
print('Calibrating...', end=' ')
print('black...', end=' ')
epaper.display(epaper.getbuffer(black), epaper.getbuffer(white))
print('colour...', end=' ')
epaper.display(epaper.getbuffer(white), epaper.getbuffer(black))
print('white...')
epaper.display(epaper.getbuffer(white), epaper.getbuffer(white))
print(f'Cycle {_ + 1} of {cycles} complete')
if not self.supports_colour:
for _ in range(cycles):
print('Calibrating...', end=' ')
print('black...', end=' ')
epaper.display(epaper.getbuffer(black))
print('white...')
epaper.display(epaper.getbuffer(white)),
print(f'Cycle {_ + 1} of {cycles} complete')
print('-----------Calibration complete----------')
epaper.sleep()
@classmethod
def get_display_size(cls, model_name):
"""Returns the size of the display as a tuple -> (width, height)
Looks inside "drivers" folder for the given model name, then returns it's
size.
Args:
- model_name: str -> The name of the E-Paper display to get it's size.
Returns:
(width, height) ->tuple, showing the size of the display
You can use this function directly without creating the Display class:
>>> Display.get_display_size('model_name')
"""
if not isinstance(model_name, str):
print('model_name should be a string')
return
else:
driver_files = top_level + '/inkycal/display/drivers/*.py'
drivers = glob.glob(driver_files)
drivers = [i.split('/')[-1].split('.')[0] for i in drivers]
drivers.remove('__init__')
drivers.remove('epdconfig')
if model_name not in drivers:
print('This model name was not found. Please double check your spellings')
return
else:
with open(top_level + '/inkycal/display/drivers/' + model_name + '.py') as file:
for line in file:
if 'EPD_WIDTH=' in line.replace(" ", ""):
width = int(line.rstrip().replace(" ", "").split('=')[-1])
if 'EPD_HEIGHT=' in line.replace(" ", ""):
height = int(line.rstrip().replace(" ", "").split('=')[-1])
return width, height
@classmethod
def get_display_names(cls):
"""Prints all supported E-Paper models.
Fetches all filenames in driver folder and prints them on the console.
Returns:
Printed version of all supported Displays.
Use one of the models to intilialize the Display class in order to gain
access to the E-Paper.
You can use this function directly without creating the Display class:
>>> Display.get_display_names()
"""
driver_files = top_level + '/inkycal/display/drivers/*.py'
drivers = glob.glob(driver_files)
drivers = [i.split('/')[-1].split('.')[0] for i in drivers]
drivers.remove('__init__')
drivers.remove('epdconfig')
print(*drivers, sep='\n')
>>> Display.get_display_names()
"""
driver_files = top_level+'/inkycal/display/drivers/*.py'
drivers = glob.glob(driver_files)
drivers = [i.split('/')[-1].split('.')[0] for i in drivers]
drivers.remove('__init__')
drivers.remove('epdconfig')
print(*drivers, sep='\n')
if __name__ == '__main__': if __name__ == '__main__':
print("Running Display class in standalone mode") print("Running Display class in standalone mode")

File diff suppressed because it is too large Load Diff