wagtail / Willow

A wrapper that combines the functionality of multiple Python image libraries into one API
https://willow.wagtail.org/
BSD 3-Clause "New" or "Revised" License
274 stars 53 forks source link

Image save on Google App Engine PIL #49

Closed erdem closed 2 years ago

erdem commented 7 years ago

I got an error on GAE using with Willow 0.4. When wagtail thumbnail backend processing an image, PIL can't save the image.

Error logs:

hero_header.html, error at line 22
   encoder error -2 when writing image file

   22 :      {% responsiveimage value.image width-1280 srcset="width-650 650w, width-1100 1100w, width-1600 1600w, width-1900 1900w" as image %} 

Traceback:

File "/base/data/home/apps/s~project-v2-staging/1.398769727526236024/sitepackages/prod/django/core/handlers/base.py" in get_response
  174.                     response = self.process_exception_by_middleware(e, request)

File "/base/data/home/apps/s~project-v2-staging/1.398769727526236024/sitepackages/prod/django/core/handlers/base.py" in get_response
  172.                     response = response.render()

File "/base/data/home/apps/s~project-v2-staging/1.398769727526236024/sitepackages/prod/django/template/response.py" in render
  160.             self.content = self.rendered_content

File "/base/data/home/apps/s~project-v2-staging/1.398769727526236024/sitepackages/prod/django/template/response.py" in rendered_content
  137.         content = template.render(context, self._request)

File "/base/data/home/apps/s~project-v2-staging/1.398769727526236024/sitepackages/prod/django/template/backends/django.py" in render
  95.             return self.template.render(context)

File "/base/data/home/apps/s~project-v2-staging/1.398769727526236024/sitepackages/prod/django/template/base.py" in render
  206.                     return self._render(context)

File "/base/data/home/apps/s~project-v2-staging/1.398769727526236024/sitepackages/prod/django/template/base.py" in _render
  197.         return self.nodelist.render(context)

File "/base/data/home/apps/s~project-v2-staging/1.398769727526236024/sitepackages/prod/django/template/base.py" in render
  992.                 bit = node.render_annotated(context)

File "/base/data/home/apps/s~project-v2-staging/1.398769727526236024/sitepackages/prod/django/template/base.py" in render_annotated
  959.             return self.render(context)

File "/base/data/home/apps/s~project-v2-staging/1.398769727526236024/sitepackages/prod/django/template/loader_tags.py" in render
  173.         return compiled_parent._render(context)

File "/base/data/home/apps/s~project-v2-staging/1.398769727526236024/sitepackages/prod/django/template/base.py" in _render
  197.         return self.nodelist.render(context)

File "/base/data/home/apps/s~project-v2-staging/1.398769727526236024/sitepackages/prod/django/template/base.py" in render
  992.                 bit = node.render_annotated(context)

File "/base/data/home/apps/s~project-v2-staging/1.398769727526236024/sitepackages/prod/django/template/base.py" in render_annotated
  959.             return self.render(context)

File "/base/data/home/apps/s~project-v2-staging/1.398769727526236024/sitepackages/prod/django/template/loader_tags.py" in render
  69.                 result = block.nodelist.render(context)

File "/base/data/home/apps/s~project-v2-staging/1.398769727526236024/sitepackages/prod/django/template/base.py" in render
  992.                 bit = node.render_annotated(context)

File "/base/data/home/apps/s~project-v2-staging/1.398769727526236024/sitepackages/prod/django/template/base.py" in render_annotated
  959.             return self.render(context)

File "/base/data/home/apps/s~project-v2-staging/1.398769727526236024/sitepackages/prod/django/template/defaulttags.py" in render
  220.                     nodelist.append(node.render_annotated(context))

File "/base/data/home/apps/s~project-v2-staging/1.398769727526236024/sitepackages/prod/django/template/base.py" in render_annotated
  959.             return self.render(context)

File "/base/data/home/apps/s~project-v2-staging/1.398769727526236024/sitepackages/prod/django/template/base.py" in render
  1049.         return render_value_in_context(output, context)

