## Defining custom commands

However, that command line is a little longer than I prefer to type each time
I want to develop a picture. So let's see how this can be simplified! There
are powerful ways to do this since G'MIC actually is a kind of command macro
system. Commands are built from other commands. Below is a simple command
definition:

	#@gmic resize_thebigpicture : : Resize the image 990 px wide, the same width as in Boston Globe's "The Big Picture"
	resize_thebigpicture :
	-e "Resize image$?"
	-v - -repeat @#
	-resize2dx 990,5
	-mv[-1] 0 -done -v +

Let's go through this code and see what it does. First we have a comment line,
it starts with a hash (#) but with a twist: this is an "intelligent comment"
that gmic uses when it provides online help. It is a good idea to begin each
command definition with a comment that begins `#@gmic`. Following this comes
the command name, the arguments it uses, and a descriptive sentence about what
it does. These different parts are separated by colons - in this case the
command does not take any arguments.

Next follows the actual command definition. This command is called
`resize_thebigpicture`. It performs a resizing operation, with a predefined
width - the same width as is used for images in the excellent [The Big
Picture](http://www.boston.com/bigpicture) blog. If you want your pictures to
look as good as these, it is a good idea to resize them to this size!

The command definition starts with the command name, followed by a
colon. Leave this on its own line, and on the following lines add the actual
commands that should be performed by this command.

The gut of this command is the resize operation, `-resize2dx 990,5` which
resizes, keeping image proportions, to the width 990 pixels using bi-cubic
interpolation. Surrounding this command is something I would call recommended
boilerplate code. The `-e "Resize image$?"` line will print a helpful comment
as the command executes. The dollarsign-questionmark `$?` part of this
comment will be substituted with a note about what image this is applied to as
it executes.

`-v -` will decrease the comment verbosity one notch for the following
commands. This makes G'MIC print less details as it executes, to make the
output of command invocation more concise. As you can see, the command
definition ends with `-v +` which increases the comment verbosity again, so the
change actually only applies within this command. This will make it possible
to get more or less information from gmic as it executes.

Between these two comment modifiers is a form of loop. But to understand this
loop it is important to understand that gmic works not only with one image at
a time, but with any number of images. Think of gmic as applying commands to a
number of images, just like cars running through an assembly line. But instead
of cars there are images, and instead of robots doing welding and painting
there are image commands. Also, in this assembly line, each robot will finish
all its cars before the next robot starts.

To get a command to work on many images, we should write it to work with a
loop. It begins with `-repeat @#` and ends with `-done`. This will repeat as
many times as there are images waiting for the command. `@#` is shorthand for
the number of arguments, and this is the number of repetitions that will be
made. After each resize2dx command has been performed in this loop, the images
waiting for the command will be rotated. `-mv[-1] 0` will take care of this
rotation. This is the `move` command. In this case the move command will move
the last image in the list to be the first. Images are addressed like this:
[0] is the first image in the list of images, [1] is the following and so
on. [-1] is the last image, and [-2] is the one before that. Every command can
act on any image, you only need to tell it which image it should be applied
to.

This system may seem complex but it is part of what makes G'MIC
powerful. Think of these lists as layers in Photoshop and you will understand
what kind of operations can be performed this way!

To make a long story short, a custom command definition may look complex, but
it is quite simple, if you consider that you can use copy and paste. And there
is an excellent source to copy from - in fact a very big part of G'MIC is
actually defined as commands just like
this. [gmic_def.gmic](http://cimg.cvs.sourceforge.net/*checkout*/cimg/CImg/examples/gmic_def.gmic)
contains approximately 160 commands defined in just in this way, and by
studying a command that does approximately what you want to accomplish, you
get lots of help to accomplish your goal.

Put your command in a separate text file called "custom.gmic" and give it to
gmic as argument. Then call your new command 

	gmic -m custom.gmic image.jpg -resize_thebigpicture -output resized.jpg

and you will have a newly resized, stunning image to submit to The Boston
Globe. But why not apply it to two images at once?

	gmic -m custom.gmic image1.jpg image2.jpg -resize_thebigpicture -output[0] resized1.jpg -output[1] resized2.jpg

And let's get some help for our new command:

	gmic -m custom.gmic -help resize_thebigpicture


	gmic : GREYC's Magic Image Converter (Oct 21 2009, 02:06:35)


	Version 1.3.2.8, Copyright (C) 2008-2009, David Tschumperle (http://gmic.sourceforge.net)


	-resize_thebigpicture
	Resize the image 990 px wide, the same width as in Boston Globe's "The Big Picture"

With this introduction to command macros, it is time to apply it to our raw
converter toolchain:

	#@gmic resize_thebigpicture : : Resize the image 990 px wide, the same width as in Boston Globe's "The Big Picture"
	resize_thebigpicture :
	-e "Resize image$?"
	-v - -repeat @#
	-resize2dx 990,5
	-mv[-1] 0 -done -v +

	#@gmic linear16develop : '"outfile"' : Develop a linear 16 bit image and write to 16 bit file.
	linear16develop :
	-e "Develop image$?."
	-v - -repeat @#
	-linear16boost -write16 $1
	-done -v +

	#@gmic linear16develop_preview : '"outfile"' : Develop a linear 16 bit
	#image, downsize it to preview size, and write to 8 bit file.
	linear16develop_preview :
	-e "Develop image$?."
	-v - -repeat @#
	-linear16boost -resize_thebigpicture -convert16to8 -write8 $1
	-done -v +
	
	#@gmic linear16boost : : Operations on linear 16 bit image: gamma, contrast, color boost.
	linear16boost :
	-e "Gamma, contrast, color boost on image$?."
	-v - -type float -repeat @#
	# RGB operations requires values in 8-bit range, so downsize
	# (will still be floating point so high precision)
	-div 256
	-gimp_channel_processing 2.2,1,0,0,2,12,88,256,0,0
	-gimp_mix_lab 1,0,0,1.3,0,0,1.3,0,0,0,2
	-mul 256
	-mv[-1] 0 -done -v +

	#@gmic convert16to8 : : Convert image values retrieved in 16 bit to fit in 8 bit.
	convert16to8 :
	-e "Converting to 8 bit for image$?."
	-v - -repeat @#
	-div 256
	-mv[-1] 0 -done -v +

	#@gmic write16 : '"outfile"' : Write 16 bit image to file.
	write16 :
	-e "Writing image$?."
	-v - -repeat @#
	-c 0,65536 -type ushort -o $1
	-mv[-1] 0 -done -v +

	#@gmic write8 : '"outfile"' : Write 8 bit image to file.
	write8 :
	-e "Writing image$?."
	-v - -repeat @#
	-c 0,255 -type uchar -o $1
	-mv[-1] 0 -done -v +


Here we have broken up the steps performed earlier in a number of commands and
combined them so we both can apply them individually, using simpler names, do
all steps at once, or combine them with other G'MIC commands:

	dcraw -c -w -4 image.cr2 | gmic -m custom.gmic -.ppm \
	-linear16develop_preview image_preview.jpg

	dcraw -c -w -4 image.cr2 | gmic -m custom.gmic -.ppm \
	-linear16develop image.tiff

	dcraw -c -w -4 image.cr2 | gmic -m custom.gmic -.ppm \
	-linear16boost -sharpen 50 -smooth 25 -write16 image2.tiff

All these commands were defined using the same pattern: a comment, the command
name followed by its containing commands, in order: an output message, a
logging adjustment, a loop, the actual operation of the command, rotation the
image list, ending the loop and re-adjusting the logging level. The only thing
that is new here are commands that take arguments, such as the filename in the
image write commands. Arguments should be declared in the comment, and to
access the argument, you use $1, $2, $3 etc for each argument in order. Much
of this will feel familiar if you have developed shell scripts before.

