I'm trying trying to use the Image.composite() function with the code below:

import Image

im1 = Image.open("GetGif1.png")
im2 = Image.open("GetGif2.png")
im3 = Image.composite('im1','im2',"L")
im.save('output.png')

But I get this error:

Traceback (most recent call last):
  File "composite_images.py", line 11, in <module>
    im3 = Image.composite('im1','im2',"L")
  File "/usr/lib/python2.5/site-packages/PIL/Image.py", line 1960, in composite
    image = image2.copy()
AttributeError: 'str' object has no attribute 'copy'

Can someone please explain what is wrong with the snippet?

Thank you

Dani AI

Generated

correctly spotted the immediate issue: the composite call needs image objects, not string names. later nailed the other point — the third argument must be an Image to act as the mask (not the literal "L"). Below is a compact checklist and a small, working pattern you can apply.

Checklist

  • All three arguments to Image.composite must be PIL Image objects (not strings).
  • Images must share the same size; resize if necessary.
  • The mask should be a single-channel image (greyscale, e.g. mode L) or an explicit alpha channel extracted from an RGBA image.
  • Convert modes explicitly (e.g. to RGBA when preserving transparency) before composing.

Practical pattern

from PIL import Image

fg = Image.open("fg.png").convert("RGBA")
bg = Image.open("bg.png").convert("RGBA")
mask = Image.open("mask.png").convert("L")   # greyscale mask, same size
mask = mask.resize(fg.size)
out = Image.composite(fg, bg, mask)
out.save("result.png")

Troubleshooting tips

  • If you see "'str' object has no attribute 'copy'", you passed string(s) instead of Image objects — print type(obj) to check.
  • If the result looks wrong, confirm img.mode and img.size for each image and convert/resize as needed.
  • For simple alpha blend use Image.blend; for min-per-channel darkening use ImageChops.darker (as switched to).
  • When working with GIFs remember opening an animated GIF gives the first frame — use ImageSequence for multiple frames and convert to RGBA if you need alpha.

This keeps the composite call predictable and avoids the common type/mode/size pitfalls.

Recommended Answers

All 2 Replies

Hi seamus.boyle,

The problem is in line 5:

im3 = Image.composite('im1','im2',"L")

See, what you're doing is sending the string literals "im1" and "im2" as arguments to the function Image.composite(). But Image.composite() doesn't want string literals - it wants actual image objects, the variables themselves! Get rid of the single quotes and you should be fine:

im3 = Image.composite(im1,im2,"L")

Hope this helps!

Thanks for the reply G-Do

I had actually just left the quotes in after doing a trial and error approach with the snippet.

The actual problem was with the third argument (the "L"). It should have been an actual Image object.

Turns out the resulting image wasn't what I was after, now I'm using the ImageChops.darker() function

If anyone is interested I'm using this code:

import Image
import ImageChops

im1 = Image.open('GetGif1.gif').convert("RGB")
im2 = Image.open('GetGif2.gif').convert("RGB")
im3 = ImageChops.darker(im1, im2)
#im3.save('output.png')
im3.show()

to replicate what I had been using in a shell script

$ composite $Symbol-gmma.gif $tmp/$$3.gif -compose darken $Symbol-gmma.gif
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.