fixed a few things in rss module, minor improvements to other modules. Added test file for use without installing
		
			
				
	
	
		
			180 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			180 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| #!/usr/bin/python3
 | |
| # -*- coding: utf-8 -*-
 | |
| """
 | |
| Image module for inkycal Project
 | |
| Copyright by aceisace
 | |
| Development satge: Beta
 | |
| """
 | |
| 
 | |
| from os import path
 | |
| from PIL import ImageOps
 | |
| import requests
 | |
| import numpy
 | |
| 
 | |
| """----------------------------------------------------------------"""
 | |
| #path = 'https://github.com/aceisace/Inky-Calendar/raw/master/Gallery/Inky-Calendar-logo.png'
 | |
| #path  ='/home/pi/Inky-Calendar/images/canvas.png'
 | |
| path      = inkycal_image_path
 | |
| path_body = inkycal_image_path_body
 | |
| mode = 'auto'         # 'horizontal' # 'vertical' # 'auto'
 | |
| upside_down = False    # Flip image by 180 deg (upside-down)
 | |
| alignment = 'center'  # top_center, top_left, center_left, bottom_right etc.
 | |
| colours = 'bwr'       # bwr # bwy # bw
 | |
| render = True         # show image on E-Paper?
 | |
| """----------------------------------------------------------------"""
 | |
| 
 | |
| # First determine dimensions
 | |
| if mode == 'horizontal':
 | |
|   display_width, display_height == display_height, display_width
 | |
| 
 | |
| if mode == 'vertical':
 | |
|   raise NotImplementedError('Vertical mode is not currenctly supported')
 | |
| 
 | |
| # .. Then substitute possibly parameterized path
 | |
| # TODO Get (assigned) panel dimensions instead of display dimensions
 | |
| path = path.replace('{model}', model).replace('{width}',str(display_width)).replace('{height}',str(display_height))
 | |
| print(path)
 | |
| 
 | |
| """Try to open the image if it exists and is an image file"""
 | |
| try:
 | |
|   if 'http' in path:
 | |
|     if path_body is None:
 | |
|       # Plain GET
 | |
|       im = Image.open(requests.get(path, stream=True).raw)
 | |
|     else:
 | |
|       # POST request, passing path_body in the body
 | |
|       im = Image.open(requests.post(path, json=path_body, stream=True).raw)
 | |
|   else:
 | |
|     im = Image.open(path)
 | |
| except FileNotFoundError:
 | |
|   print('Your file could not be found. Please check the path to your file.')
 | |
|   raise
 | |
| except OSError:
 | |
|   print('Please check if the path points to an image file.')
 | |
|   raise
 | |
| 
 | |
| """Turn image upside-down if specified"""
 | |
| if upside_down == True:
 | |
|   im.rotate(180, expand = True)
 | |
| 
 | |
| if mode == 'auto':
 | |
|   if (im.width > im.height) and (display_width < display_height):
 | |
|     print('display vertical, image horizontal -> flipping image')
 | |
|     im = im.rotate(90, expand=True)
 | |
|   if (im.width < im.height) and (display_width > display_height):
 | |
|     print('display horizontal, image vertical -> flipping image')
 | |
|     im = im.rotate(90, expand=True)
 | |
| 
 | |
| def fit_width(image, width):
 | |
|   """Resize an image to desired width"""
 | |
|   print('resizing width from', image.width, 'to', end = ' ')
 | |
|   wpercent = (display_width/float(image.width))
 | |
|   hsize = int((float(image.height)*float(wpercent)))
 | |
|   img = image.resize((width, hsize), Image.ANTIALIAS)
 | |
|   print(img.width)
 | |
|   return img
 | |
| 
 | |
| def fit_height(image, height):
 | |
|   """Resize an image to desired height"""
 | |
|   print('resizing height from', image.height, 'to', end = ' ')
 | |
|   hpercent = (height / float(image.height))
 | |
|   wsize = int(float(image.width) * float(hpercent))
 | |
|   img = image.resize((wsize, height), Image.ANTIALIAS)
 | |
|   print(img.height)
 | |
|   return img
 | |
| 
 | |
| if im.width > display_width:
 | |
|   im = fit_width(im, display_width)
 | |
| if im.height > display_height:
 | |
|   im = fit_height(im, display_height)
 | |
| 
 | |
| if alignment == 'center':
 | |
|   x,y = int((display_width-im.width)/2), int((display_height-im.height)/2)
 | |
| elif alignment == 'center_right':
 | |
|   x, y = display_width-im.width, int((display_height-im.height)/2)
 | |
| elif alignment == 'center_left':
 | |
