synapse icon indicating copy to clipboard operation
synapse copied to clipboard

Thumbnailing CMYK colorspace image gives Internal Server Error

Open matrixbot opened this issue 2 years ago • 1 comments

This issue has been migrated from #10741.


When a jpeg image using the CMYK colorspace is uploaded to synapse, any attempts to get a thumbnail with the /media/r0/thumbnail endpoint return Internal Server Error. The logs contain the following exception:

synapse.http.server - 93 - ERROR - GET-393903 - Failed handle request via 'ThumbnailResource': <XForwardedForRequest at 0xffff176a5e20 method='GET' uri='/_matrix/media/r0/thumbnail/alephc.xyz/onBfeogmWNGmprAkaswiXiOC?width=64&height=64&method=crop' clientproto='HTTP/1.1' site='8008'>
Traceback (most recent call last):
  File "/home/synapse/synapse/env/lib/python3.8/site-packages/PIL/PngImagePlugin.py", line 1230, in _save
    rawmode, mode = _OUTMODES[mode]
KeyError: 'CMYK'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
  File "/home/synapse/synapse/env/lib/python3.8/site-packages/synapse/http/server.py", line 258, in _async_render_wrapper
    callback_return = await self._async_render(request)
  File "/home/synapse/synapse/env/lib/python3.8/site-packages/synapse/http/server.py", line 286, in _async_render
    callback_return = await raw_callback_return
  File "/home/synapse/synapse/env/lib/python3.8/site-packages/synapse/rest/media/v1/thumbnail_resource.py", line 69, in _async_render_GET
    await self._select_or_generate_local_thumbnail(
  File "/home/synapse/synapse/env/lib/python3.8/site-packages/synapse/rest/media/v1/thumbnail_resource.py", line 170, in _select_or_generate_local_thumbnail
    file_path = await self.media_repo.generate_local_exact_thumbnail(
  File "/home/synapse/synapse/env/lib/python3.8/site-packages/synapse/rest/media/v1/media_repository.py", line 535, in generate_local_exact_thumbnail
    t_byte_source = await defer_to_thread(
  File "/home/synapse/synapse/env/lib/python3.8/site-packages/twisted/python/threadpool.py", line 238, in inContext
    result = inContext.theWork()  # type: ignore[attr-defined]
  File "/home/synapse/synapse/env/lib/python3.8/site-packages/twisted/python/threadpool.py", line 254, in <lambda>
    inContext.theWork = lambda: context.call(  # type: ignore[attr-defined]
  File "/home/synapse/synapse/env/lib/python3.8/site-packages/twisted/python/context.py", line 118, in callWithContext
    return self.currentContext().callWithContext(ctx, func, *args, **kw)
  File "/home/synapse/synapse/env/lib/python3.8/site-packages/twisted/python/context.py", line 83, in callWithContext
    return func(*args, **kw)
  File "/home/synapse/synapse/env/lib/python3.8/site-packages/synapse/logging/context.py", line 902, in g
    return f(*args, **kwargs)
  File "/home/synapse/synapse/env/lib/python3.8/site-packages/synapse/rest/media/v1/media_repository.py", line 501, in _generate_thumbnail
    return thumbnailer.crop(t_width, t_height, t_type)
  File "/home/synapse/synapse/env/lib/python3.8/site-packages/synapse/rest/media/v1/thumbnailer.py", line 152, in crop
    return self._encode_image(cropped, output_type)
  File "/home/synapse/synapse/env/lib/python3.8/site-packages/synapse/rest/media/v1/thumbnailer.py", line 159, in _encode_image
    output_image.save(output_bytes_io, fmt, quality=80)
  File "/home/synapse/synapse/env/lib/python3.8/site-packages/PIL/Image.py", line 2235, in save
    save_handler(self, fp, filename)
  File "/home/synapse/synapse/env/lib/python3.8/site-packages/PIL/PngImagePlugin.py", line 1232, in _save
    raise OSError(f"cannot write mode {mode} as PNG") from e
OSError: cannot write mode CMYK as PNG

Accessing the image via the /media/r0/download endpoint does not have any issue.

I have attached a small image that exhibits the issue, otherwise one can be created by taking any jpeg and using image magick: convert in.jpg -colorspace cmyk.jpg

Version & Config Info

Synapse: 1.41.1, with dynamic_thumbnails: true Python: 3.8.10 Pillow: 8.3.1 Running on Ubuntu 20.04

Test Image

cmyk

matrixbot avatar Dec 19 '23 00:12 matrixbot

the related upstream library issue: https://github.com/python-pillow/Pillow/issues/1380 the application-side solution to this (png doesn't support the cymk colorspace) is to bolt this logic in:

if image_file.mode == "CMYK":
    image_file = image_file.convert("RGB")

which would resolve the problem within the mediaserver component.

wolfspyre avatar Jul 13 '24 02:07 wolfspyre