Page 1 of 1

Improve windowsbatch handling of portrait & landscape images

Posted: 2014-02-01T08:55:44-07:00
by michaelmahoney
I'd like to improve my handling of a series of images of varied portrait/landscape orientation as well as varied aspect ratio.

I'm currently handling this by resizing everything to an arbitrary width of 800px, using the -wave operator, and the resizing again down to thumbnail size, as follows:

Code: Select all

FOR %a IN (*.jpg) DO convert %a[800x] -auto-orient -background none -wave 10x1600 -chop 0x10 -resize 290x290 %athumb.png
This works satisfactorily but requires an extra -resize operation, which I'd like to lose. What's the best way?

I can see a few possibilities. The issue is that I need to know the image width in pixels to tell -wave how to shear the image. Here are the Ideas I have:

1. Drop the command line into a batch file and use that to first interrogate IM for the image width, second drop the width into an environment variable, and third use that to calculate and supply the width (x2) to -wave. The problem is that I can't get this to work in a batch file- see my topic, "Getting command line to work in windows batch file."

2. Some way I haven't figured out of supplying the image width to -wave, perhaps using fx. I haven't managed to get this to work, though I noticed an example where it was done apparently to supply a value to -rotate:

Code: Select all

\( -clone 0 -rotate `convert null: -format '%[fx:rand()*30-15]' info:` \) \
which is a unix solution but looks adaptable from the following: viewtopic.php?t=15352&p=54189.

just using a percent escape to provide the width x2 to -wave doesn't work... am I missing something?

I'm new to IM but confident I can get it to work... eventually. Some advice on how best to proceed would be very helpful and appreciated.

Much thanks!

Mike

Re: Improve windowsbatch handling of portrait & landscape im

Posted: 2014-02-01T11:23:52-07:00
by fmw42
just using a percent escape to provide the width x2 to -wave doesn't work... am I missing something?
That is true. There are only a few functions that allow escapes or fx calculation to be used as argument. They are primarily -distort function and there is no equivalent to -wave that I know about.

In the unix command you referenced, there is an implicit second convert imbedded in the same command line. So it looks like one command, but is really not.

In unix, this would be

# full width=64, so one full wavelength
convert koala.gif -background blue -wave 10x64 show:
vs
# double width=128, so only 1/2 wavelength
convert koala.gif -background blue -wave 10x$(convert koala.gif -format "%[fx:2*w]" info:) show:


You likely will need to make a multi-line script to do what you want so that you can compute the arguments from the file sizes as variables and feed that to -wave.

IM 7 will allow you to do more of that kind of thing in-line. So might try the IM 7 alpha.

Re: Improve windowsbatch handling of portrait & landscape im

Posted: 2014-02-01T11:30:51-07:00
by snibgo
To get the width and height, I generally use something like this:

Code: Select all

FOR /F "usebackq" %%L IN (`%IM%identify -format "WW=%%w\nHH=%%h" x.jpg`) DO set %%L
If you need double the width, either use "set /A WW2=%WW%*2" or:

Code: Select all

FOR /F "usebackq" %%L IN (`%IM%identify -format "WW=%%w\nHH=%%h\nWW2=%%[fx:w*2]" x.jpg`) DO set %%L
EDIT: Corrected my typo, changing %W% to %WW%.

Re: Improve windowsbatch handling of portrait & landscape im

Posted: 2014-02-05T08:06:56-07:00
by michaelmahoney
snibgo wrote:To get the width and height, I generally use something like this:

Code: Select all

FOR /F "usebackq" %%L IN (`%IM%identify -format "WW=%%w\nHH=%%h" x.jpg`) DO set %%L
If you need double the width, either use "set /A WW2=%WW%*2" or:

Code: Select all

FOR /F "usebackq" %%L IN (`%IM%identify -format "WW=%%w\nHH=%%h\nWW2=%%[fx:w*2]" x.jpg`) DO set %%L
EDIT: Corrected my typo, changing %W% to %WW%.
This works great for for a single file, but I can't seem to get this to work inside another FOR loop, or to accept a parameter or variable for x.jpg. I'm trying to process a number of files passed to my batch by drag & drop or send to. I thought the best way would be to nest this inside the FOR loop that runs for every *.jpg passed, and replace x.jpg with the same parameter I feed to convert as a filename.

Here's what I have:

Code: Select all

SETLOCAL EnableDelayedExpansion
%~d1
CD "%~p1"
FOR %%A IN (*.jpg) DO (
FOR /F "usebackq" %%L IN (`identify -format "WW=%%w\nHH=%%h" %%A`) DO SET %%L
SET /A WW2=WW*2
IF !HH! LEQ !WW! SET /A LS=WW
IF !HH! GTR !WW! SET /A LS=HH
SET /A BW=LS/400, FW=LS/33
convert %%A ^
-set filename:fname %%t -auto-orient ^
-bordercolor grey60 -border !BW! ^
-bordercolor white -border !FW! ^
-bordercolor grey60 -border !BW! ^
-background none -wave 10x!WW2! -chop 0x10 ^
-background black ( +clone -shadow 60x10+10+10 -rotate 180 ) ^
+swap ^
-background none -flatten ^
-rotate 5 ^
-resize 290x290 -unsharp 2x0.5+0.7+0 ^
%%[filename:fname]_thumb.png)
PAUSE
Interestingly, the error I get is "+swap unexpected at this time", though +swap works fine in another FOR loop.

