Skip to content

Commit 34a4218

Browse files
authored
Update server transcodeImage method (#845)
* Update server transcodeImage method * Update server transcodeImage tests
1 parent 3e1ce1c commit 34a4218

2 files changed

Lines changed: 81 additions & 19 deletions

File tree

plexapi/server.py

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -734,21 +734,46 @@ def startAlertListener(self, callback=None):
734734
notifier.start()
735735
return notifier
736736

737-
def transcodeImage(self, media, height, width, opacity=100, saturation=100):
738-
""" Returns the URL for a transcoded image from the specified media object.
739-
Returns None if no media specified (needed if user tries to pass thumb
740-
or art directly).
737+
def transcodeImage(self, imageUrl, height, width,
738+
opacity=None, saturation=None, blur=None, background=None,
739+
minSize=True, upscale=True, imageFormat=None):
740+
""" Returns the URL for a transcoded image.
741741
742742
Parameters:
743+
imageUrl (str): The URL to the image
744+
(eg. returned by :func:`~plexapi.mixins.PosterUrlMixin.thumbUrl`
745+
or :func:`~plexapi.mixins.ArtUrlMixin.artUrl`).
746+
The URL can be an online image.
743747
height (int): Height to transcode the image to.
744748
width (int): Width to transcode the image to.
745-
opacity (int): Opacity of the resulting image (possibly deprecated).
746-
saturation (int): Saturating of the resulting image.
749+
opacity (int, optional): Change the opacity of the image (0 to 100)
750+
saturation (int, optional): Change the saturation of the image (0 to 100).
751+
blur (int, optional): The blur to apply to the image in pixels (e.g. 3).
752+
background (str, optional): The background hex colour to apply behind the opacity (e.g. '000000').
753+
minSize (bool, optional): Maintain smallest dimension. Default True.
754+
upscale (bool, optional): Upscale the image if required. Default True.
755+
imageFormat (str, optional): 'jpeg' (default) or 'png'.
747756
"""
748-
if media:
749-
transcode_url = '/photo/:/transcode?height=%s&width=%s&opacity=%s&saturation=%s&url=%s' % (
750-
height, width, opacity, saturation, media)
751-
return self.url(transcode_url, includeToken=True)
757+
params = {
758+
'url': imageUrl,
759+
'height': height,
760+
'width': width,
761+
'minSize': int(bool(minSize)),
762+
'upscale': int(bool(upscale))
763+
}
764+
if opacity is not None:
765+
params['opacity'] = opacity
766+
if saturation is not None:
767+
params['saturation'] = saturation
768+
if blur is not None:
769+
params['blur'] = blur
770+
if background is not None:
771+
params['background'] = str(background).strip('#')
772+
if imageFormat is not None:
773+
params['format'] = imageFormat.lower()
774+
775+
key = '/photo/:/transcode%s' % utils.joinArgs(params)
776+
return self.url(key, includeToken=True)
752777

753778
def url(self, key, includeToken=None):
754779
""" Build a URL string with proper token argument. Token will be appended to the URL

tests/test_server.py

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,24 +60,52 @@ def test_server_url(plex):
6060

6161

6262
def test_server_transcodeImage(tmpdir, plex, movie):
63-
width, height = 500, 500
64-
original_url = plex.url(movie.thumb)
65-
resize_url = plex.transcodeImage(movie.thumb, height, width)
66-
grayscale_url = plex.transcodeImage(movie.thumb, height, width, saturation=0)
63+
width, height = 500, 100
64+
background = "000000"
65+
66+
original_url = movie.thumbUrl
67+
resize_jpeg_url = plex.transcodeImage(original_url, height, width)
68+
no_minSize_png_url = plex.transcodeImage(original_url, height, width, minSize=False, imageFormat="png")
69+
grayscale_url = plex.transcodeImage(original_url, height, width, saturation=0)
70+
opacity_background_url = plex.transcodeImage(original_url, height, width, opacity=0, background=background, blur=100)
71+
online_no_upscale_url = plex.transcodeImage(
72+
"https://raw.githubusercontent.com/pkkid/python-plexapi/master/tests/data/cute_cat.jpg", 1000, 1000, upscale=False)
73+
6774
original_img = download(
6875
original_url, plex._token, savepath=str(tmpdir), filename="original_img",
6976
)
70-
resized_img = download(
71-
resize_url, plex._token, savepath=str(tmpdir), filename="resize_image"
77+
resized_jpeg_img = download(
78+
resize_jpeg_url, plex._token, savepath=str(tmpdir), filename="resized_jpeg_img"
79+
)
80+
no_minSize_png_img = download(
81+
no_minSize_png_url, plex._token, savepath=str(tmpdir), filename="no_minSize_png_img"
7282
)
7383
grayscale_img = download(
7484
grayscale_url, plex._token, savepath=str(tmpdir), filename="grayscale_img"
7585
)
76-
with Image.open(resized_img) as image:
77-
assert width, height == image.size
86+
opacity_background_img = download(
87+
opacity_background_url, plex._token, savepath=str(tmpdir), filename="opacity_background_img"
88+
)
89+
online_no_upscale_img = download(
90+
online_no_upscale_url, plex._token, savepath=str(tmpdir), filename="online_no_upscale_img"
91+
)
92+
7893
with Image.open(original_img) as image:
79-
assert width, height != image.size
94+
assert image.size[0] != width
95+
assert image.size[1] != height
96+
with Image.open(resized_jpeg_img) as image:
97+
assert image.size[0] == width
98+
assert image.size[1] != height
99+
assert image.format == "JPEG"
100+
with Image.open(no_minSize_png_img) as image:
101+
assert image.size[0] != width
102+
assert image.size[1] == height
103+
assert image.format == "PNG"
80104
assert _detect_color_image(grayscale_img, thumb_size=150) == "grayscale"
105+
assert _detect_dominant_hexcolor(opacity_background_img) == background
106+
with Image.open(online_no_upscale_img) as image1:
107+
with Image.open(utils.STUB_IMAGE_PATH) as image2:
108+
assert image1.size == image2.size
81109

82110

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

103131

132+
def _detect_dominant_hexcolor(file):
133+
# https://stackoverflow.com/questions/3241929/python-find-dominant-most-common-color-in-an-image
134+
pilimg = Image.open(file)
135+
pilimg.convert("RGB")
136+
pilimg.resize((1, 1), resample=0)
137+
rgb_color = pilimg.getpixel((0, 0))
138+
return "{:02x}{:02x}{:02x}".format(*rgb_color)
139+
140+
104141
def test_server_fetchitem_notfound(plex):
105142
with pytest.raises(NotFound):
106143
plex.fetchItem(123456789)

0 commit comments

Comments
 (0)