PIL Drawing a semi-transparent square overlay on image

Sorry, the comment I made about it being a bug was incorrect, so...

You can do it by creating a temporary image and using Image.alpha_composite() as shown in the code below. Note that it supports semi-transparent squares other than black.

from PIL import Image, ImageDraw
from io import BytesIO
from urllib.request import urlopen

TINT_COLOR = (0, 0, 0)  # Black
TRANSPARENCY = .25  # Degree of transparency, 0-100%
OPACITY = int(255 * TRANSPARENCY)

url = "https://i.ytimg.com/vi/W4qijIdAPZA/maxresdefault.jpg"
with BytesIO(urlopen(url).read()) as file:
    img = Image.open(file)
    img = img.convert("RGBA")

# Determine extent of the largest possible square centered on the image.
# and the image's shorter dimension.
if img.size[0] > img.size[1]:
    shorter = img.size[1]
    llx, lly = (img.size[0]-img.size[1]) // 2 , 0
else:
    shorter = img.size[0]
    llx, lly = 0, (img.size[1]-img.size[0]) // 2

# Calculate upper point + 1 because second point needs to be just outside the
# drawn rectangle when drawing rectangles.
urx, ury = llx+shorter+1, lly+shorter+1

# Make a blank image the same size as the image for the rectangle, initialized
# to a fully transparent (0% opaque) version of the tint color, then draw a
# semi-transparent version of the square on it.
overlay = Image.new('RGBA', img.size, TINT_COLOR+(0,))
draw = ImageDraw.Draw(overlay)  # Create a context for drawing things on it.
draw.rectangle(((llx, lly), (urx, ury)), fill=TINT_COLOR+(OPACITY,))

# Alpha composite these two images together to obtain the desired result.
img = Image.alpha_composite(img, overlay)
img = img.convert("RGB") # Remove alpha for saving in jpg format.
img.save('dark-cat.jpg')
img.show()

Here's the result of applying it to your test image:

picture of a cat with blacken square rectangle superimposed on it


Given that I keep coming back to this issue whenever I want to draw a transparent rectangle with PIL, I decided to give an update.

Your code is pretty much working for me if I just change one thing: Save the image in the PNG format instead of JPEG.

So when I'm running

from io import BytesIO
from urllib.request import urlopen
from PIL import Image
from PIL import ImageDraw

url = "https://i.ytimg.com/vi/W4qijIdAPZA/maxresdefault.jpg"
file = BytesIO(urlopen(url).read())
img = Image.open(file)
draw = ImageDraw.Draw(img, "RGBA")
draw.rectangle(((280, 10), (1010, 706)), fill=(200, 100, 0, 127))
draw.rectangle(((280, 10), (1010, 706)), outline=(0, 0, 0, 127), width=3)
img.save('orange-cat.png')

I get this wonderful image:

cat with semi-transparent orange bounding box