Here's what I have at the moment, not fully automated yet:
These are the original images to be cropped in batch, all jpegs, all in the same folder:
The next step is to create a montage (still done manually):
montage -define jpeg:size=220x -geometry 220x220 *.jpg montage1.png
And then it's edited on GIMP:
gimp montage1.png
On GIMP, you create a new, transparent layer over the montage, and make those squiggles over the points of interest. Here's how it looks:
You can tweak the transparency of the squiggle-mask layer if that's more convenient, but it's possibly ideal to restore full opacity after finishing. But maybe the "threshold 90%" manages to deal with it regardless, I haven't yet tested.
Then you toggle the visibility of the montage itself, leaving you only with the squiggles over a transparent background (still "real transparency", rather than ImageMagick's black and white, the script takes care of that for simplicity), and you export them as "montage.png", on the same folder.
You run the script, wait a while (it's slower than I'd expected, I think I'm piping too much stuff*, possibly there are more adequate ImageMagick syntaxes to produce the same results, faster), and the result is:
Here's the humiliatingly messy and altogether ridiculous working prototype code, if anyone is interested:
Code: Select all
#!/bin/bash
# This script is free to do whatever and whatnot, except patenting and making billions with it
# No guarantees whatsoever
convert montage.png -crop 220x220 maskplain-%02d.gif
\ls -1 *.jpg > originals.txt
\ls -1 maskplain*.gif > masks.txt
#while read original <&3 && read mask <&4 ; do echo $original - $mask ; done 3<originals.txt 4<masks.txt # expression to pair originals and masks, according to file order
while read original <&3 && read mask <&4 ; do
echo $original $mask
res=($(identify -format "%w %h" {$original}))
#res2=($(identify -format "%wx%h" {$original}))
x=${res[0]}
y=${res[1]}
samplevar="${x}x"
((y>x)) && samplevar="x${y}"
expandvar="x${x}"
((y>x)) && expandvar="${y}x"
echo ${res[@]}
echo $x x $y echo $expandvar
echo $samplevar
convert <(convert $mask +repage -colorspace gray -threshold 90% -background white -alpha remove gif:-) -sample ${samplevar} /dev/shm/masktmp-${original}.gif ## GET LARGEST DIMENSION FROM ORIGINAL
cropv=`convert /dev/shm/masktmp-${original}.gif -format "%@" info:` ; convert <(convert "${original}" -gravity center -extent $expandvar jpg:-) -crop $cropv +repage "${original/.jpg/-cropped.jpg}"
# rm /dev/shm/masktmp1-$$.gif
# cool # "cool" is just a script I have that will implement an arbitrary sleep, according to CPU temperature
done 3<originals.txt 4<masks.txt
There's a lot to do in terms of organizing and cleaning temporary files and everything. Just the core logic is working.
Now it associates the original files with their crop-masks by sheer file order, which is possibly not the best solution, ideally the association would be more explicit. It requires that there are no extra jpegs added to the folder during the whole process, or between the creation of the main mask file and the execution of the script. Otherwise it will just put those new files somewhere on the line, "stealing" the crop masks of other files and making a whole mess.
I"ll gradually polish it and update the script, either here and/or on my blog at linuxquestions.org
And thanks again, fmw42!!!
* I'm particularly confused by the apparent necessity of this pipe:
cropv=`convert /dev/shm/masktmp-${original}.gif -format "%@" info:` ; convert <(convert "${original}" -gravity center -extent $expandvar jpg:-) -crop $cropv +repage "${original/.jpg/-cropped.jpg}"
I thought it should work just with:
cropv=`convert /dev/shm/masktmp-${original}.gif -format "%@" info:` ; convert "${original}" -gravity center -extent $expandvar -crop $cropv +repage "${original/.jpg/-cropped.jpg}"
But for some reason it doesn't.