简体   繁体   中英

How to use PIL (Python Image Library) rotate image and let black background to be transparency

I want to rotate a gray "test" image and paste it onto a blue background image. Now I just can remove the black color after rotate my gray "test" image, but their is now a white color section. How can I use Python to change the "white" color section to blue?

Here is my code, can someone help me? I'd appreciate it.

dst_im = Image.new("RGBA", (196,283), "blue" )
im = src_im.convert('RGBA')
rot = im.rotate( angle, expand=1 ).resize(size)
f = Image.new( 'RGBA', rot.size, (255,)*4 )
im2 = Image.composite( rot, f, rot )
im2.convert(src_im.mode)
im2_width, im2_height = im2.size
cut_box = (0, 0, im2_width, im2_height )
paste_box = ( left, top, im2_width+left, im2_height+top )
region = im2.crop( cut_box )
dst_im.paste( region, paste_box )
dst_im.save("test.gif")

在此输入图像描述

I have the impression that your code could be simplified as follows:

from PIL import Image

src_im = Image.open("winter3.jpg")
angle = 45
size = 100, 100

dst_im = Image.new("RGBA", (196,283), "blue" )
im = src_im.convert('RGBA')
rot = im.rotate( angle, expand=1 ).resize(size)
dst_im.paste( rot, (50, 50), rot )
dst_im.save("test.png")

This gives the following result:

在此输入图像描述

Another answer using PIL is clearly more succinct. I had a similar problem and had the image in an ndarray. Yipes, mine came out way more complicated than user1202136. I'm posting it only because it demonstrates another solution using numpy and array stacking, but user1202136's solution is much better.

    import matplotlib.pyplot as plt
    import numpy as np
    import scipy.ndimage 



    def rgba(rgb_img, alpha):
        '''
        ' takes an rgb ndarray r x c x 3 of dtype=uint8
        ' and adds an alpha 0-255 to each pixel
        '''
        rows = len(rgb_img)                                # get image dimensions
        columns = len(rgb_img[0])
        rgb_flat = rgb_img.reshape([rows * columns, 3])    # list of rgb pixels
        a = np.zeros([rows*columns, 1], dtype=np.uint8)  # alpha for each pixel
        a.fill(alpha)
        rgba = np.column_stack([rgb_flat, a])              # place 4th column
        return rgba.reshape([rows, columns, 4])           # reform into r x c x 4

    def pad_with_transparent_pixels(rgba_img):
        '''
        ' takes an rgba image r x c
        ' and places within a buffer of [ 0 0 0 0] to become square,
        ' with sides = diagonal of img
        '''
        rows = len(rgba_img)                                # get image dimensions
        columns = len(rgba_img[0])
        diag = (rows**2 + columns**2)**0.5
        diag = int(diag) + 1
        top_pad_height = (diag-rows)/2 + 1
        left_pad_width = (diag-columns)/2 + 1
        top_pad = np.zeros([top_pad_height, diag, 4], dtype=np.uint8)
        left_pad = np.zeros([rows, left_pad_width, 4], dtype=np.uint8)
        right_pad = np.zeros([rows, 
                              # assures total width of top_pad for row_stack:
                              diag - left_pad_width - columns, 
                              4 ], 
                             dtype=np.uint8)
        center = np.column_stack([left_pad, rgba_img, right_pad])
        return np.row_stack([top_pad, center, top_pad])

    def clean_rotate(rgba_img,angle):
        rows = len(rgba_img)
        columns = len(rgba_img[0])
        diag = (rows**2 + columns**2)**.5
        diag = int(diag)
        pad_img = pad_with_transparent_pixels(rgba_img)
        rot_img = scipy.ndimage.rotate(pad_img, angle)
        rot_img_rows = len(rot_img)
        rot_img_columns = len(rot_img[0])
        crop_side = max(1,(rot_img_columns - diag) / 2) #max to avoid splicing [:0]
        crop_top = max(1,(rot_img_rows - diag) / 2)
        print diag, crop_side, crop_top
        return rot_img[crop_top:-crop_top,crop_side:-crop_side]

    img = plt.imread('C:\\Users\\bbrown\\Desktop\\Maurine.jpg') # read in a jpg

    figure, axes = plt.subplots(1, 2)              # create 1x2 grid of axes
    axes[0].imshow(img)                            # place image on first axes
    rgba_image = rgba(img, 255)                      # create an opaque rgba image
    rot_img = clean_rotate(rgba_image,50)

    #make a pattern of 10 images
    for i in range(10):
        rot_img = clean_rotate(rgba_image,5*i)
        axes[1].imshow(rot_img)
        plt.show()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM