Creating an openpyxl image from a PIL image fails

Issue #644 invalid
Patrice B created an issue

Since opening an image file with openpyxl.drawing.image.Image(), with path argument Image(path) fails with IOError: cannot identify image file, I am now trying to open the image using PIL, then create openpyxl image from the PIL Image, like so:

pil_img = PILImage.open(path_to_image))
img = Image(pil_img)

This is the approach suggested by https://www.odoo.com/fr_FR/forum/aide-1/question/add-signature-image-stored-in-database-to-excel-file-91361

However, this fails too, because in openpyxl.drawing.image.py, function _import_image(img) does not recognize my image as a PILImage.

There is a test that goes like this:

if not isinstance(img, PILImage.Image):
    img = PILImage.open(img)

return img

So that if image was recognized as PILImage.Image, it would simply be returned. But the isinstance test fails because the type is JpegImageFile (or PngImageFile).

If I comment-out the isinstance test and let it return img, it works.

Maybe the test for a PILImage instance or compatible should be refined ?

(added) Actually, passing a PIL Image created with PILImage.new(...) still fails the isinstance test. Maybe the test could be reversed: if it's a string then it's probably a file path, otherwise consider it's some kind of PILImage ?

Comments (8)

  1. CharlieC

    I don't understand this issue. Can you please supply a simple test case.

    BTW. the code in the linked page depends on a very old version of openpyxl and should not be copied.

  2. Patrice B reporter

    Thank you for your reply.

    Here are 2 snippets. All with fresh install of openpyxl 2.3.5 and Pillow 3.2.0

    from openpyxl.drawing.image import Image
    from PIL import Image as PILImage
    # (...)
    wb = load_workbook(path_to_xlsx_file)
    img = Image(img_path)
    

    Fails with stacktrace:

    File "(...)/lib/site-packages/openpyxl/drawing/image.py", line 49, in __init__
      self.image = _import_image(img)
    File "(...)/lib/site-packages/openpyxl/drawing/image.py", line 36, in _import_image
      img = PILImage.open(img)
    File "(...)/lib/site-packages/PIL/Image.py", line 2309, in open
      % (filename if filename else fp))
    IOError: cannot identify image file '(path)'
    

    Second snippet:

    pil_img = PILImage.new("RGB", (512, 512), "red")
    # pil_img = PILImage.open(img_path)    would give same result
    img = Image(pil_img)
    

    Fails with stacktrace:

    File "(...)/lib/site-packages/openpyxl/drawing/image.py", line 49, in __init__
      self.image = _import_image(img)
    File "(...)lib/site-packages/openpyxl/drawing/image.py", line 36, in _import_image
      img = PILImage.open(img)
    File "(...)/lib/site-packages/PIL/Image.py", line 2279, in open
      prefix = fp.read(16)
    File "(...)/lib/site-packages/PIL/Image.py", line 632, in __getattr__
      raise AttributeError(name)
    AttributeError: read
    

    Here, it seems the PIL image object was not recognized by isinstance() test, and was considered as a path.

  3. CharlieC

    Sorry, I don't see a problem.

    from PIL import Image as PILImage
    pil_img = PILImage.new("RGB", (512, 512), "red")
    from openpyxl.drawing.image import _import_image
    _import_image(pil_img)
    <PIL.Image.Image image mode=RGB size=512x512 at 0x11075E0B8>
    
  4. Patrice B reporter

    You are right, it seems to work fine under Python console, but fails in server environment, which is google_appengine development (and same problem in production). So the issue is probably related to this environment, although I don't see in what way.

  5. Log in to comment