snibgo's ImageMagick pages

IM with Cygwin

IM can run under Cygwin, which provides a Unix-like environment under Windows.

You might want to do this because:

Cygwin is a fairly simple and cheap (no money; less than 1 GB disk) way of using Unix tools on a Window computer. This provides a far more comprehensive shell (bash), and access to standard Unix utilities (bc, sed, awk, etc). The main complication is with directory names.

This page is rather long and complex. I have tried to document the various oddities I have discovered. If you simply want to use pre-built ImageMagick bash scripts, you can skip to Cygwin for pre-built IM bash scripts.

Alternatives to Cygwin include:

For more detailed information about Cygwin, see the official Cygwin User's Guide.

Cygwin provides alternative shells, including ash, bash, dash, fish, posh, tcsh and sh. I will ignore all these except for bash, which will be used for all for all Unix-like examples on this page.

For more information on bash, type "man bash" at the command line. (After following the steps given on this page, "man bash" should work from either Cygwin or Windows.)

Information on this page is based on a Cygwin v1.7.30 installation on 16 July 2014 to a 64-bit Windows 8.1 computer, following a query on the ImageMagick forums: How To: Using Cygwin and Scripts (e.g., Fred's) with IM.

Install ImageMagick

If you haven't already, you should install the ordinary Windows binary release of ImageMagick from the official Download Binary Releases IM page.

I suggest you add the path to the installation directory to your Windows system path. (The installation can do this for you.)

The variety:

Downloading and installing IM takes about five minutes.

If convert ever gives you an error message like "Invalid Parameter" or "Invalid drive specification" then you are probably running the Microsoft Windows tool convert.exe because IM's convert.exe isn't in a directory on your path. The command "where convert.exe" will tell you the locations where Windows finds the program. IM's directory should be at the top of this list.

Alternatively, you might compile ImageMagick from source. There are complications if you compile it yourself (for example, you might compile the Unix or Windows source). This page assumes you install only the pre-compiled Windows binary.

Install Cygwin

From the Cygwin homepage, run the 64-bit or 32-bit installation program. For my 64-bit computer, this downloads and runs setup-x86_64.exe. This runs as a conventional Windows installation, but you are given the choice of what packages to install. You probably want "bc" and "gnuplot", which are in "math", and are not installed by default.

You might want the complete "graphics" packages, but beware. The "graphics" package includes an old version of ImageMagick, v6.7.6-3, when the current official release is v6.8.9-5. I strongly suggest you do not install ImageMagick from Cygwin.

"Graphics" includes "poppler: PDF manipulation utilities", which can be useful.

"Utils" contains dos2unix.exe and unix2dos.exe which you might find useful for converting text files between Unix and Dos formats. They are not essential.

If you want to compile ImageMagick, or build programs with the IM libraries, you probably want the "Devel" package.

Depending on how much you have selected and your internet speed, download and installation might take between two and ten hours, mostly unattended.

By default, this installs 64-bit Cygwin to the directory C:\cygwin64. If you have installed to somewhere else, adjust the following as required.

By default, it creates a "Cygwin64 terminal" on the desktop. Running this gives a console that looks and operates like a Windows console. For copy-and-paste, use right-mouse-click, or ctrl-ins and shift-ins.

You can also start the Cygwin terminal by typing this at a Windows command prompt:

C:\cygwin64\bin\mintty.exe -i /Cygwin-Terminal.ico -

When environment variables are set as described below, a Cygwin terminal can be started with the command:

mintty.exe -i /Cygwin-Terminal.ico -

... and this will work whether typed as a bash or cmd command, in either a Cygwin terminal or Windows console.

When you want to update the packages you already have, or uninstall packages, or add new ones, run the same setup-x86_64.exe program.

Check the installation

Start the "Cygwin64 terminal" by double-clicking the desktop icon.

The prompt will be something like this:

Alan@Fiona ~
$

My username is Alan, my computer is called Fiona, and my currrent directory is "~" which is Unix-speak for "home directory".

In the Cygwin terminal, the default shell (also known as "command interpreter") is called "bash". The usual prompt for bash is "$".

From bash, we can start the normal Windows shell by typing cmd. This shows the usual Windows prompt. On my computer, this shows the current directory, which is "C:\cygwin64\home\Alan". Type exit to leave the Windows shell and return to bash. (We can repeat this: inside bash, run cmd. Inside cmd run bash. Inside that bash, run cmd. Keep going until we are thoroughly confused.)

If you type exit at bash, the Cygwin terminal will close.

In the Cygwin terminal, there are two additional entries to the system path. These are C:\cygwin64\usr\local\bin and C:\cygwin64\bin. Like Windows cmd, bash will look for programs and scripts in the system path.

Check that some common Unix utility programs can run, by asking for help on each one. At a Windows cmd console, type "bash", then type each bash command. From a Cygwin console, you are already running bash. At the bash prompt, type each of these commands. (The initial dollar-signs represent the bash prompt, telling you these are bash commands. Don't type them.) Each program should write its help text to the console.

set PATH=%IMG7%;%PATH%

bash
$ awk --help
$ bc --help
$ cut --help
$ sed --help
$ tr --help
$ gnuplot --help
$ magick -version
$ exit

If any of these give a message like ...

bash: gnuplot: command not found

... then that program hasn't been installed.

If you use convert, then check that convert --help displays the help for ImageMagick's convert. If it displays "Invalid drive specification" then the program being run is Microsoft's convert, which means the path is wrong.

Cygwin can be set up so your home directory on Cygwin is the same as your home directory on Windows.

Setting environment variables

cy_envvar.png

I suggest you add a Windows environment variable called SHELLOPTS (all capital letters). The value should be igncr (all lower-case letters).

I suggest you ensure Imagemagick's directory is in the system path, and add three more entries to the system path. Two are the locations of Cygwin's binary files, C:\cygwin64\bin and C:\cygwin64\usr\local\bin.

The third is a location for bash script files. You might choose to put bash script files in a directory that is already on your system path. I decided to put them in a new directory called F:\pictures\bash, so I added that to my PATH variable.

I have put these at the front of my path. This means that when an external command has the same name (such as tree, timeout and find) in both Cygwin and Windows, the Cygwin version will be run. I am not (yet) sure that this is the best place. Perhaps they are better placed at the end of my path.

You can create and modify system-wide environment variables at: Control panel => System => Advanced system settings => Advanced tab => Environment variables. An alternative is to set environment variables in a BAT file that is executed whenever a console starts up.

These settings will be used in new consoles that are created from scratch, but not in any existing consoles, or in new consoles that are created from other existing consoles.


Start a new Cygwin terminal by double-clicking the desktop icon. Type this command:

echo $SHELLOPTS

The result should be something like:

braceexpand:emacs:hashall:histexpand:history:igncr:interactive-comments:monitor

Bash has added "igncr" to its own default entries. Because this contains "igncr", Cygwin's bash will now ignore CR characters in scripts. See Line ends below.

Next time you reboot, check these variables from the Windows command line:

set SHELLOPTS
set Path

Using environment variables

Bash (like cmd) will inherit environment variables from the calling process.

When using an evironment variable in cmd, we bracket it between percent signs, eg %TEMP%.

Bash is sightly different. Generally it is prefixed with a dollar, eg $TEMP, and terminated by any character that can't be in a name. If it must be terminated by a character that can be in a name, we also put it inside braces, {}, eg ${TEMP}.

When we run a bash script from a cmd prompt, by typing bash before the script name, cmd will expand the variable, so we use the cmd %TEMP% style.

When we start bash as an interactive shell and then type commands from within bash, bash will expand the variable, so we use the bash $TEMP or ${TEMP} style.

Bash automatically translates environment variables from cmd format to bash format.

cy_usetemp.png

Trouble is, we sometimes don't want them translated. We can use cygpath to translate back:

cy_cygpath.png

This uses a handy bash trick: backslashes enclose a command that will be run first, and the output of this sub-command will be substituted in the main command.

Directories

"Directories" are also known as "folders".

Windows is usually configured as directories within devices. For example, my computer has devices "C:" and "F:", and sometimes other devices for external disks or memory cards.

Unix (and Cygwin) regards disks and memory cards as files. Even the Windows clipboard is a file, /dev/clipboard. (This is text only, so isn't useful for ImageMagick's clipboard: format.)

Windows Cygwin
C:\ /cygdrive/c/
F:\ /cygdrive/f/
C:\Users\Alan (aka %USERPROFILE%) /cygdrive/c/Users/Alan
C:\cygwin64 /
C:\cygwin64\home\Alan /home/Alan (aka ~)
C:\cygwin64\usr\bin /usr/bin
C:\im\ImageMagick-6.8.9-Q16\ /cygdrive/c/im/ImageMagick-6.8.9-Q16

The utility cygpath.exe can convert from either format to the other.

When a Cygwin tool is given a directory name, it will look for backslashes and device-letter-colon. If it finds either of these, it decides this is a Windows reference. Otherwise, it decides this is a Cygwin reference.

ls /

... lists files in Cygwin's root, so is like dir C:\cygwin64.

ls '\'
ls \\

... these both list files in Windows root of current device, so are like dir \.

ls F:/
ls 'F:\'

... these both list files in Windows root of F:, so are like dir F:\.

ls /temp

... this is a Cygwin reference, so is like dir C:\cygwin64\temp.

ls '\temp'

... this is a Windows reference, so is like dir \temp.

ls \temp

... bash will strip and ignore the backslash, so this is like ls temp,
which is either a Windows or Cygwin reference (because they are the same),
so is like dir temp.

This is probably not what the user intended.

If the directory contains a backslash, either quote the directory or escape each backslash.

While running bash interactively, I often want to list directories in Windows format. For this, I use a command like:

$ cmd /c dir '\web\im\x.*'

Dir needs backslashes. The quotes prevent bash from removing the backslashes before running cmd which runs dir. The quotes can be single or double.

cmd /c can be followed by anything that could be on a cmd command line, such as a BAT filename or image filename.

Line ends

Windows marks line ends by using two characters, both CR (carriage return) and LF (line feed). Unix and Cygwin use only one character: LF. If Cygwin's bash encounters CR-LF at the end of a script line, it will interpret CR as part of the command, which will either make it invalid or cause some weird bug.

If you edit script files with Windows tools, you will get CR-LF at the end of each line. Microsoft Notepad won't properly read files that have only LF. (Microsoft Wordpad happily reads LF-only, and will convert them to CR-LF.)

Personally, I don't care how line ends are marked, and I would prefer that software didn't care either. Making the system-wide environment variable SHELLOPTS, as shown above, makes bash not care. Problem solved.

But solving one problem may cause another. If you have any scripts that deliberately include the CR character, this will cause problems. In that case, you might prefer an alternative solution, such as one of the following:

  1. When starting bash, include "-o igncr" in the command.
  2. If you edit a script with a Windows tool, ensure that the first non-comment line is:
    set -o igncr #
    After bash runs this command, it will ignore any CR characters in the rest of the script. The '#' at the end starts a comment that runs to the end of the line. Thus, it comments-out the CR character for that line. If you don't include the '#', bash will raise an error and ignore the command.
  3. If you edit a script with a Windows tool, convert it afterwards to change every CR-LF to LF. A command (under bash or cmd) to do this is:
    sed -e 's-\r\n$-\n-' < myfile.dos > myfile.unix
  4. Don't use Windows tools to edit scripts, or ensure that any you do use are set to "Unix line-ends".
  5. Edit /etc/fstab, changing binary to text as required. See Cygwin User's Guide => 3. Using Cygwin => The Cygwin Mount Table.

If you want to check whether a file is CR-LF or LF, type the following commnd from cmd or bash:

cat -v myfile.ext

Any CR characters will show as ^M.

ASIDE: When I started playing with computers in the 1960s, we prepared programs by typing on a Teletype, which printed to a long roll of paper and also punched paper tape. Most Teletypes were off-line (not hooked up to a computer), and we had to press carriage-return to move the print head to the left, then line-feed to scroll the paper up a line. But if we used the only Teletype in town that was hooked up to a computer, pressing the carriage-return key sent that character to the computer which echoed back with both carriage-return and line-feed.

A simple bash script

To test a simple script, make a file called cygtest in some directory on your path. I have decided to put bash scripts into F:\pictures\bash\, so that is where I put this file. For example, using notepad to create the file, I type the following command:

notepad F:\pictures\bash\cygtest.

The final dot will create the file with no extension. I type the following into the file. (You can copy from this web page and paste into the editor.)

#!/bin/bash
# This is a test script for bash.

echo -n The current directory is:
pwd

echo This script file is: $0

type $0

echo Goodbye

Use dir to check it doesn't have an extension. For example, if it is called cygtest.txt then exit the editor, rename it as cygtest, and re-start the editor.

ASIDE: You might prefer to give bash scripts an extension of ".sh". If you do this, you can then associate bash scripts with the bash shell program, so you can run them by typing the name at the cmd prompt, or double-clicking in Windows Explorer.

FURTHER ASIDE: Windows looks at the file extension to decide what program to use to execute a script. Unix works differently: it reads the first line, which should be '#' (the comment character) followed by the path to the program that can execute the script. So Unix scripts (and even compiled programs) often have no extension.

With Cygwin's ls tool used with cmd, we can find this file like this:

F:\prose\PICTURES>ls /cygdrive/f/pictures/bash/cygtest
/cygdrive/f/pictures/bash/cygtest

F:\prose\PICTURES>ls F:/pictures/bash/cygtest
F:/pictures/bash/cygtest

F:\prose\PICTURES>ls \pictures\bash\cygtest
\pictures\bash\cygtest

With the cygdrive reference, we can't use Windows-style back-slashes:

F:\prose\PICTURES>ls \cygdrive\f\pictures\bash\cygtest
ls: cannot access \cygdrive\f\pictures\bash\cygtest: No such file or directory

If we run ls within bash, the first two methods work with forward-slashes. Backslashes work only if the filename is quoted:

F:\prose\PICTURES>bash

$ ls /cygdrive/f/pictures/bash/cygtest
/cygdrive/f/pictures/bash/cygtest

$ ls F:/pictures/bash/cygtest
F:/pictures/bash/cygtest

$ ls \pictures\bash\cygtest
ls: cannot access picturesbashcygtest: No such file or directory

$ ls '\pictures\bash\cygtest'
\pictures\bash\cygtest

$ ls \cygdrive\f\pictures\bash\cygtest
ls: cannot access cygdrivefpicturesbashcygtest: No such file or directory

$ exit
exit

Unquoted backslashes used for ls within bash are ignored. The Windows tool dir.exe, when used with bash, gives the same results. Even Windows tools, when used within bash, ignore backslashes! This is explained in man bash:

"After the preceding expansions, all unquoted occurrences of the characters \, ', and " that did not result from one of the above expansions are removed."

So we can use backslashes, provided we quote the filenames. Quote can be single or double. I suggest that backslashes are not used within bash, whether as typed commands or in scripts.

(This backslash problem doesn't occur when starting bash with a scriptname followed by one or more filenames.)

Cygwin's bash has a couple of extra goodies: when a pathname starts with a device-name, or contains forward slashes, bash assumes it is a Windows path.

We get more information about the file from ls -l:

F:\prose\PICTURES>ls -l F:\pictures\bash\cygtest
-rwxr-xr-x 1 Alan None 149 Jul 19 13:37 F:\pictures\bash\cygtest

Now we have created the script, and verified with ls that it exists, we can run it in two ways. The first is to tell bash to run the script and immediately exit. The second is to run bash interactively, then run the script, then tell bash to exit.

ASIDE: In Unix, the user commonly has to change the mode of the script file to make it executable, with this command (from bash or cmd):

chmod u+x cygtest

This doesn't seem to be needed.

To run the script directly, I type this at the Windows command line:

bash cygtest 

This runs bash non-interactively. Bash starts up, runs the script, then exits. The result is:

The current directory is:/cygdrive/f/prose/PICTURES
This script file is: cygtest
cygtest is /cygdrive/f/pictures/bash/cygtest
Goodbye

If the script wasn't in a directory on my path, it would have given me one warning and one error. The cleanest way of avoiding such warnings and errors is to keep bash scripts in a directory on the system path.

When Windows runs a BAT script, by default it echoes each command to the terminal. This is useful when developing scripts, but slows them down, so this can be prevented with the command "echo off". When bash runs scripts, by default it doesn't echo each command. If we want it to echo commands (to stderr), use the "-v" option:

bash -v cygtest >cy_simp2.lis 2>&1
#!/bin/bash
# This is a test script for bash.

echo -n The current directory is:
The current directory is:pwd
/cygdrive/f/prose/PICTURES

echo This script file is: $0
This script file is: cygtest

type $0
cygtest is /cygdrive/f/pictures/bash/cygtest

echo Goodbye
Goodbye

Some comments on the output:

For the second method, I run bash interactively. Bash starts up, then waits for commands, which it executes. It exits when I tell it to. Within bash, I type the script name, "cygtest". Then I exit bash, "exit".

cy_bash_scr.png

The output from type is slightly different.

We can call a bash script from inside a BAT script. Just type "bash" and the filename in the BAT script.

We can also call BAT scripts from inside a bash script, with the "cmd" command.

Running ImageMagick

ImageMagick is a Windows program, not a Cygwin program. Even the build of IM distributed with Cygwin is a Windows program. As such, argument directory paths should be as Windows knows them, not as Cygwin knows them (which would be with /cygdrive).

Directories can be absolute or relative, with or without a device name.

ASIDE:

A relative path gives the location in relation to the current directory. Examples are:

An absolute path, also known as "full path", gives the location in relation to the root. For Windows, it may or may not include the device. Examples are:

Here is a bash session to show the possibilities:

# Remove any temporary files:
rm F:/web/im/cy_g*.png

# Check they have really gone:
ls F:/web/im/cy_g*.png
ls: cannot access 'F:/web/im/cy_g*.png': No such file or directory

# These should succeed:
convert -size 10x10 gradient: /web/im/cy_g1.png
$IMB/convert -size 10x10 gradient: '\web\im\cy_g2.png'
$IMB/convert -size 10x10 gradient: F:/web/im/cy_g3.png
$IMB/convert -size 10x10 gradient: 'F:\web\im\cy_g4.png'
$IMB/convert -size 10x10 gradient: '..\..\web\im\cy_g5.png'

# This should fail because IM can't see /cygdrive/f/web/im/:
$IMB/convert -size 10x10 gradient: /cygdrive/f/web/im/cy_g6.png
convert.exe: unable to open image `/cygdrive/f/web/im/cy_g6.png': No such file or directory @ error/blob.c/OpenBlob/2709.
convert.exe: WriteBlob Failed `/cygdrive/f/web/im/cy_g6.png' @ error/png.c/MagickPNGErrorHandler/1645.

# Which files do we have?
ls -l F:/web/im/cy_g*.png
-rw-r--r-- 1 Alan Alan 343 Sep  2 04:33 F:/web/im/cy_g1.png
-rw-r--r-- 1 Alan Alan 298 Sep  2 04:33 F:/web/im/cy_g2.png
-rw-r--r-- 1 Alan Alan 298 Sep  2 04:33 F:/web/im/cy_g3.png
-rw-r--r-- 1 Alan Alan 298 Sep  2 04:33 F:/web/im/cy_g4.png
-rw-r--r-- 1 Alan Alan 298 Sep  2 04:33 F:/web/im/cy_g5.png

The same applies to bash scripts that call IM. Here is a trivial script file, cy_make_grad, in a directory on my path:

convert -size 10x10 gradient: $1

I can execute this from cmd either by prefixing with each call with "bash", or by running bash first and calling the script directly from within the bash session.

1. Executing from cmd by prefixing each call with "bash":

del \web\im\cy_h*.png
bash cy_make_grad /web/im/cy_h1.png
bash cy_make_grad '\web\im\cy_h2.png'
bash cy_make_grad F:/web/im/cy_h3.png
bash cy_make_grad 'F:\web\im\cy_h4.png'
bash cy_make_grad '..\..\web\im\cy_h5.png'
dir \web\im\cy_h*.png 
 Volume in drive F is New Volume
 Volume Serial Number is F8C5-053E

 Directory of f:\web\im

02/09/2022  04:33               343 cy_h1.png
02/09/2022  04:33               343 cy_h2.png
02/09/2022  04:33               343 cy_h3.png
02/09/2022  04:33               343 cy_h4.png
02/09/2022  04:33               343 cy_h5.png
               5 File(s)          1,715 bytes
               0 Dir(s)  126,148,403,200 bytes free

2. Or we run bash, execute the script multiple times from within bash, then exit bash:

del \web\im\cy_j*.png
bash
$ cy_make_grad /web/im/cy_j1.png
$ cy_make_grad '\web\im\cy_j2.png'
$ cy_make_grad F:/web/im/cy_j3.png
$ cy_make_grad 'F:\web\im\cy_j4.png'
$ cy_make_grad '..\..\web\im\cy_j5.png'
$ exit
dir \web\im\cy_j*.png >cy_cmd_mgrad2.lis
 Volume in drive F is New Volume
 Volume Serial Number is F8C5-053E

 Directory of f:\web\im

02/09/2022  04:34               343 cy_j1.png
02/09/2022  04:34               343 cy_j2.png
02/09/2022  04:34               343 cy_j3.png
02/09/2022  04:34               343 cy_j4.png
02/09/2022  04:34               343 cy_j5.png
               5 File(s)          1,715 bytes
               0 Dir(s)  126,148,403,200 bytes free

These two methods work fine. When running IM in a bash script, we must give directory/file names as Windows knows them, not as Cygwin knows them. If we use backslashes, we need to quote them.

Complex bash scripts

As an example, I use curves, a script by Fred Weinhaus. The commands are very easy, provided the image files are in the current directory. After copying it to a directory on my path, I type these commands in a Windows cmd console:

%IMG7%magick -size 100x100 gradient: cy_samp.png

bash curves "25,75 75,25" cy_samp.png cy_samp_out.png
cy_samp.png cy_samp_out.png

Instead of the current directory, we can specify a relative or absolute path in the usual Windows way, such as ..\another_dir\cy_samp.png or F:\top_dir\another_dir\cy_samp.png. The following are all valid:

F:\prose\PICTURES>bash curves "25,75 75,25" cy_samp.png c.png
F:\prose\PICTURES>bash curves "25,75 75,25" ./cy_samp.png c.png
F:\prose\PICTURES>bash curves "25,75 75,25" .\cy_samp.png c.png
F:\prose\PICTURES>bash curves "25,75 75,25" ..\pictures\cy_samp.png c.png
F:\prose\PICTURES>bash curves "25,75 75,25" F:\prose\pictures\cy_samp.png c.png

We can do the same with interactive bash:

F:\prose\PICTURES>bash
$ curves "25,75 75,25" cy_samp.png c.png
$ curves "25,75 75,25" ./cy_samp.png c.png
$ curves "25,75 75,25" '.\cy_samp.png c.png'
$ curves "25,75 75,25" '..\pictures\cy_samp.png' c.png
$ curves "25,75 75,25" 'F:\prose\pictures\cy_samp.png' c.png
$ exit

If we use backslashes, we need to quote the filename.

We might use the Windows temporary directory for the gradient file. As we are running a cmd command, this needs the cmd style for the environment variable.

%IMG7%magick -size 100x100 gradient: %TEMP%\cy_samp2.png

bash curves "25,90 75,35" %TEMP%\cy_samp2.png cy_samp2_out.png

cy_samp2_out.png

cy_samp2_out.png

To run the same command interactively: start bash, then type the command (not prefixed with "bash"), then type "exit". As bash will expand the environment variable, it must be in the bash style. But Fred's curves runs IM's convert, which is a Windows program so it expects a Windows directory, so we need to convert it with cygpath.

So the command we will give bash is:

curves "25,90 75,35" `cygpath -w $TEMP/`cy_samp2.png cy_samp3_out.png
cy_b_curves.png

We have seen that bash scripts can be run from cmd by prefixing each script name with "bash". Or they can be run by starting bash, then typing the command(s), then exiting bash. I suggest that the second method is generally better. It avoids the overhead of starting and stopping bash for every script. And workflows that start by manually calling individual scripts quickly evolve into complex scripts that call sub-scripts. Although cmd scripts can call bash scripts, and bash scripts can call cmd scripts, it is easier to stick to just one language.

We have also seen that file paths to IM need to be as Windows knows them (ie not using /cygdrive), either with forward slashes, or with backslashes in which case they must be quoted.

I have tested a small sample of Fred's scripts, downloaded on 24 July 2014, and they had no major problems. There were two small issues:

  1. Fred's script plot has a name conflict with plot.exe, a compiled program available in Cygwin. I chose to rename Fred's script as fmwplot.
  2. Fred's script 3Dbox contains the line:
    tmpdir="/tmp"
    tmpdir is then used indirectly by both Cygwin tools and IM tools. This causes problems, as /tmp is two different places in the Windows and Unix worlds. This needs to be changed to point to an existing directory that is the same place in both worlds. This can be an absolute path with device-letter-colon such as:
    tmpdir="C:/temp"
    or a relative path such as:
    tmpdir="./temp"
    or
    tmpdir="."
    or, if you like, the Windows translation of the usual Windows environment variable %TEMP%:
    tmpdir="`cygpath -w $TEMP`"

Another problem has been reported for IM v7: Some of Fred's scripts call identify, which may not exist in a v7 installation. A solution is to edit the script, changing identify to magick identify.

Here is my script that exercises some of Fred's scripts. (This is not a BAT or bash script, but a hybrid language. You can copy-paste the Windows commands into a command window. When bash starts, copy-paste each bash command (without "$"). )

rem Clean up from any previous run.
rem
del cy_ft_*.png

rem Run bash interactively, so we don't start and stop bash once per script.
rem
bash

$ # Create some test images.
$ #
$ convert rose: cy_ft_rose.png
$ convert cy_ft_rose.png -gravity West -crop 20x0+0+0 +repage cy_ft_left.png
$ convert cy_ft_rose.png -gravity North -crop 0x20+0+0 +repage cy_ft_top.png
$ convert rose: \
$    -channel R -evaluate Pow 3 \
$    -channel GB -evaluate Pow 0.4 \
$    cy_ft_rose_skew_hist.png


$ # Run each script.
$ #
$ 3Drotate pan=30 tilt=30 roll=30 cy_ft_rose.png cy_ft_rose_3drot.png
$ 3Dbox pan=30 tilt=30 roll=30 cy_ft_rose.png cy_ft_left.png cy_ft_top.png cy_ft_rose_3dbox.png
$ 3Dcover cy_ft_rose.png cy_ft_rose_3dcov.png
$ 3Dreflection cy_ft_rose.png cy_ft_rose_3dref.png
$ cylinderize cy_ft_rose.png cy_ft_rose_cyl.png
$ fmwplot cy_ft_rose.png cy_ft_rose_plt.png
$ histmatch -c rgb cy_ft_rose.png cy_ft_rose_skew_hist.png cy_ft_hist.png

$ exit

The script makes these test images:

cy_ft_rose.png cy_ft_left.png cy_ft_top.png cy_ft_rose_skew_hist.png

Fred's scripts create these outputs:

cy_ft_rose.png cy_ft_rose_3drot.png cy_ft_rose_3dbox.png cy_ft_rose_3dcov.png cy_ft_rose_3dref.png cy_ft_rose_cyl.png cy_ft_rose_plt.png cy_ft_hist.png

Translating between Windows and Unix

Some differences between Windows cmd and Cygwin bash:

cmd bash
Case doesn't matter (ie case insensitive) Case does matter (ie case sensitive)
Directory separators are '\' (though '/' often works) Directory separators are '/'
Variables are bracketed with '%' Variables are prefixed with '$'
Escape character is '^'. Escape character is '\'.
In scripts, percent signs '%' often need doubling Don't double percent signs
In scripts, parentheses don't need escaping unless they are inside for (..) or if (..) Parentheses need escaping: \( and \)
Commands are often noisy, telling us what they are doing Commands are usually quiet unless things go wrong
Commands in BAT scripts are echoed to the console by default In bash scripts, commands are not echoed by default,
but are echoed if we use bash -verbose
Each device has its own current working directory There are no devices
Often uses double-quote character (") Often uses single-quote character (')
Directories usually don't have extensions Directories and executable files usually don't have extensions

Piping and redirection work in similar ways. Looping and control-flow are very different.

In bash, the hash character # has a special meaning. When used to define a colour such as #00f it usually needs to be escaped or quoted: \#00f or '#00f' or "#00f". As double-quotes work in both bash and BAT, they are my preference.

Both cmd and bash have internal and external commands. External commands are .exe programs, stored on disk, that can be run from both cmd and bash. Internal commands are built-in to the shell, so cmd internal commands can be run only from cmd, and bash internal commands can be run only from bash.

Here are some example commands. They are internal, except where marked (*). n/a means there is no exact equivalent.

cmd bash Action
cd pwd (*) Show the current working directory
cd mysubdir cd mysubdir Change to a subdirectory of the current one
cd .. cd .. Move up one directory
F: n/a Change to current directory of device "F:"
cd \ n/a Change to root directory of current device
n/a cd / Change to root directory
dir /b ls (*) List files; short format
dir ls -l (*) List files; long format
dir /s ls -l -R (*) List files; long format; recurse into subdirectories
md mysubdir mkdir mysubdir (*) Make a directory
rd mysubdir rmdir mysubdir (*) Remove a directory
copy from.ext to.ext cp from.ext to.ext (*) Copy a file
xcopy from.ext to.ext(*) cp from.ext to.ext (*) Copy a file
del file.ext rm file.ext Delete (remove) a file
ren old.ext new.ext mv old.ext new.ext Rename a file
echo Hello echo Hello Write text
type file.ext cat file.ext (*) Write the contents of a file
exit exit Exit from a script or shell
exit /B 0 exit 0 Exit from a script or shell, returning 0
where myprog type -a myprog Lists full path to program named myprog
rem This is a comment
:: This is a comment
# This is a comment Comments are ignored
set var=value var=value
declare var=value
local var=value
Assigns value to an environment variable
set set List environment variables

My BAT scripts often contain code to assign results of arithmetic expressions to variables, where the assignments are given in a -format, separating each assignment with \n. Like this:

for /F "usebackq" %%L in (`magick ... ^
  -format "W_2=%%[fx:w/2]\nH_2=%%[fx:h/2]" ^
  info:`) do set %%L

In bash, this would be:

declare `magick ... \
  -format "W_2=%[fx:w/2]\nH_2=%[fx:h/2]" \
  info:`

Or:

declare $(magick ... \
  -format "W_2=%[fx:w/2]\nH_2=%[fx:h/2]" \
  info:)

For more examples of sending IM text data to variables, see Text data.

Windows console or Cygwin terminal?

If you want to run bash scripts under Windows, should you use a Cygwin terminal or a Windows console? In the Windows console, you need to type "bash" to enter bash. In the Cygwin terminal, you are already running bash. That seems the most significant difference.

If you want to run a Windows console so it immediately runs bash instead of cmd, then type ...

cmd /C start bash

... from either cmd or bash.

On the other hand, if you want to run the Cygwin terminal so it runs cmd instead of bash, then type ...

mintty -e cmd

... from either cmd or bash.

Building IM

If you have the Cygwin's "Devel" package, you can build ImageMagick, and build IM demonstration progams. I describe this in the pages Compiling IM with Cygwin and Compiling the MagickWand demonstration programs.

Cygwin for pre-built IM bash scripts

If you simply want to use pre-built ImageMagick bash scripts, (such as Fred's ImageMagick Scripts) I suggest you follow these instructions. See the above sections for more detailed instructions, and alternatives.

  1. If you haven't already, install the Windows ImageMagick binary from the official Download Binary Releases IM page. Put the directory at the front of the Windows environment variable Path.
  2. Install Cygwin from the Cygwin homepage. Include the bc package. Do not include ImageMagick.
  3. Create a directory where you will store pre-built scripts.
  4. Set Windows environment variables:
  5. Download the pre-built scripts to the directory you made in step (3).
  6. Start a new command console. If this is a Windows console, type "bash" to start bash.
  7. Run any pre-built bash scripts as required by typing the script name and any required arguments. For image files, give directory names in Windows format but with forward slashes, and either relative or absolute paths.
  8. If you want to edit the script, go ahead. Fred's scripts often write temporary files to "./", which is the current directory, and deletes them at the end. This works with no problem, and I suggest you don't change it.
  9. If the script refers to absolute paths such as "/tmp", this may cause problems, and these should be changed to relative paths such as "." or "./tmp".

This page was developed for the following software versions:

Version: ImageMagick 7.1.0-42 Q16-HDRI x64 396d87c:20220709 https://imagemagick.org
Copyright: (C) 1999 ImageMagick Studio LLC
License: https://imagemagick.org/script/license.php
Features: Cipher DPC HDRI OpenCL 
Delegates (built-in): bzlib cairo freetype gslib heic jng jp2 jpeg jxl lcms lqr lzma openexr pangocairo png ps raqm raw rsvg tiff webp xml zip zlib
Compiler: Visual Studio 2022 (193231332)
GNU bash, version 4.4.12(3)-release (x86_64-unknown-cygwin)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Source file for this web page is cygwin.h1. To re-create this web page, run "procH1 cygwin".


This page, including the images, is my copyright. Anyone is permitted to use or adapt any of the code, scripts or images for any purpose, including commercial use.

Anyone is permitted to re-publish this page, but only for non-commercial use.

Anyone is permitted to link to this page, including for commercial use.


Page version v1.0 28-July-2014.

Page created 02-Sep-2022 03:36:40.

Copyright © 2022 Alan Gibson.