From d0e37c8087593552d6a637c44125652f5fac4cbd Mon Sep 17 00:00:00 2001 From: Genadi Naydenov Date: Fri, 7 Oct 2022 12:18:08 +0300 Subject: [PATCH] Add function that swaps two colours. Swap the black and colour pixels of night weather icons. Add `DARK_MODE` as environment variable. It swaps black and white pixels of the final image. Make weather text scaling and icon positioning based on display height. Make swap colours False by defualt. Fix 02d.png and 02n.png position for small screens. Limit dark mode to weather mode. Update README. Change-type: minor Signed-off-by: Genadi Naydenov --- README.md | 6 +++- inkyshot/update-display.py | 49 +++++++++++++++++++++++++-------- inkyshot/weather-icons/02d.png | Bin 502 -> 499 bytes inkyshot/weather-icons/02n.png | Bin 356 -> 355 bytes 4 files changed, 43 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 26312e0..35ab6be 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,11 @@ To enable the weather display, set the environment variable `MODE` to `weather`. Next, use either `LATLONG` (e.g. 39.9199,32.8543) or `WEATHER_LOCATION` (e.g. Ankara, Turkey) environment variables to define the location for weather information. Entering only an empty `WEATHER_LOCATION` is also sufficient and in this case Inkyshot will lookup the latitude and longitude information from device's IP address. -Set `SCALE` environment variable to `F` to display the temperature values in Fahrenheit scale. The default is Celcius scale. +Set `SCALE` environment variable to `F` to display the temperature values in Fahrenheit scale. The default is Celsius scale. + +Set `TEMP_THRESHOLD` environment variable to a desired temperature. All readings above this value will be displayed in colour on colour eInk screens. The default value is 25 Celsius (77 Fahrenheit). + +You can use the `WEATHER_DARK_MODE` environment variable if you want to eanble dark mode on the inkyshot. Use the `WEATHER_FONT` variable to customize the font used in weather display mode. diff --git a/inkyshot/update-display.py b/inkyshot/update-display.py index 0095694..df90685 100644 --- a/inkyshot/update-display.py +++ b/inkyshot/update-display.py @@ -78,6 +78,24 @@ def create_mask(source): mask_image.putpixel((x, y), 255) return mask_image +def swap_two_colours(img, dark_mode=False): + """Swap two colours. + """ + black = BLACK + if dark_mode: + target = BLACK - 1 + else: + target = BLACK + 1 + logging.info(f"Swapping colours {black} and {target}") + w, h = img.size + for x in range(w): + for y in range(h): + if img.getpixel((x, y)) == black: + img.putpixel((x, y), target) + elif img.getpixel((x, y)) == target: + img.putpixel((x, y), black) + return img + # Declare non pip fonts here ** Note: ttf files need to be in the /fonts dir of application repo Grand9KPixel = "/usr/app/fonts/Grand9KPixel.ttf" @@ -104,6 +122,7 @@ def draw_weather(weather, img, scale, fill): # Load weather icon icon_name = weather['symbol'].split('_')[0] time_of_day = '' + swap_colours = False # Couple of symbols have different icons for day and night. Check if this symbol is one of them. if len(weather['symbol'].split('_')) > 1: symbol_cycle = weather['symbol'].split('_')[1] @@ -111,9 +130,13 @@ def draw_weather(weather, img, scale, fill): time_of_day = 'd' elif symbol_cycle == 'night': time_of_day = 'n' + swap_colours = True icon_filename = f"{icon_map[icon_name]:02}{time_of_day}.png" filepath = Path(__file__).parent / 'weather-icons' / icon_filename icon_image = Image.open(filepath) + if swap_colours: + logging.info("Swapping night weather icon black and colour pixels") + icon_image = swap_two_colours(icon_image) # Draw the weather icon if WEATHER_INVERT and WAVESHARE: icon_mask = create_mask(icon_image) @@ -121,9 +144,9 @@ def draw_weather(weather, img, scale, fill): icon = Image.new('1', (100, 100), 255) icon.paste(icon_image, (0,0), icon_mask) icon_inverted = ImageOps.invert(icon.convert('RGB')) - img.paste(icon_inverted, (120 + X_OFFSET, 3 + Y_OFFSET)) + img.paste(icon_inverted, (119 + X_OFFSET, 3 + Y_OFFSET)) else: - img.paste(icon_image, (120 + X_OFFSET, 3 + Y_OFFSET)) + img.paste(icon_image, (119 + X_OFFSET, 3 + Y_OFFSET)) return img def get_current_display(): @@ -225,12 +248,12 @@ def set_current_display(val): logging.error(f"Failed to set current display to {val}. Error is: {err}") def temp_to_str(temp, scale): - """Prepare the temperature to draw based on the defined scale: Celcius or Fahrenheit""" + """Prepare the temperature to draw based on the defined scale: Celsius or Fahrenheit""" if scale == 'F': - temp = celcius_to_fahrenheit(temp) + temp = celsius_to_fahrenheit(temp) return f"{temp:.1f}" -def celcius_to_fahrenheit(temp): +def celsius_to_fahrenheit(temp): """Convert Celsius to Fahrenheit""" return temp * 9/5 + 32 @@ -273,7 +296,7 @@ def celcius_to_fahrenheit(temp): SCALE = 'F' if "SCALE" in os.environ and os.environ["SCALE"] == 'F' else 'C' # Temperature threshold above which T is displayed in colour -TEMP_THRESHOLD = 25 if SCALE == 'C' else celcius_to_fahrenheit(25) +TEMP_THRESHOLD = 25 if SCALE == 'C' else celsius_to_fahrenheit(25) if "TEMP_THRESHOLD" in os.environ: TEMP_THRESHOLD = os.environ['TEMP_THRESHOLD'] @@ -315,15 +338,13 @@ def celcius_to_fahrenheit(temp): HEIGHT = display.HEIGHT BLACK = display.BLACK WHITE = display.WHITE - if display.colour == "black": - COLOUR = BLACK + COLOUR = BLACK if display.colour == "black" else display.RED + if HEIGHT == 104: # Display size: W 212 x H 104 X_OFFSET = 0 Y_OFFSET = 0 WEATHER_FONT_INCREASE = 0 else: - # Both display.RED and display.YELLOW = 2 - COLOUR = display.RED # Display size: W 250 x H 122 # text margin is 3 + 1/3*X_OFFSET = 10 pixels from left border # weather icon is 250 - (120 + 21 + 100) = 9 pixels from right border @@ -367,7 +388,7 @@ def celcius_to_fahrenheit(temp): os.environ['LATLONG'] = f"{LAT},{LONG}" # If weather is empty dictionary, fall back to drawing quote if len(weather) > 0: - temperature = weather['temperature'] if SCALE == 'C' else celcius_to_fahrenheit(weather['temperature']) + temperature = weather['temperature'] if SCALE == 'C' else celsius_to_fahrenheit(weather['temperature']) fill = COLOUR if temperature >= TEMP_THRESHOLD else BLACK img = draw_weather(weather, img, SCALE, fill) else: @@ -444,6 +465,12 @@ def celcius_to_fahrenheit(temp): if "ROTATE" in os.environ: img = img.rotate(180) +# Enable dark mode +# #(it swaps the colour of the first two pixels in the palette) +if "WEATHER_DARK_MODE" in os.environ and target_display == 'weather': + logging.info("Switching to dark mode") + img = swap_two_colours(img, dark_mode=True) + if WAVESHARE: # epd does not have a set_image method. display.display(display.getbuffer(img)) diff --git a/inkyshot/weather-icons/02d.png b/inkyshot/weather-icons/02d.png index 7ff40b24778a646cdef2248ca31625d58c3afc21..f9781f94e14f0f7ef3f05b40a05593cf4440e394 100644 GIT binary patch delta 418 zcmV;T0bTy~1M>rrTYrN|L_t(|ob8oCZp0uAMPb1axDQ8Q5oeJj

