Posts Tagged ‘batch file’

Joining photos together with ImageMagick

Tuesday, June 29th, 2010

In my posts I often have a need to stitch multiple photos together in a rectangular block. I prefer to have the photos stitched together rather than uploading them as individual images as this removes the need to lay them out (using divs, tables, etc). Plus the stitched together image size is smaller than the size of uploading individual images. This is the kind of image montage I’m talking about.

flowers stitched together with imagemagick

I always like to have them in a single row, sized to the correct width, with a small white space between the images. Previously I was doing this manually with Paint Shop Pro. Doing it manually takes a while (even when you know all the keyboard shortcuts), is error prone, and is boring to do.

And things get even more difficult if you have a mixture of portrait and landscape images as I’d have to resort to a calculator to work out what sizes each sub-image should be.

portrait and landscape joined with imagemagick

I’m no expert with ImageMagick but I managed to put together a script that can do the job automatically. This does it in three steps (three convert commands), but I’ve do doubt that someone who knows ImageMagick well could do it in one much more efficiently – please leave a comment if you know how. This is what it does:

  • Resizes the images to a maximum height of 768 pixels (this does assume that the height of all your images is over 768 pixels. If not you can adjust this value). This step sorts out the problem of images being in portrait or landscape. The images are then appended together with whitespace between them.
  • I chop off the extra bit of whitespace on the very right of the montage.
  • I resize the image to have a width of 450 pixels and save it back out into the same directory as the first image, ready for including on my blog.

I save the intermediate images as PNGs so that the result isn’t being JPEG compressed too many times!

Here’s the DOS batch file code. Some of the code is based on that from a recent post of mine on extracting the directory name from a file path.

goto :skip_functions

:setDir
if not %imgdir% == "" goto :EOF
set imgdir=%1
goto :EOF

:getDirectory
del %TEMP%resize.tmp
dir %1 > %TEMP%resize.tmp
for /f "skip=3 tokens=3" %%i in (%temp%resize.tmp) do call :setDir %%i
goto :EOF

:skip_functions

set imgdir=""
call :getDirectory %1

cd %imgdir%
del prout*.*
convert %9 %8 %7 %6 %5 %4 %3 %2 %1 -resize "x768" -background White -gravity east -splice 20x0 +append prout.png
convert prout.png -gravity east -chop 20x0 prout2.png
convert prout2.png -strip -resize 450 -compress JPEG -quality 85 %RANDOM%.jpg
del prout.png
del prout2.png

I’ve put a shortcut to this script in my Send To menu (type %APPDATA%MicrosoftWindowsSendTo into the Windows Explorer address bar to get to the folder containing the shortcuts).

I can then right click on whatever images I want to stitch together, choose the photoResize.bat option from the SendTo menu, and the stitching is automatically done for me, and the resulting JPEG left in the same directory as the images.

photo stitching context menu

There are some limitations which you could fix if you really needed to.

  • The script assumes that all the images have a height greater than 768.
  • It is always outputting to JPEG. It could be changed so that if all the images are in the same format, it outputs that that same format. E.g. stitching together 3 PNGs would output to a PNG.
  • I’m using three convert commands which I’m sure is very inefficient. I’ve no doubt this operation could be done with one command.
  • The order that the images are stitched together is not defined when using the Send To shortcut.


DOS: Get the directory name from a file path

Monday, June 28th, 2010

If you need to write a DOS batch file that takes a file path as an input parameter and needs to do something to other files in the same directory as the input file then you’ll find there is no easy way to get the file’s directory name into a variable.

dos path from file

You could pass in the directory name as a separate parameter but that seems like cheating. I sometimes find answers to problems like these on Rob van der Woude’s scripting site or Google, but no luck this time.

I had to figure this one out from scratch. Here’s what I do. Let me know if you have a better (shorter) way of doing this.

  • Output the result of running ‘dir’ on the file path into a temporary file.
  • Loop through the lines in the temporary file, skipping the first three, and then taking the third token.
  • Assign that token to a variable.

