Added image-frame design

This commit is contained in:
Maximilian Giller 2019-07-12 13:46:50 +02:00
parent 6bda730c61
commit 3309dde202
9 changed files with 205 additions and 15 deletions

2
.gitignore vendored
View file

@ -16,4 +16,6 @@
/Calendar/CalendarEvent.pyc
/Calendar/design_exported_old.png
/Calendar/settings_dev.py
/Calendar/settings_pers.py
/.vscode
/Calendar/images/

View file

@ -47,3 +47,49 @@ colors = {
"fg" : "black",
"bg" : "white"
}
supported_img_formats = [
"BMP",
"DIB",
"EPS",
"GIF",
"ICNS",
"ICO",
"IM",
"JPG",
"JPEG",
"J2K",
"J2P",
"JPX",
"MSP",
"PCX",
"PNG",
"PPM",
"SGI",
"SPI",
"TGA",
"TIFF",
"WEBP",
"XBM",
"BLP",
"CUR",
"DCX",
"DDS",
"FLI",
"FLC",
"FPX",
"FTEX",
"GBR",
"GD",
"IMT",
"IPTC",
"NAA",
"MCIDAS",
"MIC",
"MPO",
"PCD",
"PIXAR",
"PSD",
"WAL",
"XPM",
]

View file

@ -17,7 +17,7 @@ class DesignEntity (object):
def __init_image__ (self, color = colors["bg"]):
rounded_size = (int(self.size[0]),int(self.size[1]))
self.__image__ = Image.new('RGB', rounded_size, color=color)
self.__image__ = Image.new('RGBA', rounded_size, color=color)
def get_image (self):
if self.__finished_image__ is False:

View file

@ -19,6 +19,7 @@ from DayListPanel import DayListPanel
from DayViewPanel import DayViewPanel
from MonthViewPanel import MonthViewPanel
from AgendaListPanel import AgendaListPanel
from ImageFramePanel import ImageFramePanel
import OwmForecasts
import IcalEvents
import RssParserPosts
@ -52,7 +53,8 @@ available_panels = {
"month-overview" : MonthOvPanel,
"day-view" : DayViewPanel,
"agenda-list" : AgendaListPanel,
"month-view" : MonthViewPanel
"month-view" : MonthViewPanel,
"image-frame" : ImageFramePanel
}
loop_timer = LoopTimer(update_interval, run_on_hour=True)

View file

@ -71,7 +71,7 @@ class EpdAdapter (DisplayAdapter):
print('Converting image to data and sending it to the display')
print('This may take a while...' + '\n')
prepared_image = design.get_image().rotate(270, expand=1)
prepared_image = design.get_image().rotate(270, expand=1).convert("RGB")
self.display_frame(self.get_frame_buffer(prepared_image))
# Powering off the E-Paper until the next loop

83
Calendar/ImageDesign.py Normal file
View file

@ -0,0 +1,83 @@
from DesignEntity import DesignEntity
from Assets import path as application_path
from PIL import Image, ExifTags
class ImageDesign (DesignEntity):
"""Creates a TableDesign filled with rss post
date and title"""
def __init__ (self, size, path, fill = "none", color="RGBA", dither=None): # fill: "none" : original size, "stretch" : strech to fill, "scale" : scale to fill, "border" : scale until one side touches border
super(ImageDesign, self).__init__(size)
self.set_path(path)
self.fill = fill
self.color = color
self.dither = dither
def set_path (self, path):
path = path.replace('\\', '/')
if path[0] != '/' and ':' not in path[0:3]:
path = application_path + '/' + path
self.path = path
def __finish_image__ (self):
img = Image.open(self.path)
img = img.convert(self.color, dither=self.dither)
img = self.__fix_orientation__(img)
img = self.__resize_image__(img)
pos = self.__get_centered_position__(img)
self.__init_image__("#00000000")
self.draw(img, pos)
def __resize_image__(self, img):
if self.fill is "none":
return img
if self.fill is "stretch":
img = img.resize(self.size, resample=Image.LANCZOS)
if self.fill is "scale":
size = self.size
img_proportions = img.width / img.height
if img_proportions < size[0] / size[1]:
size = (size[0], int(size[0] * (1 / img_proportions)))
else:
size = (int(size[1] * img_proportions), size[1])
img = img.resize(size, resample=Image.LANCZOS)
if self.fill is "border":
size = self.size
img_proportions = img.width / img.height
if img_proportions < size[0] / size[1]:
size = (int(size[1] * img_proportions), size[1])
else:
size = (size[0], int(size[0] * (1 / img_proportions)))
img = img.resize(size, resample=Image.LANCZOS)
return img
def __get_centered_position__(self, img):
screen_size = self.size
img_size = img.size
delta_size = [s - i for s, i in zip(screen_size, img_size)]
delta_center_pos = [s / 2 for s in delta_size]
return delta_center_pos
def __fix_orientation__(self, img):
if "parsed_exif" not in img.info.keys():
return img
for orientation in ExifTags.TAGS.keys():
if ExifTags.TAGS[orientation]=='Orientation':
break
exif=img.info["parsed_exif"]
if exif[orientation] == 3:
img = img.rotate(180, expand=True)
elif exif[orientation] == 6:
img = img.rotate(270, expand=True)
elif exif[orientation] == 8:
img = img.rotate(90, expand=True)
return img

View file

