跳至内容

Python 图像库/阴影

来自维基教科书,开放的书籍,为开放的世界

阴影是强调图像的一种常见方式。

创建阴影

[编辑 | 编辑源代码]

阴影可以通过获取一个简单的实心矩形(通常为黑色或灰色,但你也可以使用彩色阴影)并重复对其应用 ImageFilter BLUR 滤镜来创建。此滤镜使用 5×5 核,因此一次迭代不会产生平滑的模糊效果。你可以通过实验找到适合你目的的最佳迭代次数。

def makeShadow(image, iterations, border, offset, backgroundColour, shadowColour):
    # image: base image to give a drop shadow
    # iterations: number of times to apply the blur filter to the shadow
    # border: border to give the image to leave space for the shadow
    # offset: offset of the shadow as [x,y]
    # backgroundCOlour: colour of the background
    # shadowColour: colour of the drop shadow
    
    #Calculate the size of the shadow's image
    fullWidth  = image.size[0] + abs(offset[0]) + 2*border
    fullHeight = image.size[1] + abs(offset[1]) + 2*border
    
    #Create the shadow's image. Match the parent image's mode.
    shadow = Image.new(image.mode, (fullWidth, fullHeight), backgroundColour)
    
    # Place the shadow, with the required offset
    shadowLeft = border + max(offset[0], 0) #if <0, push the rest of the image right
    shadowTop  = border + max(offset[1], 0) #if <0, push the rest of the image down
    #Paste in the constant colour
    shadow.paste(shadowColour, 
                [shadowLeft, shadowTop,
                 shadowLeft + image.size[0],
                 shadowTop  + image.size[1] ])
    
    # Apply the BLUR filter repeatedly
    for i in range(iterations):
        shadow = shadow.filter(ImageFilter.BLUR)

    # Paste the original image on top of the shadow 
    imgLeft = border - min(offset[0], 0) #if the shadow offset was <0, push right
    imgTop  = border - min(offset[1], 0) #if the shadow offset was <0, push down
    shadow.paste(image, (imgLeft, imgTop))

    return shadow

首先,让我们忽略最后一步,专注于阴影。让我们看看不同迭代次数的结果。边框设置为 8,背景为白色,阴影为 0x444444 灰色。初始图像为 30×30 像素。

1 次迭代 2 次迭代 3 次迭代 5 次迭代 10 次迭代

请注意,阴影始终包含在图像边界内 - 这是因为蓝色滤镜“碰到”图像边界造成的。如果边框更大,你会看到在大量迭代次数下模糊会散开。

现在,我们可以添加最后一部分并尝试一下。结果如下。此图像使用了 [3,3] 的偏移量,进行了 3 次迭代,颜色与之前相同。

原始图像(SVG 被制作成了矩形 PNG) 带有阴影的最终图像

生成模糊阴影所需的计算量很大,特别是对于大型图像或多次迭代,但相同的阴影可以重复用于相同大小的任何图像。因此,如果你要创建许多相同大小的图像块,则一次计算阴影并将其重复用于每个图像将是有益的。

你还可以通过识别阴影的中心将是阴影颜色的平面填充来加快阴影的计算 - 只需计算边缘即可。较亮边框向内延伸的距离取决于迭代次数。对于大型图像,此更改将问题从图像大小的二次方(即宽度加倍,时间乘以四倍)减少到线性(宽度加倍,时间加倍),但对于图标来说不太可能产生很大影响。

处理非矩形图像

[编辑 | 编辑源代码]

添加透明度

[编辑 | 编辑源代码]
华夏公益教科书