add dynamic image colage http image server for menu items
This commit is contained in:
185
resources/lib/image_server.py
Normal file
185
resources/lib/image_server.py
Normal file
@@ -0,0 +1,185 @@
|
||||
|
||||
import xbmcvfs
|
||||
import xbmc
|
||||
import base64
|
||||
import re
|
||||
from urlparse import urlparse
|
||||
|
||||
import threading
|
||||
import httplib
|
||||
import io
|
||||
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
|
||||
from PIL import ImageFilter, Image, ImageOps
|
||||
|
||||
from .simple_logging import SimpleLogging
|
||||
from .datamanager import DataManager
|
||||
from .downloadutils import DownloadUtils
|
||||
from .utils import getArt
|
||||
|
||||
PORT_NUMBER = 24276
|
||||
log = SimpleLogging(__name__)
|
||||
|
||||
def get_image_links(url):
|
||||
|
||||
download_utils = DownloadUtils()
|
||||
server = download_utils.getServer()
|
||||
if server is None:
|
||||
return []
|
||||
|
||||
url = re.sub("(?i)limit=[0-9]+", "limit=4", url)
|
||||
url = url.replace("{ItemLimit}", "4")
|
||||
url = re.sub("(?i)SortBy=[a-zA-Z]+", "SortBy=Random", url)
|
||||
|
||||
if not re.search('limit=', url, re.IGNORECASE):
|
||||
url += "&Limit=4"
|
||||
|
||||
if not re.search('sortBy=', url, re.IGNORECASE):
|
||||
url += "&SortBy=Random"
|
||||
|
||||
data_manager = DataManager()
|
||||
result = data_manager.GetContent(url)
|
||||
|
||||
items = result.get("Items")
|
||||
if not items:
|
||||
return []
|
||||
|
||||
art_urls = []
|
||||
for iteem in items:
|
||||
art = getArt(item=iteem, server=server)
|
||||
art_urls.append(art)
|
||||
|
||||
return art_urls
|
||||
|
||||
|
||||
|
||||
def build_image(path):
|
||||
log.debug("build_image()")
|
||||
|
||||
log.debug("Request Path : {0}", path)
|
||||
|
||||
request_path = path[1:]
|
||||
|
||||
if request_path == "favicon.ico":
|
||||
return []
|
||||
|
||||
decoded_url = base64.b64decode(request_path)
|
||||
log.debug("decoded_url : {0}", decoded_url)
|
||||
|
||||
image_urls = get_image_links(decoded_url)
|
||||
|
||||
width, height = 500, 750
|
||||
collage = Image.new('RGB', (width, height), (5, 5, 5))
|
||||
|
||||
cols = 2
|
||||
rows = 2
|
||||
thumbnail_width = int(width / cols)
|
||||
thumbnail_height = int(height / rows)
|
||||
size = thumbnail_width, thumbnail_height
|
||||
image_count = 0
|
||||
|
||||
for art in image_urls:
|
||||
|
||||
thumb_url = art.get("thumb")
|
||||
if thumb_url:
|
||||
url_bits = urlparse(thumb_url.strip())
|
||||
|
||||
host_name = url_bits.hostname
|
||||
port = url_bits.port
|
||||
user_name = url_bits.username
|
||||
user_password = url_bits.password
|
||||
url_path = url_bits.path
|
||||
url_query = url_bits.query
|
||||
|
||||
server = "%s:%s" % (host_name, port)
|
||||
url_full_path = url_path + "?" + url_query
|
||||
|
||||
log.debug("Adding Image : {0} {1} {2}", image_count, server, url_full_path)
|
||||
|
||||
conn = httplib.HTTPConnection(server)
|
||||
conn.request("GET", url_full_path)#"/emby/Items/32907/Images/Primary?maxHeight=635&tag=b06948152c2c1203ceedd66721a18f6f&quality=90")
|
||||
image_responce = conn.getresponse()
|
||||
image_data = image_responce.read()
|
||||
|
||||
loaded_image = Image.open(io.BytesIO(image_data))
|
||||
|
||||
image = ImageOps.fit(loaded_image, (size), method=Image.ANTIALIAS, bleed=0.0, centering=(0.5, 0.5))
|
||||
|
||||
x = int(image_count % cols) * thumbnail_width
|
||||
y = int(image_count/cols) * thumbnail_height
|
||||
collage.paste(image, (x, y))
|
||||
|
||||
del image_data
|
||||
del loaded_image
|
||||
del image
|
||||
|
||||
image_count += 1
|
||||
|
||||
del image_urls
|
||||
|
||||
imgByteArr = io.BytesIO()
|
||||
collage.save(imgByteArr, format='JPEG')
|
||||
image_bytes = imgByteArr.getvalue()
|
||||
|
||||
return image_bytes
|
||||
|
||||
|
||||
class HttpImageHandler(BaseHTTPRequestHandler):
|
||||
|
||||
def log_message(self, format, *args):
|
||||
log_line = format % args
|
||||
log.debug(log_line)
|
||||
return
|
||||
|
||||
def do_GET(self):
|
||||
log.debug("HttpImageHandler:do_GET()")
|
||||
self.serve_image()
|
||||
return
|
||||
|
||||
def do_HEAD(self):
|
||||
log.debug("HttpImageHandler:do_HEAD()")
|
||||
self.send_response(200)
|
||||
self.end_headers()
|
||||
return
|
||||
|
||||
def do_QUIT(self):
|
||||
log.debug("HttpImageHandler:do_QUIT()")
|
||||
self.send_response(200)
|
||||
self.end_headers()
|
||||
return
|
||||
|
||||
def serve_image(self):
|
||||
|
||||
image_bytes = build_image(self.path)
|
||||
|
||||
self.send_response(200)
|
||||
self.send_header('Content-type', 'image/jpeg')
|
||||
self.send_header('Content-Length', str(len(image_bytes)))
|
||||
self.end_headers()
|
||||
self.wfile.write(image_bytes)
|
||||
|
||||
|
||||
class HttpImageServerThread(threading.Thread):
|
||||
|
||||
keep_running = True
|
||||
|
||||
def __init__(self):
|
||||
threading.Thread.__init__(self)
|
||||
|
||||
def stop(self):
|
||||
self.keep_running = False
|
||||
log.debug("HttpImageServerThread:stop called")
|
||||
try:
|
||||
conn = httplib.HTTPConnection("localhost:%d" % PORT_NUMBER)
|
||||
conn.request("QUIT", "/")
|
||||
conn.getresponse()
|
||||
except Exception as err:
|
||||
pass
|
||||
|
||||
def run(self):
|
||||
log.debug("HttpImageServerThread:started")
|
||||
server = HTTPServer(('', PORT_NUMBER), HttpImageHandler)
|
||||
|
||||
while self.keep_running:
|
||||
server.handle_request()
|
||||
|
||||
log.debug("HttpImageServerThread:exiting")
|
||||
@@ -4,6 +4,7 @@
|
||||
import sys
|
||||
import json
|
||||
import urllib
|
||||
import base64
|
||||
|
||||
import xbmcplugin
|
||||
import xbmcaddon
|
||||
@@ -155,13 +156,15 @@ def show_movie_years(params):
|
||||
|
||||
item_url = get_emby_url("{server}/emby/Users/{userid}/Items", params)
|
||||
|
||||
art = {"thumb": "http://localhost:24276/" + base64.b64encode(item_url)}
|
||||
|
||||
content_url = urllib.quote(item_url)
|
||||
url = sys.argv[0] + ("?url=" +
|
||||
content_url +
|
||||
"&mode=GET_CONTENT" +
|
||||
"&media_type=movies")
|
||||
log.debug("addMenuDirectoryItem: {0} - {1}", name, url)
|
||||
addMenuDirectoryItem(name, url)
|
||||
addMenuDirectoryItem(name, url, art=art)
|
||||
|
||||
xbmcplugin.endOfDirectory(int(sys.argv[1]))
|
||||
|
||||
@@ -234,6 +237,8 @@ def show_movie_pages(params):
|
||||
item_data['path'] = item_url
|
||||
item_data['media_type'] = 'movies'
|
||||
|
||||
item_data["art"] = {"thumb": "http://localhost:24276/" + base64.b64encode(item_url)}
|
||||
|
||||
collections.append(item_data)
|
||||
start_index = start_index + page_limit
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ from resources.lib.server_detect import checkServer
|
||||
from resources.lib.library_change_monitor import LibraryChangeMonitor
|
||||
from resources.lib.datamanager import clear_old_cache_data
|
||||
from resources.lib.tracking import set_timing_enabled
|
||||
from resources.lib.image_server import HttpImageServerThread
|
||||
|
||||
settings = xbmcaddon.Addon()
|
||||
|
||||
@@ -63,6 +64,10 @@ try:
|
||||
except Exception as error:
|
||||
log.error("Error with initial service auth: {0}", error)
|
||||
|
||||
|
||||
image_server = HttpImageServerThread()
|
||||
image_server.start()
|
||||
|
||||
# set up all the services
|
||||
monitor = Service()
|
||||
playback_service = PlaybackService(monitor)
|
||||
@@ -155,6 +160,8 @@ while not xbmc.abortRequested:
|
||||
|
||||
xbmc.sleep(1000)
|
||||
|
||||
image_server.stop()
|
||||
|
||||
# call stop on the library update monitor
|
||||
library_change_monitor.stop()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user