helgeerbe / picframe

Picture frame viewer for raspi, controlled via mqtt and automatticly integrated as mqtt device in homeassistant.
MIT License
98 stars 28 forks source link

Transparent Matting #291

Open Rob-Chill opened 1 year ago

Rob-Chill commented 1 year ago

Hey guys,

i wonder if anyone can help me with my issue (feature). I use a self-made picture frame with an Raspberry pi 2 Zero W and PI3D and Picture Frame with following versions:

INFO:start.py:starting ['/usr/local/bin/picframe', '-v'] picframe version: 2022.06.03

Checking required packages...... PIL : 9.3.0 exifread : 2.3.2 pi3d : 2.49 yaml : 6.0 paho.mqtt : 1.6.1 iptcinfo3 : 2.1.4 numpy : 1.16.2 ninepatch : installed, but no version info

Checking optional packages...... pyheif : Not found!

For all of my pictures I use the matting function of the picframe phython program. Therefore I use Outter matting with texture and inner matting without texture. My wish is to use pictures with a frame (for example see following picture)

mat_texture1

For now I have to convert this picture to black an white, because there is no transparency for the matting texture (outer_mat_color: [R, G, B]). If I use for example outer_mat_color: [126, 190, 190] with mint green the outer frame shows the picture in mint green but, too dark. So with the converting in black and white like the next picture, it shows the configurated colour. mat_texture So at the moment there is just an overlay of the actual configurated colour for the outer matting frame.

My question is, if there is any possibility to use coloured pictures as frame matting texture or is it somehow possible to set the outer matting into transparent?

I hope you can help me, thank you in advance!

Rob

here my configuration.yaml

viewer: blur_amount: 12 # default=12, larger values than 12 will increase processing load quite a bit blur_zoom: 1.0 # default=1.0, must be >= 1.0 which expands the backgorund to just fill the space around the image blur_edges: False # default=False, use blurred version of image to fill edges - will override FIT = False edge_alpha: 1.0 # default=0.5, background colour at edge. 1.0 would show reflection of image fps: 20.0 # default=20.0 background: [0, 0, 0, 1.0] # default=[0.2, 0.2, 0.3, 1.0], RGBA to fill edges when fitting blend_type: "blend" # default="blend", choices={"blend", "burn", "bump"}, type of blend the shader can do font_file: "/home/pi/picframe_data/data/fonts/NotoSans-Regular.ttf" shader: "/home/pi/picframe_data/data/shaders/blend_new" show_text_fm: "%b %d, %Y" # default "%b %d, %Y", format to show date over the image show_text_tm: 20.0 # default=20.0, time to show text over image with file name show_text_sz: 40 # default=40, text character size show_text: "" # default="title caption name date folder location", show text, include combination of words: title, caption name, date, location, folder text_justify: "L" # text justification L, C or R text_bkg_hgt: 0.25 # default=0.25 (0.0-1.0), percentage of screen height for text background texture text_opacity: 1.0 # default=1.0 (0.0-1.0), alpha value of text overlay fit: True # default=False, True => scale image so all visible and leave 'gaps'

False => crop image so no 'gaps'

kenburns: False # default=False, will set fit->False and blur_edges->False display_x: 0 # offset from left of screen (can be negative) display_y: 0 # offset from top of screen (can be negative) display_w: null # width of display surface (null->None will use max returned by hardware) display_h: null # height of display surface use_glx: False # default=False. Set to True on linux with xserver running

mat_images: True # default=0.01, True, automatically mat all images. False, don't automatically mat any images. Real value, auto-mat all images with aspect ratio difference > than value mat_type: null outer_mat_color: [126, 190, 190] # mint green inner_mat_color: [40, 81, 81] # dark green mat_resource_folder: "/home/pi/picframe_data/data/mat/mat_version_white_lines_green" outer_mat_border: 40 # default=75, Minimum outer mat border in pixels outer_mat_use_texture: True # default=True, True uses a texture for the outer mat. False creates a solid-color outer mat. inner_mat_border: 15 # default=40, Minimum inner mat border in pixels (for styles that use it) inner_mat_use_texture: False # default=False, True uses a texture for the inner mat. False creates a solid-color inner mat.

show_clock: False # default=False, True shows clock overlay. False does not show clock overlay clock_justify: "C" # default="R", clock justification L, C, or R clock_text_sz: 40 # default=120, clock character size clock_format: "%I:%M" # default="%I:%M", strftime format for clock string clock_format: "\n%Y-%m-%d %A %H:%M Uhr"

