Splitting an image in half, leaving one half transparent, keeping the same image dimensions

Question:

I have an image, I want to split it vertically. When I do this I want to maintain the same aspect ratio (1024×1024), but make the other half of each image transparent. (Imagine going into photoshop, and just deleting half of an image leaving the transparent mask.)

I used image slicer to easily slice in half vertically. Then PIL to paste a new image. I get the ValueError: images do not match, and so I was wondering if there is an easier way.

from image_slicer import slice

from PIL import Image

slice('stickfigure.png', 2)

img = Image.open("stickfigure_01_01.png")
img.show()

img2 = Image.open("stickfigure_01_02.png")
img2.show()


background = Image.open("emptycanvas.png")
foreground = Image.open("stickfigure_01_01.png")

final = Image.new("RGBA", background.size)
final = Image.alpha_composite(final, background)
final = Image.alpha_composite(final, foreground)

Emptycanvas is just a 1024×1024 blank transparent png.

Asked By: ati

||

Answers:

You don’t really actually want to split the image in half, since you want to retain the original dimensions. So you actually just want to make one half transparent – remember the alpha/transparency is just a layer in your image, so all you need is a new, alpha layer that is white where you want to see the original image and black where you don’t.

So, let’s make a radial gradient, get its size, and make a new black alpha channel the same size. Then draw a white rectangle on the left half and push that into your image as the alpha/transparency channel:

#!/usr/bin/env python3

from PIL import Image, ImageDraw

# Create radial gradient, and get its dimensions
im = Image.radial_gradient('L')
w, h = im.size
im.save('DEBUG-initial.png')

enter image description here

# Create single channel alpha/transparency layer, same size, initially all black
alpha = Image.new('L', (w,h))
draw  = ImageDraw.Draw(alpha)

# Fill left half with white
draw.rectangle((0,0,int(w/2),h), fill='white')
alpha.save('DEBUG-alpha.png')

enter image description here

# Push that alpha layer into gradient image
im.putalpha(alpha)
im.save('result.png')

enter image description here


Note that as you didn’t supply any representative image, I don’t know whether your image already had some transparency, and if it did, this simple method will replace it throughout the image. If that is the case, you should extract the existing transparency from the image and draw onto that, rather than assuming you can replace the transparency wholesale like I did. You can use either of the following approaches:

R,G,B,A = im.split()    
#
# modify A here
#
result = Image.merge('RGBA', (R,G,B,A))

or

alpha = im.getchannel('A')
#
# modify alpha here
# 
im.putalpha(A)

Although you didn’t mention it in your question, it seems you not only want to make one half transparent, but also want to move the remaining visible part to the other side!

You need to add this near the start to copy the right half:

# Copy right half
rhs = im.crop((int(w/2),0,w,h))

and this near the end to paste the copied right half into the left half:

im.paste(rhs, (0,0))
Answered By: Mark Setchell