Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update server transcodeImage method #845

Merged
merged 2 commits into from
Nov 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 35 additions & 10 deletions plexapi/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -734,21 +734,46 @@ def startAlertListener(self, callback=None):
notifier.start()
return notifier

def transcodeImage(self, media, height, width, opacity=100, saturation=100):
""" Returns the URL for a transcoded image from the specified media object.
Returns None if no media specified (needed if user tries to pass thumb
or art directly).
def transcodeImage(self, imageUrl, height, width,
opacity=None, saturation=None, blur=None, background=None,
minSize=True, upscale=True, imageFormat=None):
""" Returns the URL for a transcoded image.

Parameters:
imageUrl (str): The URL to the image
(eg. returned by :func:`~plexapi.mixins.PosterUrlMixin.thumbUrl`
or :func:`~plexapi.mixins.ArtUrlMixin.artUrl`).
The URL can be an online image.
height (int): Height to transcode the image to.
width (int): Width to transcode the image to.
opacity (int): Opacity of the resulting image (possibly deprecated).
saturation (int): Saturating of the resulting image.
opacity (int, optional): Change the opacity of the image (0 to 100)
saturation (int, optional): Change the saturation of the image (0 to 100).
blur (int, optional): The blur to apply to the image in pixels (e.g. 3).
background (str, optional): The background hex colour to apply behind the opacity (e.g. '000000').
minSize (bool, optional): Maintain smallest dimension. Default True.
upscale (bool, optional): Upscale the image if required. Default True.
imageFormat (str, optional): 'jpeg' (default) or 'png'.
"""
if media:
transcode_url = '/photo/:/transcode?height=%s&width=%s&opacity=%s&saturation=%s&url=%s' % (
height, width, opacity, saturation, media)
return self.url(transcode_url, includeToken=True)
params = {
'url': imageUrl,
'height': height,
'width': width,
'minSize': int(bool(minSize)),
'upscale': int(bool(upscale))
}
if opacity is not None:
params['opacity'] = opacity
if saturation is not None:
params['saturation'] = saturation
if blur is not None:
params['blur'] = blur
if background is not None:
params['background'] = str(background).strip('#')
if imageFormat is not None:
params['format'] = imageFormat.lower()

key = '/photo/:/transcode%s' % utils.joinArgs(params)
return self.url(key, includeToken=True)

def url(self, key, includeToken=None):
""" Build a URL string with proper token argument. Token will be appended to the URL
Expand Down
55 changes: 46 additions & 9 deletions tests/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,24 +60,52 @@ def test_server_url(plex):


def test_server_transcodeImage(tmpdir, plex, movie):
width, height = 500, 500
original_url = plex.url(movie.thumb)
resize_url = plex.transcodeImage(movie.thumb, height, width)
grayscale_url = plex.transcodeImage(movie.thumb, height, width, saturation=0)
width, height = 500, 100
background = "000000"

original_url = movie.thumbUrl
resize_jpeg_url = plex.transcodeImage(original_url, height, width)
no_minSize_png_url = plex.transcodeImage(original_url, height, width, minSize=False, imageFormat="png")
grayscale_url = plex.transcodeImage(original_url, height, width, saturation=0)
opacity_background_url = plex.transcodeImage(original_url, height, width, opacity=0, background=background, blur=100)
online_no_upscale_url = plex.transcodeImage(
"https://raw.githubusercontent.com/pkkid/python-plexapi/master/tests/data/cute_cat.jpg", 1000, 1000, upscale=False)

original_img = download(
original_url, plex._token, savepath=str(tmpdir), filename="original_img",
)
resized_img = download(
resize_url, plex._token, savepath=str(tmpdir), filename="resize_image"
resized_jpeg_img = download(
resize_jpeg_url, plex._token, savepath=str(tmpdir), filename="resized_jpeg_img"
)
no_minSize_png_img = download(
no_minSize_png_url, plex._token, savepath=str(tmpdir), filename="no_minSize_png_img"
)
grayscale_img = download(
grayscale_url, plex._token, savepath=str(tmpdir), filename="grayscale_img"
)
with Image.open(resized_img) as image:
assert width, height == image.size
opacity_background_img = download(
opacity_background_url, plex._token, savepath=str(tmpdir), filename="opacity_background_img"
)
online_no_upscale_img = download(
online_no_upscale_url, plex._token, savepath=str(tmpdir), filename="online_no_upscale_img"
)

with Image.open(original_img) as image:
assert width, height != image.size
assert image.size[0] != width
assert image.size[1] != height
with Image.open(resized_jpeg_img) as image:
assert image.size[0] == width
assert image.size[1] != height
assert image.format == "JPEG"
with Image.open(no_minSize_png_img) as image:
assert image.size[0] != width
assert image.size[1] == height
assert image.format == "PNG"
assert _detect_color_image(grayscale_img, thumb_size=150) == "grayscale"
assert _detect_dominant_hexcolor(opacity_background_img) == background
with Image.open(online_no_upscale_img) as image1:
with Image.open(utils.STUB_IMAGE_PATH) as image2:
assert image1.size == image2.size


def _detect_color_image(file, thumb_size=150, MSE_cutoff=22, adjust_color_bias=True):
Expand All @@ -101,6 +129,15 @@ def _detect_color_image(file, thumb_size=150, MSE_cutoff=22, adjust_color_bias=T
return "blackandwhite"


def _detect_dominant_hexcolor(file):
# https://stackoverflow.com/questions/3241929/python-find-dominant-most-common-color-in-an-image
pilimg = Image.open(file)
pilimg.convert("RGB")
pilimg.resize((1, 1), resample=0)
rgb_color = pilimg.getpixel((0, 0))
return "{:02x}{:02x}{:02x}".format(*rgb_color)


def test_server_fetchitem_notfound(plex):
with pytest.raises(NotFound):
plex.fetchItem(123456789)
Expand Down