clock_opacity: 1.0 # default=1.0 (0.0-1.0), alpha value of clock overlay

menu_text_sz: 40 # default=40, menu character size menu_autohide_tm: 10.0 # default=10.0, time in seconds to show menu before auto hiding (0 disables auto hiding) geo_suppress_list: [] # default=None, substrings to remove from the location text

model: pic_dir: "/home/pi/Pictures/Maximilian" # default="/home/pi/Pictures", root folder for images deleted_pictures: "/home/pi/DeletedPictures" # move deleted pictures here follow_links: False # default=False, By default, picframe will not walk down into symbolic links that resolve to directories. Set follow_links to True to visit directories pointed to by symlinks, on systems that support them. no_files_img: "/home/pi/picframe_data/data/no_pictures.jpg" # default="PictureFrame2020img.jpg", image to show if none selected subdirectory: "" # default="", subdir of pic_dir - can be changed by MQTT" recent_n: 0 # default=7 (days), when shuffling file change date more recent than this number of days play before the rest reshuffle_num: 1 # default=1, times through before reshuffling time_delay: 100.0 # default=200.0, time between consecutive slide starts - can be changed by MQTT fade_time: 20.0 # default=10.0, change time during which slides overlap - can be changed by MQTT" shuffle: True # default=True, shuffle on reloading image files - can be changed by MQTT" sort_cols: 'fname ASC' # default='fname ASC' can be any columns in the table with optional ASC or DESC separated by commas

fname, last_modified, file_id, orientation, exif_datetime, f_number,

                                      # exposure_time, iso, focal_length, make, model, lens, rating,
                                      # latitude, longitude, width, height, title, caption, tags,
                                      # is_portrait, location

image_attr: [ # image attributes send by MQTT, Keys are taken from exifread library, "PICFRAME GPS" is special to retrieve GPS lon/lat, "PICFRAME LOCATION" is special to retrieve geo reverse (load_geoloc hast to be True) "PICFRAME GPS", "PICFRAME LOCATION", "EXIF FNumber", "EXIF ExposureTime", "EXIF ISOSpeedRatings", "EXIF FocalLength", "EXIF DateTimeOriginal", "Image Model", "Image Make", "IPTC Caption/Abstract", "IPTC Object Name", "IPTC Keywords"] load_geoloc: False # get location information from open street map NB if you switch this on (recommended) geo_key: "this_needs_to@be_changed" # then you MUST change the geo_key to something unique to you

i.e. use your email address

locale: "en_GB.UTF-8" # "locale -a" shows the installed locales which could used

locale: "de_DE.UTF-8" # "locale -a" shows the installed locales which could used key_list: [ ["tourism","amenity","isolated_dwelling"], ["suburb","village"], ["city","county"], ["region","state","province"], ["country"]] db_file: "/home/pi/picframe_data/data/pictureframe.db3" # database used by PictureFrame portrait_pairs: True log_level: "WARNING" # default=WARNING, could beDEBUG, INFO, WARNING, ERROR, CRITICAL log_file: "" # default="" for debugging set this to the path to a file. NB logging messages will

mqtt: use_mqtt: False # default=False. Set True true, to enable mqtt server: "your_mqtt_broker" # No defaults for server port: 8883 # default=8883 for tls, 1883 else (tls must be "" then !!!!!) login: "name" # your mqtt user password: "your_password" # password for mqtt user tls: "/path/to/your/ca.crt" # filename including path to your ca.crt. If not used, must be set to "" !!!! device_id: "picframe" # default="picframe" unique id of device. change if there is more than one PictureFrame device_url: "" # if use_http==True, set url to picframe config page. Must be a valid url, or "" otherwise home assistant runs in an error.

http: use_http: False # default=False. Set True to enable http NB THIS SERVER IS FOR LOCAL NETWORK AND SHOULD NOT BE EXPOSED TO EXTERNAL ACCESS path: "/home/pi/picframe_data/html" # path to where html files are located port: 9000 # port used to serve pages by http server < 1024 requires root which is bad idea use_ssl: False keyfile: "path/to/key.pem" # private-key certfile: "path/to/cert.pem" # server certificate

peripherals: input_type: null # default=null, valid options: {null, "keyboard", "touch", "mouse"} buttons: pause: # pause/unpause the show enable: True # default=True label: "Pause" # default="Pause" shortcut: " " # default=" " display_off: # turn off the display (when off, any input from selected peripheral will turn it back on) enable: True # default=True label: "Display off" # default="Display off" shortcut: "o" # default="o" location: # shows or hides location information enable: False # default=False label: "Location" # default="Location" shortcut: "l" # default="l" exit: # exit PictureFrame enable: False # default=False label: "Exit" # default="Exit" shortcut: "e" # default="e" power_down: # power down the device, uses sudo enable: False # default=False label: "Power down" # default="Power down" shortcut: "p" # default="p"

jgodfrey commented 1 year ago

Hi @Rob-Chill,

So, to make sure I understand - you want to use a specific image (like the one pictured above) as the mat texture - and in full color?

First off, this is definitely not supported in the current code base. I haven't looked at the matting code for a while, but poking around, here are a few tips...

When the outer mat texture is loaded in the code it's automatically converted to grayscale. The grayscale conversion is done because, eventually, the "white" in the image is converted to the mat color (either automatically chosen or user-defined).

So, to work with a color image, you'd need to drop the convert("L") piece here:

https://github.com/helgeerbe/picframe/blob/9707f402eb160b443cad2c98562c8f9bc2a725bf/picframe/mat_image.py#L32

The actual colorized mat is created here:

https://github.com/helgeerbe/picframe/blob/9707f402eb160b443cad2c98562c8f9bc2a725bf/picframe/mat_image.py#L311

Specifically, that colorize() call is what converts the whites of the grayscale image to the chosen color. Commenting out that call (in addition to removing the grayscale conversion mentioned above) might (?) do what you want.

If you give that a go, I'm curious if / how it works. Let us know.

Rob-Chill commented 1 year ago

Hey jgodfrey,

thank you for the tips. I will have a go at it, as soon as possible and will let u know the result.

cya Rob

Rob-Chill commented 1 year ago

Good evening everybody,

could you give me a hint, where I find the mat_image.py on my raspberry pi?

Thanks in advance. Rob

Rob-Chill commented 1 year ago

Hey its me again,

i finally found it in /usr/local/lib/python3.7/dist-packages/picframe/. I commented the code and it works fine.

Thank you for your help! I really appreciate it.

Here a picture with the result: IMG_20221129_215811

jgodfrey commented 1 year ago

Oh, nice - glad you got it working!

Edit: Looks great BTW! :)

