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

MissingDelegateError: no decode delegate for this image format `/tmp/magick-FTfvbM7n' @ error/constitute.c/ReadImage/544 #53

Open thenewguy opened 7 years ago

thenewguy commented 7 years ago

I am running into an issue I cannot figure out.

Here is the traceback:

======================================================================
ERROR: test_wand_image_reads_gif (wagtailimages_autoformat.tests.test_requirements.TestRequirements)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/wagtailimages_autoformat/tests/test_requirements.py", line 22, in test_wand_image_reads_gif
    self.assertIsInstance(image.get_wand_image(), WandImage)
  File "/usr/local/lib/python2.7/dist-packages/willow/image.py", line 60, in wrapper
    image = converter(image)
  File "/usr/local/lib/python2.7/dist-packages/willow/plugins/wand.py", line 124, in open
    image = _wand_image().Image(file=image_file.f)
  File "/usr/local/lib/python2.7/dist-packages/wand/image.py", line 2740, in __init__
    self.read(file=file, resolution=resolution)
  File "/usr/local/lib/python2.7/dist-packages/wand/image.py", line 2822, in read
    self.raise_exception()
  File "/usr/local/lib/python2.7/dist-packages/wand/resource.py", line 222, in raise_exception
    raise e
MissingDelegateError: no decode delegate for this image format `/tmp/magick-r2MTTG6x' @ error/constitute.c/ReadImage/544

Here is a copy of the tests:

from django.contrib.staticfiles import finders
from django.test import TestCase
from willow.plugins.pillow import PillowImage
from willow.plugins.wand import WandImage, _wand_image
from willow.image import Image

class TestRequirements(TestCase):
    def test_wand_image_checks(self):
        # wand is required for animated gifs
        WandImage.check()

    def test_pillow_image_checks(self):
        PillowImage.check()

    def test_wand_image_reads_gif(self):
        path = finders.find('wagtailimages_autoformat/tests/ajax-loader.gif')
        image = Image.open(open(path, 'rb'))
        self.assertIsInstance(image.get_wand_image(), WandImage)

    def test_wand_gif_path_directly(self):
        path = finders.find('wagtailimages_autoformat/tests/ajax-loader.gif')
        with _wand_image().Image(filename=path) as i:
            self.assertEqual(i.animation, True)
            self.assertEqual(i.size, (32, 32))

    def test_wand_gif_file_directly(self):
        path = finders.find('wagtailimages_autoformat/tests/ajax-loader.gif')
        with _wand_image().Image(file=open(path, 'rb')) as i:
            self.assertEqual(i.animation, True)
            self.assertEqual(i.size, (32, 32))

Note that using wand directly has no issues with the file. Only when using the willow api to open the file with wand. See tests test_wand_gif_path_directly and test_wand_gif_file_directly. This error occurs with your 'newtons_cradle.gif' test file as well so it isn't specific to my file or I would upload it as well.

    def test_wand_image_reads_gif(self):
        #path = finders.find('wagtailimages_autoformat/tests/ajax-loader.gif')
        path = finders.find('wagtailimages_autoformat/tests/newtons_cradle.gif')
        with open(path, 'rb') as f:
            image = Image.open(f)
            self.assertIsInstance(image, Image)
            self.assertIsInstance(image.get_wand_image(), WandImage)
            self.assertTrue(image.get_wand_image().has_animation())

Have you encountered this before and what other information can I provide to help narrow this down?

Here is a list of my installed packages:

pip freeze
amqp==1.4.9
anyjson==0.3.3
appdirs==1.4.3
asn1crypto==0.22.0
Babel==2.4.0
backports.ssl-match-hostname==3.5.0.1
beautifulsoup4==4.5.3
billiard==3.3.0.23
boto3==1.4.4
botocore==1.5.38
brotlipy==0.6.0
celery==3.1.25
certifi==2017.1.23
cffi==1.10.0
configparser==3.5.0
coverage==4.3.4
cryptography==1.8.1
csscompressor==0.9.4
Django==1.10.7
django-appconf==1.0.2
django-cachalot==1.4.1
django-classy-tags==0.8.0
django-compressor==2.1.1
django-db-locking==1.2.1
django-modelcluster==3.1
django-randomfields==0.1.7
django-sekizai==0.10.0
django-taggit==0.22.0
django-treebeard==4.1.0
djangorestframework==3.6.2
docutils==0.13.1
elasticsearch==5.3.0
enum34==1.1.6
flake8==3.3.0
flower==0.9.1
funcsigs==1.0.2
futures==3.0.5
html5lib==0.9999999
idna==2.5
ipaddress==1.0.18
isort==4.2.5
Jinja2==2.9.6
jmespath==0.9.2
jobtastic==0.3.1
kombu==3.0.37
librabbitmq==1.6.1
lxml==3.7.3
MarkupSafe==1.0
mccabe==0.6.1
mock==2.0.0
olefile==0.44
packaging==16.8
pbr==2.0.0
Pillow==4.1.0
psutil==3.4.2
psycopg2==2.7.1
pycodestyle==2.3.1
pycparser==2.17
pyflakes==1.5.0
Pygments==1.6
pyOpenSSL==16.2.0
pyparsing==2.2.0
python-dateutil==2.6.0
python-memcached==1.58
pytz==2017.2
rcssmin==1.0.6
requests==2.13.0
rjsmin==1.0.12
roman==2.0.0
s3transfer==0.1.10
six==1.10.0
Sphinx==1.2.2
tornado==4.2
Unidecode==0.4.20
urllib3==1.20
uWSGI==2.0.15
wagtail==1.9
Wand==0.4.4
whitenoise==3.3.0
Willow==0.4

Running in a Docker container based on Ubuntu 14.04 and pillow/wand deps are installed this way: apt-get build-dep -y python-pil python-wand

kaedroho commented 7 years ago

Sounds like ImageMagick wasn't compiled with the right delegates to read the file.

To check, try running convert -list configure and search for the line that starts with DELEGATES.

Mine is: DELEGATES bzlib mpeg fontconfig freetype gslib jng jpeg lcms lqr lzma openexr openjp2 pango png ps rsvg tiff webp wmf x xml zlib

thenewguy commented 7 years ago

This is the result:

# convert -list configure | grep -i 'delegates'
DELEGATES     bzlib djvu fftw fontconfig freetype jbig jpeg jng jp2 lcms2 lqr lzma openexr pango png rsvg tiff x11 xml wmf zlib

Several differences... happen to know which one is offending? I didn't think it was a problem since wand can directly open the gif file but wasn't thinking that willow could be using a different conversion format

thenewguy commented 7 years ago

I think I figured it out. Looks like the issue is write buffering. The error message sent me in the wrong direction. I am not sure how to write a test for it... any ideas?

This works:

from willow.plugins.wand import WandImage
from willow.registry import registry
from willow.image import GIFImageFile

def flush_before_conversion(image_file):
    image_file.f.flush()
    return WandImage.open(image_file)

registry.register_converter(GIFImageFile, WandImage, flush_before_conversion, cost=1)
jamieduk commented 6 years ago

As you can see, I have an issue :+1: convert -list configure | grep -i 'delegates' DELEGATES mpeg ps

i need all common filetypes like jpeg png bmp all of them help please I need a quick and easy idiot proof way of doing this! a script would be nice to automate it? help me someone!

kvnptl commented 5 years ago

Download "Synaptic Package Manager" from ubuntu software center. remove older packages and reinstall broken packages from there. If your lib* package not available in your system, then install it from Synaptic package manager. Hope it helps :)