v>?6Vmu!zqgc zHaIa=TaDC3YiTr0-r#R+VjJ^s&20ESaq(RQCH#b9R}zW1D*^mKT}ToNv3C;l!;IaX zKp~)z-~gi4$b`ge1dza;3?QH@;sMZL3{p8scZsF zUr**jHbD$KtL|jTYauTgxMP`9C<-zY*?JiaVIlGaaq9#zlB`5tQQQ*Wkzo7i9EX&L}@6qlfEB7!ne~%Iyj%)!w~EmK&M6TcwbC6LkW* z4nA4csBy7qgx)NfonX4RvCk+_0H?dw6>4Zce|g;W=!E!P@u;*L#XS4gNf;7P`o9-3 zeT~4d!+zG4$DMrG{ior?2*W93Mw4kg&4L+CK(zNwS{t;V%=*7;9~?-9Ck6(0mjD0& M07*qoM6N<$f@_Mz>i_@% delta 421 zcmV;W0b2g^1NH-uTYrX0L_t(|ob8o8ZUi9=g`uEN5$;27Kru{_Bg`r065DSRX~HQ3 z#@OaB(nc$#NGz?y?ziJ-9v-aJf5`BU6TLl)yrho_dF49tT8Zw7O+VP+%AzG6Nf<~{ z55X%vlJrX^c0#-kVM}x*ArmttZ;9BEq(5V*UnDVpbi||`CVz6o7;lMarW&&B3B*rW z@(IG%{0Kah?P~}CP!hz}WSEW(%7wib65GNx$$-$-5(HUDwkpYFp{DDsB(5d3fEc%? zON=01$?7zf7UOB;UL}EjQx&|OconZ4dBC7J@5xb8!PE6*8>xT{3TZxrs)BV}CKq=~ zM^4OzL}XJ;Tz^vmtJDoua_4?T7wS$=%Oo`Jh-5V#I;th{OHzgM$z2mtPWv)5vJWJP zu9^_+#05E~I<@1++OjG8l)$QY#}hd^N1YOH@F`2c0?J!|7edsfaITk{grVGXG8-AD z%RZ3s$Sr1~~UR$kxa>)U@hG1gPYttQiYnyn{bjvnVtT8JOa`ac_AdBlVA#ZCRe P00000NkvXXu0mjfIe5de diff --git a/inkyshot/weather-icons/02n.png b/inkyshot/weather-icons/02n.png index 38c23e34c6c3d65fdcc71ca18fa77c02595b5eca..4745fab995e040c6f1f2c3838ab531a277ab95fe 100644 GIT binary patch delta 227 zcmV<9038410^Mi(Z}Z3cqWXPnrciC#XT_2YJ>3s)GJRJ$WSmiReio d3~Sc>b3R#444KsCj3WR5002ovPDHLkV1fZZXQKcB delta 228 zcmV<#ae}BOU2WS^2BE_=;pH~+t_crHF%0-ROFNgFE$bz)Wv5sm=`;q49woLX zSn5{;gy=1S32JRc(N((Z+^qoh7ri>+6@J$&pEL`4PEdo;5Av)7R0aKsdh$sA6Va1G e7}l)$-+TZ-9t@c~x)Eal0000