@ -0,0 +1,58 @@
from PanelDesign import PanelDesign
from settings import general_settings
from Assets import supported_img_formats, path as application_path
from os import listdir
from os.path import isfile, join
from ImageDesign import ImageDesign
from random import choice
class ImageFramePanel (PanelDesign):
"""Converts the display into a digital frame and
shows a slide show of images, iterating on each update"""
def __init__ (self, size):
super(ImageFramePanel, self).__init__(size)
self.overlay_path = self.__complete_path__(general_settings["overlay-image"])
self.image_folder_path = self.__complete_path__(general_settings["image-folder"])
self.images = self.__extract_valid_img_paths__()
self.__first_render__()
def __extract_valid_img_paths__ (self):
images = []
for file in listdir(self.image_folder_path):
file_path = join(self.image_folder_path, file).replace('\\', '/')
if isfile(file_path) and self.overlay_path != file_path:
if file.split('.')[-1].upper() in supported_img_formats:
images.append(file_path)
return images
def __complete_path__(self, path):
path = path.replace('\\', '/')
if path[0] != '/' and ':' not in path[0:3]:
path = join(application_path, path)
return path
def __first_render__(self):
current_image = choice(self.images)
img = ImageDesign(self.size, current_image, fill="scale", color="1")
self.draw_design(img)
if self.overlay_path != "":
overlay = ImageDesign(self.size, self.overlay_path)
overlay.__finish_image__()
self.__image__.alpha_composite(overlay.__image__)
def add_weather (self, weather):
pass
def add_calendar (self, calendar):
pass
def add_rssfeed (self, rss):
pass
def add_crypto (self, crypto):
pass
def add_tasks (self, tasks):
pass

View file

@ -1,26 +1,20 @@
""" To quickly get started, fill in the following details:"""
ical_urls = [
"https://calendar.google.com/calendar/ical/en.usa%23holiday%40group.v.calendar.google.com/public/basic.ics"
]
highlighted_ical_urls = [
]
rss_feeds = [
"http://feeds.bbci.co.uk/news/world/rss.xml#"
]
crypto_coins = [
"bitcoin",
"litecoin",
"ethereum",
"binancecoin"
]
api_key = ""
owm_paid_subscription = False
location = "Julich, DE"
location = "Berlin, DE"
week_starts_on = "Monday"
display_colours = "bwr"
language = "en"
@ -34,11 +28,13 @@ update_interval = 60
font_size = 14 # does not affect every text
font_boldness = "semibold" # extralight, light, regular, semibold, bold, extrabold
line_thickness = 1 # 1-3 Thickness advised
choosen_design = "month-overview" # month-overview, day-list, day-view, agenda-list, month-view
choosen_design = "month-overview" # month-overview, day-list, day-view, agenda-list, month-view, image-frame
general_settings = { # General settings that designs may use
"info-area" : "rss", # empty, events, rss, crypto
"highlight-event-days" : True,
"weather-info" : True
"weather-info" : True,
"image-folder" : "",
"overlay-image" : "" # Size must be 384x640px with default display
}

View file

@ -2,7 +2,7 @@
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/0962be8b02e947e9aa4326e73b387e01)](https://app.codacy.com/app/m.giller.dev/E-Paper-Calendar?utm_source=github.com&utm_medium=referral&utm_content=mgfcf/E-Paper-Calendar&utm_campaign=Badge_Grade_Dashboard)
This is a software written in python3 that allows you to transform an E-Paper display (like the kindle) into an information display. It fetches live data from Openweathermap (a weather info provider), rss-feeds and your Online Calendar (Google/Yahoo Calendar/...) and displays them on a large, beautiful and ultra-low power E-Paper display. It's ideal for staying organised and keeping track of important details without having to check them up online.
This is a software written in python3 that allows you to transform an E-Paper display (like the kindle) into an information display. It fetches live data from Openweathermap (a weather info provider), rss-feeds and your Online Calendar (Google/Yahoo Calendar/...) and displays them on a large, beautiful and ultra-low power E-Paper display. It's ideal for staying organised and keeping track of important details without having to check them up online. It can also be used as an image frame.
This software fully supports the 3-Colour **and** 2-Colour version of the 7.5" E-Paper display from waveshare/gooddisplay and works with Raspberry Pi 2, 3 and 0 (Zero, Zero W, Zero WH).
@ -27,6 +27,7 @@ This software fully supports the 3-Colour **and** 2-Colour version of the 7.5" E
* Optionally get RSS-Feed fetched and shown
* Syncronise events from any online calendar (like google, yahoo, etc.)
* Get live weather data (including temperature, humidity, etc.) using openweathermap api
* Only show a slideshow of images
## Hardware required
* 7.5" 3-Colour E-Paper Display (Black, White, Red/Yellow) with driver hat from [waveshare](https://www.waveshare.com/product/7.5inch-e-paper-hat-b.htm)
@ -92,6 +93,8 @@ Once the packages are installed, navigate to the home directory, open 'E-Paper-M
| `"info-area"` | Defines the content type of an additionaly info area on the design. Can be one of `"rss"`, `"events"` or empty, to remove this area or keep it clean. |
| `"highlight-event-days"` | If set to `True`, days with events are highlighted in contrast to days without events. |
| `"weather-info"` | If set to `False`, weather info areas disappear and make room for events/rss/etc. (depends on the design). |
| `"image-folder"` | Set a relative or absolute path to a folder containing images that you want to see fullscreen with the `"image-frame"` design activated. |
| `"overlay-image"` | Set a relative or absolute path to an image with the same size as the screen (default: 384x640px) to show some static information over every image shown in the `"image-frame"` design. If the overlay image is contained within the `"image-folder"`, it will not be included into the slideshow. |
### Debug
| Parameter | Description |