如何计算水印旋转角度,使其按比例适配底图对角线并最大化显示?
解决对角线水印最大化的问题
要实现水印沿图片对角线放置且保持最大比例,核心是计算正确的旋转角度,并根据旋转后的水印包围盒尺寸计算合适的缩放比例——而不是直接将旋转后的水印缩放到原图尺寸(这会导致水印内容被不必要地缩小)。
核心逻辑说明
- 提取尺寸:获取原图和水印的宽高参数。
- 计算对角线角度:通过原图的宽高比,用反正切函数计算出对角线的旋转角度(转换为度数)。
- 计算旋转后水印的包围盒:当水印旋转指定角度后,其外接矩形的宽高可以通过三角函数推导得出。
- 计算缩放比例:取原图与旋转后水印包围盒的宽、高比例中的较小值,确保水印缩放后刚好能放入原图且不超出边界。
- 合成水印:将缩放后的水印旋转到目标角度,再居中合成到原图上。
修改后的完整Bash脚本
#!/bin/bash # 用户可选择模式:horizontal, vertical, diagonal, 或自定义角度(如45) MODE="diagonal" for pic in * do # 跳过水印文件本身,避免循环处理 if [ "$pic" = "wm.png" ]; then continue fi # 移除图片周围透明区域并获取原图尺寸(格式:WxH) size_ui=$(convert -density 300 "$pic" -page a4 -bordercolor none -border 1x1 -trim +repage jpg:- | identify -format "%wx%h" -) W=${size_ui%x*} H=${size_ui#*x} # 获取水印尺寸(格式:wxh) size_wm=$(identify -format "%wx%h" "wm.png") w=${size_wm%x*} h=${size_wm#*x} # 根据选择的模式计算旋转角度 case $MODE in horizontal) degree=0 ;; vertical) degree=90 ;; diagonal) # 计算原图对角线角度(左上到右下方向),转换为度数 theta=$(echo "scale=10; a=atan2($H, $W); a*180/3.1415926535" | bc -l) degree=$theta ;; *) # 验证自定义角度是否为有效数字 if [[ $MODE =~ ^[0-9]+(\.[0-9]+)?$ ]]; then degree=$MODE else echo "Error: Invalid mode or angle. Use 'horizontal', 'vertical', 'diagonal', or a numeric angle." exit 1 fi ;; esac # 将角度转换为弧度,用于三角函数计算 rad_degree=$(echo "scale=10; $degree*3.1415926535/180" | bc -l) cos_theta=$(echo "scale=10; c($rad_degree)" | bc -l) sin_theta=$(echo "scale=10; s($rad_degree)" | bc -l) # 计算水印旋转后的外接矩形宽高 wm_rot_w=$(echo "scale=10; $w*$cos_theta + $h*$sin_theta" | bc -l) wm_rot_h=$(echo "scale=10; $w*$sin_theta + $h*$cos_theta" | bc -l) # 计算缩放比例(取宽高比例的较小值,确保水印能完整放入原图) scale_w=$(echo "scale=10; $W / $wm_rot_w" | bc -l) scale_h=$(echo "scale=10; $H / $wm_rot_h" | bc -l) scale=$(echo "if ($scale_w < $scale_h) $scale_w else $scale_h" | bc -l) # 计算缩放后的水印尺寸(四舍五入为整数,符合ImageMagick的尺寸要求) scaled_w=$(echo "scale=0; $w*$scale + 0.5" | bc) scaled_h=$(echo "scale=0; $h*$scale + 0.5" | bc) # 执行水印合成:缩放水印 → 旋转 → 居中叠加到原图 convert -density 300 "$pic" -page a4 \ \( "wm.png" -background none -resize "${scaled_w}x${scaled_h}" -rotate "$degree" -gravity center \) \ -compose over -composite "${pic%%.*}_watermarked.jpg" done
关键点解释
- 跳过水印文件:避免脚本循环处理水印图片本身,造成不必要的重复操作。
- 高精度角度计算:使用
bc工具进行三角函数运算,保证角度计算的准确性。 - 包围盒推导:旋转后的水印外接矩形尺寸是决定缩放比例的核心,确保水印能以最大比例适配原图。
- 缩放比例控制:取宽高比例的最小值,无论原图和水印的尺寸比例如何,都能保证水印完整放入原图且不超出边界。
- 合成顺序优化:先缩放水印再旋转,比先旋转再缩放更高效,能减少不必要的像素损失。
自定义角度说明
如果需要使用自定义角度,只需将MODE变量设置为具体的角度值(如MODE="45"),脚本会自动计算对应的缩放比例,确保水印最大化适配原图。
内容的提问来源于stack exchange,提问作者AFoeee
相关产品推荐
相关产品推荐