If all has worked the variable which I’ve called ‘thedirectory’ should now contain the file path.

I’ve tested this on Windows 7 and I’m guessing it will work on other versions of Windows, but I’ll make no promises.

Here is the code:

goto :skip_functions

:setDir
if not %thedirectory% == "" goto :EOF
set thedirectory=%1
goto :EOF

:getDirectory
del %TEMP%\getdir.tmp
dir %1 > %TEMP%\getdir.tmp
for /f "skip=3 tokens=3" %%i in (%temp%\getdir.tmp) do call :setDir %%i
goto :EOF

:skip_functions

set thedirectory=""
call :getDirectory %1

@echo off
echo thefile =%1
echo thedirectory=%thedirectory%

And if you want to know what I needed it for have a look at my post about stitching together photos using ImageMagick.

Converting file extensions to lower case

Friday, January 15th, 2010

Recently I needed to convert a large number of photo file extensions to lower case. Doing this manually would take ages and wouldn’t be a fun job.

I wrote a quick batch file to look through all the sub-directories from the one it is executed from and change selected file extensions to lower case.

To use this script place the below code in a file called lowerCaseExtensions.bat. Put the batch file in the directory containing the files that you want changed and double click on it.

The script will loop through all the files in the directory, and will loop thought the files in all sub-directories and will change jpg, png and gif extension to lower case.

@echo off
setlocal
pushd .
goto :skip_functions
:toLower
	cd %1
	echo Processing %1
	ren *.JPG *.jpg 2>&1
	ren *.PNG *.png 2>&1
	ren *.GIF *.gif 2>&1
goto :EOF
:skip_functions
for /f %%i in ('dir /b/s/ad') do call :toLower %%i
popd
endlocal

You can easily customise this to change the file extensions of other file types to lower case.

This has been tested only on my Windows XP computer so I’d suggest you test it first on some copied files before you let it lose on your real ones.

Even if you aren’t specifically interested in the functionality that this batch file implements you might find it interesting to see how to implement a simple callable function in a batch file (:toLower), and how to implement ‘for’ loops.

Starting a group of programs from a DOS batch file

Friday, August 8th, 2008

I use my computer for a variety of purposes – for example writing web content, programming, or word processing.

For each of these activities I need a different set of programs to be loaded. To take one example when I’m writing or modifying web pages I need:

  1. NoteTab Pro which I use to edit the HTML files’
  2. WS_FTP Pro for uploading the files’
  3. Explorer for seeing the files – after loading it I have to manually navigate to f:\work\website\

To load each of these programs I have to click on the Start button, find the icon, and click on it. For Explorer I’d actually use the Windows Key + E shortcut but then I’d still have to navigate to the correct folder manually.

This in total probably takes me 20-30 seconds each time I do it. On an average day I might do this once – I don’t edit web pages everyday but then on some days I’ll restart the computer a few times due to patches or installing new applications.

This may not sound a lot but over a year it could be between two and three hours spent just opening these three programs! What a waste of time.

I could add the programs I need to the startup folder. However this is not a good enough solution as I need a completely different set of applications to be loaded depending on what I will be working on.

On top of all the wasted time there is also the annoyance of having to repeat this same series of actions on a daily basis. It does become quite tedious. The web editing task is a simple example – I only need three programs open. If I were working on some serious coding I may well need five applications to be opened before I’m ready to go.

There is a simple way to remove this tedium. Create a batch file that opens all the application that you need. Put it on the path and then all you have to do is type Windows Key + R (to open the Run dialog), type in the batch file name and hit enter. Then all the programs open in quick succession.

Here is my batch file for setting up my web development environment.

start "" /max "d:\apps\NoteTabPro\NotePro.exe"
start "" /max "d:\apps\WS_FTP Pro\ftp95pro.exe"
explorer /e,f:\work\website

I have enclosed the executable paths in speech marks in case the paths have spaces in them – as with the FTP tool. The "" right after the ‘start’ command would normally set a title. I just leave it blank as we are opening Windows applications rather than a DOS session. The /max opens the applications maximised.