File "/base/data/home/apps/s~project-v2-staging/1.398769727526236024/sitepackages/prod/django/template/base.py" in render_value_in_context
  1026.     value = force_text(value)

File "/base/data/home/apps/s~project-v2-staging/1.398769727526236024/sitepackages/prod/django/utils/encoding.py" in force_text
  78.                 s = six.text_type(s)

File "/base/data/home/apps/s~project-v2-staging/1.398769727526236024/sitepackages/prod/wagtail/wagtailcore/blocks/base.py" in __str__
  524.         return self.block.render(self.value)

File "/base/data/home/apps/s~project-v2-staging/1.398769727526236024/sitepackages/prod/wagtail/wagtailcore/blocks/base.py" in render
  296.         return mark_safe(render_to_string(template, new_context))

File "/base/data/home/apps/s~project-v2-staging/1.398769727526236024/sitepackages/prod/django/template/loader.py" in render_to_string
  97.         return template.render(context, request)

File "/base/data/home/apps/s~project-v2-staging/1.398769727526236024/sitepackages/prod/django/template/backends/django.py" in render
  95.             return self.template.render(context)

File "/base/data/home/apps/s~project-v2-staging/1.398769727526236024/sitepackages/prod/django/template/base.py" in render
  206.                     return self._render(context)

File "/base/data/home/apps/s~project-v2-staging/1.398769727526236024/sitepackages/prod/django/template/base.py" in _render
  197.         return self.nodelist.render(context)

File "/base/data/home/apps/s~project-v2-staging/1.398769727526236024/sitepackages/prod/django/template/base.py" in render
  992.                 bit = node.render_annotated(context)

File "/base/data/home/apps/s~project-v2-staging/1.398769727526236024/sitepackages/prod/django/template/base.py" in render_annotated
  959.             return self.render(context)

File "/base/data/home/apps/s~project-v2-staging/1.398769727526236024/apps/core/templatetags/responsive_image.py" in render
  55.             rendition = image.get_rendition(self.filter)

File "/base/data/home/apps/s~project-v2-staging/1.398769727526236024/sitepackages/prod/wagtail/wagtailimages/models.py" in get_rendition
  278.             generated_image = filter.run(self, BytesIO())

File "/base/data/home/apps/s~project-v2-staging/1.398769727526236024/sitepackages/prod/wagtail/wagtailimages/models.py" in run
  464.                 return willow.save_as_jpeg(output, quality=quality, progressive=True, optimize=True)

File "/base/data/home/apps/s~project-v2-staging/1.398769727526236024/sitepackages/prod/willow/plugins/pillow.py" in save_as_jpeg
  73.         image.save(f, 'JPEG', quality=quality, **kwargs)

File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/PIL-1.1.7/PIL/Image.py" in save
  1439.             save_handler(self, fp, filename)

File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/PIL-1.1.7/PIL/JpegImagePlugin.py" in _save
  471.     ImageFile._save(im, fp, [("jpeg", (0,0)+im.size, 0, rawmode)])

File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/PIL-1.1.7/PIL/ImageFile.py" in _save
  491.                 raise IOError("encoder error %d when writing image file" % s)

Exception Type: IOError at /products/
Exception Value: encoder error -2 when writing image file

I solved this problem by removing optimize and progressive parameters on pillow plugin save methods. Like this:https://github.com/codeandtheory/Willow/commit/4e5010b7f16ef09c38ad46236a380db5752dcba5

Thanks

gasman commented 7 years ago

Hi @erdem,

PIL 1.1.7 (i.e. the original Pythonware package which was later forked into Pillow) is not a supported backend for Willow. I understand this will be an issue for Google App Engine users, as it's the only option available there - however, it's not really practical for Willow to implement workarounds for bugs in an old abandoned library, and it would be much more effective for Google to update their supported versions.

(Incidentally - is this happening for all JPEG images, or just a specific one?)

erdem commented 7 years ago

Hi @gasman

Thank you for explanation. It is seems to be no more solution for this issue except wait for the google update.

The problem happening only JPEG images as far as I can see. PNG images working fine.