问题
I'd like to place a watermark diagonally over a number of pictures. The width and length of these pictures differ and some might even be smaller than the watermark itself.
This will be used inside a script, in which the user can choose from different options like "horizontal", "vertical", "diagonal" or specify an angle by himself/herself. Therefore I need to calculate the rotation angle.
The angle should
- rotate the watermark, so that it is diagonally positioned over the underlying image.
- achieve the maximal possible size at constant proportions.
It would look something like this. (I have also drawn the diagonal.)
As you can see, the overlying picture just fits inside the underlying picture. If i'd choose an other angle, the overlying image would become smaller.
I had already calculated the diagonal of the underlying image and then the corresponding angle. The problem is that the length is not necessarily maximized, as seen here.
I'm using ImageMagick 6.8.9-9 Q16 x86_64 on Ubuntu Linux.
Here is the bash code without the calculation (as i said, it didn't work well). Please note that the code is actually executed via Python3. I find that shell commands are easier to read in bash.
for pic in *
do
# if there transparency around the picture, remove it and get the dimensions
size_ui=`convert -density 300 "$pic" -page a4 -bordercolor none -border 1x1 -trim +repage jpg:- | identify -format "%wx%h" -`
# get dimensions of the watermark (in case it changes over time)
size_wm=`identify -format "%wx%h" "wm.png"`
degree=`CALCULATE_THE_PERFECT_ANGLE`
# center the watermark, rotate it and resize it to the same size as the underlying picture
convert -density 300 "$pic" -page a4 \( "wm.png" -background none -gravity center -rotate "$degree" -resize "$size_ui" \) -compose over -composite "${pic%%.*}.jpg"
done
I am very sure that this problem has already been solved somewhere on stackoverflow, but could not find anything up to now.
Best regards
AFoeee
回答1:
Let we have base rectangle with width W
and height H
with ratio K=H/W
and rotated rectangle with unknown width and height but fixed ratio k=h/w
.
I marked similar angles f
at the picture. We can see that
H = h * cos(f) + w * sin(f)
W = h * sin(f) + w * cos(f)
or
K * W = k * w * cos(f) + w * sin(f)
W = k * w * sin(f) + w * cos(f)
divide the first by the second
K = (k * cos(f) + sin(f)) / (k * sin(f) + cos(f))
divide denominator and nominator by cos(f)
K = (k + tg(f)) / (k * tg(f) + 1)
K * (k * tg(f) + 1) = k + tg(f)
K * k * tg(f) + K = k + tg(f)
tg(f) * (1 - K * k) = K - k
and result is
tg(f) = (K - k) / (1 - K * k)
f = atan((K - k) / (1 - K * k))
Quick check: for square K=1
and for any k<1
tg(f)=1
, so f = Pi/4
(45 degrees)
Note that not all combinations of K and k have sense
回答2:
This ImageMagick command should take any input image $pic and any overlay image $wmark, rotate the overlay to $angle, resize it to fit within the input image to its largest possible dimensions, then composite the overlay centered on the input image.
convert $pic -density 300 -background none \( $wmark -rotate $angle \) \
+distort SRT \
"%[fx:(u.w<v.w&&u.h<v.h)&&t?min(min(u.w/v.w,v.w/u.w),min(u.h/v.h,v.h/u.h)):1] 0" \
-shave 1x1 \
+distort SRT \
"%[fx:(u.w>v.w||u.h>v.h)&&t?min(max(u.w/v.w,v.w/u.w),max(u.h/v.h,v.h/u.h)):1] 0" \
-shave 1x1 \
-gravity center -compose over -composite $result
That reads in your input image and sets the density, and background color. Then inside the parentheses it reads in your overlay image and rotates it $angle degrees.
After that are two "+distort" operations. Both leave the main input image as-is and conditionally scale the overlay image. The first "+distort" shrinks the overlay if it's larger than the input image. The second enlarges the overlay if it's smaller than the main input. In either case the overlay is scaled to the maximum dimensions that fit within the main input image.
Of course you'll have to set the values for the $pic, $wmark, and $angle variables before running the command. Also, if you need to do anything to the input image like a trim or resize, do that within the command but before reading in the overlay image.
Note that using "+distort" adds one pixel to every edge, so those get removed with the "-shave 1x1" after each operation.
来源:https://stackoverflow.com/questions/48399194/how-to-calculate-the-rotation-angle-for-an-overlying-image-so-that-it-just-fits