jgodfrey commented 1 year ago

Related, it might be interesting to blur that background image a bit... (??)

If you want to experiment with that, it'd be something like:

  1. Add ImageFilter to the import list at the top of the same source file. So:

from PIL import Image, ImageOps, ImageDraw, ImageFilter

  1. Add a filter() call back in place of the colorize() call you commented out. So:

mat_img = mat_img.filter(ImageFilter.BLUR)

There are other ways to blur / styles of blurring, but that might get you started...

Rob-Chill commented 1 year ago

Hey, yeah that sounds good to give it a try.

Btw. is it also possible, in an easy way, to add a transparence to the background, which I also could configure in the config-file? Like opacity (0.0 to 1.0).

Thanks in advance. I will let u know, if the blur will work.

Rob

Rob-Chill commented 1 year ago

I tested the blur option and it looks great so far. Is there a possibility to change the blur amount in the configuration.yaml?

Here a compare between with and without filter: IMG_20221130_221209 IMG_20221130_221451

Thank you again!

Rob

jgodfrey commented 1 year ago

I tested the blur option and it looks great so far.

Nice - looks good!

Is there a possibility to change the blur amount in the configuration.yaml?

Unfortunately, not without making additional code changes to support a new configuration option.

jgodfrey commented 1 year ago

Btw. is it also possible, in an easy way, to add a transparence to the background,

For this, it should be as simple as calling putalpha() (with an appropriate value) on the background image.

To test, I'd try something like this (in the same __get_colorized_mat() method you've been editing. Just do it before the method returns the final background image:

mat_img.putalpha(128)

I think that should give you a 50% transparent image (values between 0 and 255, I think...)

Rob-Chill commented 1 year ago

Hello again.

I will try this this weekend.

If I need a new configuration option, which files i would need? Is it possible to put the files into the pyCharm IDE to update your program with the new features?

Greets Rob

Rob-Chill commented 1 year ago

Hello,

unfortunately the putalpha doesn't work. Do I have to import this function in any way?

Greets Rob