The explorer line opens Windows Explorer and sets the open directory to be the one where I keep my website files.

I call this batch file ‘websetup.bat‘. If you want to put a batch file such as this on the path the easiest place is probably in c:\windows (or equivalent).

Alternatively you may prefer to create a new directory especially for these scripts and then add the location of this directory to your path. Following ‘Control Panel -> System -> Advanced -> Environment Variables’ will get you to the screen where you can add your script directory to your path.

Batch processing photos with DOS and ImageMagick

Thursday, August 7th, 2008

For my recent walking project I knew I was going to be taking lots of photos. I wanted a DOS script which would batch process the JPEG photos from my camera into the ‘full sized images’ (which are much smaller than the raw camera images), and the poloroid-like thumbnails.

The excellent ImageMagick tool provides a way to generate poloroid-like thumbnails automatically. I also wanted the thumbnails to be rotated at random angles which ImageMagick can do as well.

However the ImageMagick instructions were missing a few things 1) they seem to be aimed at people using Unix / Linux scripts whereas I’m using DOS scripts and 2) they show how to do this processing on single images rather than on a whole directory of them.

Poloroid rotation with ImageMagick Poloroid rotation with ImageMagick

It is quite easy to generate a random rotation angle with a simple bit of perl. The below line will generate a random floating point number between -7 and +7. I want both negative and positive numbers so that some of the poloroids will be tilted to the left, and others to the right.

perl -e "print rand() * 14 - 7"

I wanted to do all the processing through a DOS batch file so the next problem was how to get the random number into a DOS environmental variable. The answer is to use the ‘for /f‘ command to assign the output of a command into a variable:

for /f %%i in ('perl -e "print rand() * 14 - 7"') do set ANGLE=%%i

At the time when I wrote this script generating a poloroid involved a whole sequence of commands. Something like below!

-bordercolor white -border 6 -bordercolor grey60 -border 1 -background none -rotate %ANGLE% -background black ( +clone -shadow 60x4+4+4 ) +swap -background white -flatten

My script still uses this long poloroid command, but you might want to use the new one word ‘poloroid‘ command which is built straight into the latest versions of ImageMagick instead.

As well as generating the poloroid thumbnails it will also generate the full size website friendly images which are tagged with the website URL.

Prerequisites:
Your JPEG images are in an ‘images’ directory.

Usage:
ProcessPhotos.bat [path of directory that contains ‘images’ directory]

Output:
A new directory called ‘generated’ in the input directory containing a full size image (which has been tagged with the website URL), and a poloroid thumbnail.

Notes:
In order to use this script you will have to customise 1) the location of the ImageMagick executable 2) the reference to the drive – it is assuming a ‘f:’ drive here and 3) the website URL.

setlocal
pushd .
goto :skip_functions
:makeThumb
	echo %1
	set jpg=%1
	set jpg=%jpg:~0,-4%
	echo %jpg%
	for /f %%i in ('perl -e "print rand() * 14 - 7"') do set ANGLE=%%i
	set ANNOTATE=-gravity south -stroke "#000C" -strokewidth 2 -annotate +0+20 "www.advancedhtml.co.uk" -stroke none -fill white -annotate +0+20 "www.advancedhtml.co.uk"
	set POLOROID=-bordercolor white -border 6 -bordercolor grey60 -border 1 -background none -rotate %ANGLE% -background black ( +clone -shadow 60x4+4+4 ) +swap -background white -flatten
	D:appsImageMagick-6.3.6-Q16convert %1 ( +clone -resize 600x -auto-orient %ANNOTATE% -compress JPEG -quality 70 -write %jpg%_full.jpg +delete ) -resize 180x -auto-orient %POLOROID% -compress JPEG -quality 80 -sampling-factor 2x1 -strip %jpg%_th.jpg
goto :EOF
:skip_functions
f:
cd %1images
for /f %%i in ('dir /b *.jpg') do call :makeThumb %%i
md %1generated
move *_full.jpg ..generated
move *_th.jpg ..generated
popd
endlocal