Further help much appreciated.

Thanks,

Mike

Re: Improve windowsbatch handling of portrait & landscape im

Posted: 2014-02-05T08:35:14-07:00
by snibgo
Your for-loop has parenthesis, and so does the IM convert, within the for parenthesis, so you need to escape it. Change a line to:

Code: Select all

-background black ^( +clone -shadow 60x10+10+10 -rotate 180 ^)

Re: Improve windowsbatch handling of portrait & landscape im

Posted: 2014-02-05T11:37:02-07:00
by michaelmahoney
snibgo wrote:Your for-loop has parenthesis, and so does the IM convert, within the for parenthesis, so you need to escape it. Change a line to:

Code: Select all

-background black ^( +clone -shadow 60x10+10+10 -rotate 180 ^)
Much thanks! That worked great. I was on the wrong track completely.

Just as a side note and for anyone who might want to use this code:

Once it was working, I noticed that I also had to calculate the values for the -shadow based on the dimensions of the input image, as well as the curl. Giving absolute values in pixels for the curl and shadow resulted in less curl and shadow on larger images. Then when I was typing this up I noticed that I also had to calculate the -chop the same way. As a whole, it's effective, and on images that have already been resized before processing them with this batch, the final thumbnail quality was noticeably improved. It works well and I'm happy with it, with the minor caveat that on the size of images put out by modern DSLRs, it's terribly slow. I can hear my processor's cooling fan wind up every time it hits a big image. This was a special case, though. In normal usage I would resize to 800 or so on read, just for speed reasons. On a bunch of mixed-size-and-orientation images, though, it's a time saver.

Here is the final code, unless someone has an improvement I haven't thought of:

Code: Select all

SETLOCAL EnableDelayedExpansion
%~d1
CD "%~p1"
FOR %%A IN (*.jpg) DO (
FOR /F "usebackq" %%L IN (`identify -format "WW=%%w\nHH=%%h" %%A`) DO SET %%L
SET /A WW2=WW*2
IF !HH! LEQ !WW! SET /A LS=WW
IF !HH! GTR !WW! SET /A LS=HH
SET /A BW=LS/400, FW=LS/33, SH=LS/70, CU=LS/70
convert %%A ^
-set filename:fname %%t -auto-orient ^
-bordercolor grey60 -border !BW! ^
-bordercolor white -border !FW! ^
-bordercolor grey60 -border !BW! ^
-background none -wave !CU!x!WW2! -chop 0x!CU! ^
-background black ^( +clone -shadow 60x!SH!+!SH!+!SH! -rotate 180 ^) ^
+swap ^
-background none -flatten ^
-rotate 5 ^
-resize 290x290 -unsharp 2x0.5+0.7+0 ^
%%[filename:fname]_thumb.png)
BIG thanks to snibgo, without whom I would now be frustrated to the point of sedation.

Re: Improve windowsbatch handling of portrait & landscape im

Posted: 2014-02-05T11:46:21-07:00
by snibgo
SET /A WW2=WW*2
IF !HH! LEQ !WW! SET /A LS=WW
IF !HH! GTR !WW! SET /A LS=HH
SET /A BW=LS/400, FW=LS/33

should be

SET /A WW2=!WW!*2
IF !HH! LEQ !WW! SET /A LS=!WW!
IF !HH! GTR !WW! SET /A LS=!HH!
SET /A BW=!LS!/400, FW=!LS!/33

Re: Improve windowsbatch handling of portrait & landscape im

Posted: 2014-02-05T12:35:57-07:00
by michaelmahoney
snibgo wrote:SET /A WW2=WW*2
IF !HH! LEQ !WW! SET /A LS=WW
IF !HH! GTR !WW! SET /A LS=HH
SET /A BW=LS/400, FW=LS/33

should be

SET /A WW2=!WW!*2
IF !HH! LEQ !WW! SET /A LS=!WW!
IF !HH! GTR !WW! SET /A LS=!HH!
SET /A BW=!LS!/400, FW=!LS!/33

Done! I'd understood that in SET /A one was not required to use the %'s or !'s. Is it a good practice thing?

EDIT: Ah, I think I see: Is it that once the variable is declared one always uses the % or ! ?

Re: Improve windowsbatch handling of portrait & landscape im

Posted: 2014-02-05T12:48:48-07:00
by snibgo
I had to check that. After checking, I agree, % or ! shouldn't be required for "set /A". Perhaps they were once, or I once encountered a situation where I needed them, or I prefer to be explicit. Or I've forgotten anything I ever knew about scripting. Sigh.