|   x, y = 0, int((display_height-im.height)/2)
 | |
| 
 | |
| elif alignment == 'top_center':
 | |
|   x, y = int((display_width-im.width)/2), 0
 | |
| elif alignment == 'top_right':
 | |
|   x, y = display_width-im.width, 0
 | |
| elif alignment == 'top_left':
 | |
|   x, y = 0, 0
 | |
| 
 | |
| elif alignment == 'bottom_center':
 | |
|   x, y = int((display_width-im.width)/2), display_height-im.height
 | |
| elif alignment == 'bottom_right':
 | |
|   x, y = display_width-im.width, display_height-im.height
 | |
| elif alignment == 'bottom_left':
 | |
|   x, y = display_width-im.width, display_height-im.height
 | |
| 
 | |
| if len(im.getbands()) == 4:
 | |
|   print('removing transparency')
 | |
|   bg = Image.new('RGBA', (im.width, im.height), 'white')
 | |
|   im = Image.alpha_composite(bg, im)
 | |
| 
 | |
| image.paste(im, (x,y))
 | |
| im = image
 | |
| 
 | |
| if colours == 'bw':
 | |
|   """For black-white images, use monochrome dithering"""
 | |
|   black = im.convert('1', dither=True)
 | |
| elif colours == 'bwr':
 | |
|   """For black-white-red images, create corresponding palette"""
 | |
|   pal = [255,255,255, 0,0,0, 255,0,0, 255,255,255]
 | |
| elif colours == 'bwy':
 | |
|   """For black-white-yellow images, create corresponding palette"""
 | |
|   pal = [255,255,255, 0,0,0, 255,255,0, 255,255,255]
 | |
| 
 | |
| 
 | |
| """Map each pixel of the opened image to the Palette"""
 | |
| if colours != 'bw':
 | |
|   palette_im = Image.new('P', (3,1))
 | |
|   palette_im.putpalette(pal * 64)
 | |
|   quantized_im = im.quantize(palette=palette_im)
 | |
|   quantized_im.convert('RGB')
 | |
| 
 | |
|   """Create buffer for coloured pixels"""
 | |
|   buffer1 = numpy.array(quantized_im.convert('RGB'))
 | |
|   r1,g1,b1 = buffer1[:, :, 0], buffer1[:, :, 1], buffer1[:, :, 2]
 | |
| 
 | |
|   """Create buffer for black pixels"""
 | |
|   buffer2 = numpy.array(quantized_im.convert('RGB'))
 | |
|   r2,g2,b2 = buffer2[:, :, 0], buffer2[:, :, 1], buffer2[:, :, 2]
 | |
| 
 | |
|   if colours == 'bwr':
 | |
|     """Create image for only red pixels"""
 | |
|     buffer2[numpy.logical_and(r2 ==  0, b2 == 0)] = [255,255,255] # black->white
 | |
|     buffer2[numpy.logical_and(r2 ==  255, b2 == 0)] = [0,0,0] #red->black
 | |
|     colour = Image.fromarray(buffer2)
 | |
|     """Create image for only black pixels"""
 | |
|     buffer1[numpy.logical_and(r1 ==  255, b1 == 0)] = [255,255,255]
 | |
|     black = Image.fromarray(buffer1)
 | |
| 
 | |
|   if colours == 'bwy':
 | |
|     """Create image for only yellow pixels"""
 | |
|     buffer2[numpy.logical_and(r2 ==  0, b2 == 0)] = [255,255,255] # black->white
 | |
|     buffer2[numpy.logical_and(g2 == 255, b2 == 0)] = [0,0,0] #yellow -> black
 | |
|     colour = Image.fromarray(buffer2)
 | |
|     """Create image for only black pixels"""
 | |
|     buffer1[numpy.logical_and(g1 == 255, b1 == 0)] = [255,255,255]
 | |
|     black = Image.fromarray(buffer1)
 | |
| ##
 | |
| ##if render == True:
 | |
| ##  epaper = driver.EPD()
 | |
| ##  print('Initialising E-Paper...', end = '')
 | |
| ##  epaper.init()
 | |
| ##  print('Done')
 | |
| ##
 | |
| ##  print('Sending image data and refreshing display...', end='')
 | |
| ##  if three_colour_support == True:
 | |
| ##    epaper.display(epaper.getbuffer(black), epaper.getbuffer(colour))
 | |
| ##  else:
 | |
| ##    epaper.display(epaper.getbuffer(black))
 | |
| ##  print('Done')
 | |
| ##
 | |
| ##  print('Sending E-Paper to deep sleep...', end = '')
 | |
| ##  epaper.sleep()
 | |
| print('Done')
 |