一直觉得 mac 的截图效果非常好看,之前在 ArchLinux 上用 imagemagick 撸了一个类似的,最近在体验 windows 11,顺便也移植了一份。
想要对剪切板图片进行修改首先就要能获取剪切板的图片和向剪切板发送图片,在运行 Xorg 的 Linux 上可以很方便地使用 xclip 来操作
# get image from clipboard
xclip -selection clipboard -t image/png -o > /tmp/src.webp
# send image to clipboard
xclip -selection clipboard -t image/png -i /tmp/des.webp
但在 windows 11 上该如何获取呢?我先是查询了 powershell 的相关 API,然后我发现有现成的 Get-Clipboard 和 Set-Clipboard 两个模块函数可用
# get image from clipboard
$img = Get-Clipboard -Format Image
但很可惜我发现 Get-Content path/to/file | Set-Clipboard
对文本是可以的,但是对图片却会乱码,在网上查询也没找到相关解释,于是我换了一种设置剪切板的方法
# send result to clipboard
Add-Type -Assembly System.Windows.Forms
Add-Type -Assembly System.Drawing
$img = [Drawing.Image]::FromFile($result_image)
[Windows.Forms.Clipboard]::SetImage($img)
我也查询了一下 python 基于 PIL 和 win32clipboard 的操作方法
from PIL import ImageGrab
from io import BytesIO
import win32clipboard
# get image from clipboard
image = ImageGrab.grabclipboard()
# send image to clipboard
output = BytesIO()
border_image.convert('RGB').save(output, 'BMP')
data = output.getvalue()[14:]
output.close()
win32clipboard.OpenClipboard()
win32clipboard.EmptyClipboard()
win32clipboard.SetClipboardData(win32clipboard.CF_DIB, data)
win32clipboard.CloseClipboard()
对于图片的处理首先想到的就是 imagemagick 这个工具了,在 Linux 使用非常简单
先加圆角,我这里使用的圆角弧度为 8
convert /tmp/src.webp \
\( +clone -alpha extract \
-draw 'fill black polygon 0,0 0,8 8,0 fill white circle 8,8 8,0' \
\( +clone -flip \) -compose Multiply -composite \
\( +clone -flop \) -compose Multiply -composite \
\) -alpha off -compose CopyOpacity -composite /tmp/output.webp
再加阴影和边框,我设置的边框为 20px,这是为了配合我的水印图片
convert /tmp/output.webp -bordercolor none -border 20 \( +clone -background black -shadow 100x15+0+0 \) \
+swap -background transparent -layers merge +repage /tmp/des.webp
再加上自己的水印
composite -gravity SouthEast ~/.local/bin/watermark.webp /tmp/des.webp /tmp/des.webp
但我在 powershell 上尝试使用 imagemagick 的时候发现参数识别出现了问题,+clone 没认出来,还好 win 11 窗口自带阴影和圆角,那我只要打一下水印就好了
$cmd = "composite -gravity SouthEast $watermark $source_image $result_image"
Invoke-Expression $cmd
在 scoop 安装 imagemagick 的时候我发现还引入了 ffmpeg 这个依赖包,我虽然也经常用它,但毕竟还是有点大,于是我尝试用 PIL 来处理图片。
先加一下边框,我是 nord 配色的忠实用户,所以选用了 “#2E3440” 同时也是我桌面壁纸的主要颜色,这是我用 k-means 算法写的一个提取图片主要颜色的脚本。
# add border
border = 20 # border size
border_color = "#2E3440" # border color
border_image = Image.new("RGBA", (image.width + border, image.height + border), border_color)
align = int(border / 2)
border_image.paste(image, (align, align))
然后添加水印
# add watermark
watermark = Image.open(r"C:\Users\zjuyk\Desktop\watermark.webp")
watermark = watermark.convert("RGBA")
border_image.paste(watermark, (border_image.width - watermark.width, border_image.height - watermark.height), watermark)
在尝试添加圆角的时候我发现,锯齿非常严重,严重影响美观度,所以没有放进脚本里,阴影也是一样,我打算全用 windows 11 自带的窗口阴影和圆角。如果非要自己实现的话,我建议准备几张 mask image
来做图片遮罩。
#!/bin/bash -e
# Get the picture from flameshot
flameshot gui -r > /tmp/src.webp
wait $!
# Get the picture from scrot
# scrot --select "/tmp/src.webp"
# wait $!
# xclip -selection clipboard -t image/png -o > /tmp/src.webp
# add shadow, round corner, border and watermark
convert /tmp/src.webp \
\( +clone -alpha extract \
-draw 'fill black polygon 0,0 0,8 8,0 fill white circle 8,8 8,0' \
\( +clone -flip \) -compose Multiply -composite \
\( +clone -flop \) -compose Multiply -composite \
\) -alpha off -compose CopyOpacity -composite /tmp/output.webp
convert /tmp/output.webp -bordercolor none -border 20 \( +clone -background black -shadow 100x15+0+0 \) \
+swap -background transparent -layers merge +repage /tmp/des.webp
composite -gravity SouthEast ~/.local/bin/watermark.webp /tmp/des.webp /tmp/des.webp
# Send the picture to clipboard
xclip -selection clipboard -t image/png -i /tmp/des.webp
# remove the left pictures
rm /tmp/src.webp /tmp/des.webp /tmp/output.webp
# Please add execution policy
# Set-ExecutionPolicy Unrestricted
# get image from clipboard
$img = Get-Clipboard -Format Image
if ($img -eq $null) {
Write-Host "Clipboard contains no image."
Exit
}
# save it to desktop
$img.Save("C:\Users\zjuyk\Desktop\src.webp")
# add watermark
$watermark = "C:\Users\zjuyk\Desktop\watermark.webp"
$source_image = "C:\Users\zjuyk\Desktop\src.webp"
$result_image = "C:\Users\zjuyk\Desktop\res.webp"
$cmd = "composite -gravity SouthEast $watermark $source_image $result_image"
Invoke-Expression $cmd
# send result to clipboard
Add-Type -Assembly System.Windows.Forms
Add-Type -Assembly System.Drawing
$img = [Drawing.Image]::FromFile($result_image)
[Windows.Forms.Clipboard]::SetImage($img)
# remove temp files (do it manually)
Remove-Item "C:\Users\zjuyk\Desktop\src.webp" -Force
# Remove-Item "C:\Users\zjuyk\Desktop\res.webp" -Force
from PIL import ImageGrab, Image
from io import BytesIO
import win32clipboard
if __name__ == "__main__":
# get image from clipboard
image = ImageGrab.grabclipboard()
# add border
border = 20 # border size
border_color = "#2E3440" # border color
border_image = Image.new("RGBA", (image.width + border, image.height + border), border_color)
align = int(border / 2)
border_image.paste(image, (align, align))
# add watermark
watermark = Image.open(r"C:\Users\zjuyk\Desktop\watermark.webp")
watermark = watermark.convert("RGBA")
border_image.paste(watermark, (border_image.width - watermark.width, border_image.height - watermark.height), watermark)
# send image to clipboard
output = BytesIO()
border_image.convert('RGB').save(output, 'BMP')
data = output.getvalue()[14:]
output.close()
win32clipboard.OpenClipboard()
win32clipboard.EmptyClipboard()
win32clipboard.SetClipboardData(win32clipboard.CF_DIB, data)
win32clipboard.CloseClipboard()