\chapter{Converting Image Formats With {\kw iconvert}}
\label{chap:iconvert}
\indexapi{iconvert}

\section{Overview}

The {\cf iconvert} program will read an image (from any file format for
which an \ImageInput plugin can be found) and then write the image to a
new file (in any format for which an \ImageOutput plugin can be found).
In the process, {\cf iconvert} can optionally change the file format or
data format (for example, converting floating-point data to 8-bit
integers), apply gamma correction, switch between tiled and scanline
orientation, or alter or add certain metadata to the image.

The {\cf iconvert} utility is invoked as follows:

\medskip

\hspace{0.25in} {\cf iconvert} [\emph{options}] \emph{input} \emph{output}

\medskip

Where \emph{input} and \emph{output} name the input image and desired
output filename.  The image files may be of any format recognized by
\product (i.e., for which \ImageInput plugins are available).  The file
format of the output image will be inferred from the file extension of
the output filename (e.g., \qkw{foo.tif} will write a TIFF file).

Alternately, any number of files may be specified as follows:

\medskip

\hspace{0.25in} {\cf iconvert --inplace} [\emph{options}] \emph{file1 file2 ..}

\medskip

When the {\cf --inplace} option is used, any number of file names $\ge
1$ may be specified, and the image conversion commands are applied to
each file in turn, with the output being saved under the original file
name.  This is useful for applying the same conversion to many files,
or simply if you want to replace the input with the output rather than
create a new file with a different name.

\section{{\cf iconvert} Recipes}

This section will give quick examples of common uses of {\cf iconvert}.

\subsection*{Converting between file formats}

It's a snap to converting among image formats supported by \product
(i.e., for which \ImageInput and \ImageOutput plugins can be found).
The {\cf iconvert} utility will simply infer the file format from the
file extension. The following example converts a PNG image to JPEG:

\begin{code}
    iconvert lena.png lena.jpg
\end{code}

\subsection*{Changing the data format or bit depth}

Just use the {\cf -d} option to specify a pixel data format.  For
example, assuming that {\cf in.tif} uses 16-bit unsigned integer
pixels, the following will convert it to an 8-bit unsigned pixels:

\begin{code}
    iconvert -d uint8 in.tif out.tif
\end{code}

\subsection*{Changing the compression}

The following command converts writes a TIFF file, specifically using
LZW compression:

\begin{code}
    iconvert --compression lzw in.tif out.tif
\end{code}

The following command writes its results as a JPEG file at a compression
quality of 50 (pretty severe compression), illustrating how some compression
methods allow a quality metric to be optionally appended to the name:

\begin{code}
    iconvert --compression jpeg:50 50 big.jpg small.jpg
\end{code}

\subsection*{Gamma-correcting an image}

The following gamma-corrects the pixels, raising all pixel
values to $x^{1/2.2}$ upon writing:

\begin{code}
    iconvert -g 2.2 in.tif out.tif
\end{code}

\subsection*{Converting between scanline and tiled images}

Convert a scanline file to a tiled file with $16 \times 16$ tiles:

\begin{code}
    iconvert --tile 16 16 s.tif t.tif
\end{code}

\noindent Convert a tiled file to scanline:

\begin{code}
    iconvert --scanline t.tif s.tif
\end{code}


\subsection*{Converting images in place}

You can use the {\cf --inplace} flag to cause the output to
\emph{replace} the input file, rather than create a new file with a
different name.  For example, this will re-compress all of your 
TIFF files to use ZIP compression (rather than whatever they currently
are using):

\begin{code}
    iconvert --inplace --compression zip *.tif
\end{code}

\subsection*{Change the file modification time to the image capture time}

Many image formats (including JPEGs from digital cameras) contain an
internal time stamp indicating when the image was captured.  But the
time stamp on the file itself (what you'd see in a directory listing
from your OS) most likely shows when the file was last copied, not when
it was created or captured.  You can use the following command to
re-stamp your files so that the file system modification time matches
the time that the digital image was originally captured:

\begin{code}
    iconvert --inplace --adjust-time *.jpg
\end{code}

\subsection*{Add captions, keywords, IPTC tags}

For formats that support it, you can add a caption/image description,
keywords, or arbitrary string metadata:

\begin{code}
    iconvert --inplace --adjust-time --caption "Hawaii vacation" *.jpg

    iconvert --inplace --adjust-time --keyword "John" img18.jpg img21.jpg

    iconvert --inplace --adjust-time --attrib IPTC:State "HI" \
              --attrib IPTC:City "Honolulu" *.jpg
\end{code}

\medskip

\section{{\cf iconvert} command-line options}

\apiitem{--help}
Prints usage information to the terminal.
\apiend

\apiitem{-v}
Verbose status messages.
\apiend

\apiitem{--threads \emph{n}}
Use \emph{n} execution threads if it helps to speed up image operations.
The default (also if $n=0$) is to use as many threads as there are cores
present in the hardware.
\apiend

\apiitem{--inplace}
Causes the output to \emph{replace} the input file, rather than create a
new file with a different name.

Without this flag, {\cf iconvert} expects two file names, which will
be used to specify the input and output files, respectively.

But when {\cf --inplace} option is used, any number of file names $\ge 1$ may
be specified, and the image conversion commands are applied to each file
in turn, with the output being saved under the original file name.  This
is useful for applying the same conversion to many files.  

For example, the following example will add the caption ``Hawaii
vacation'' to all JPEG files in the current directory:

\begin{code}
        iconvert --inplace --adjust-time --caption "Hawaii vacation" *.jpg
\end{code}
\apiend

\apiitem{-d {\rm \emph{datatype}}}
Attempt to sets the output pixel data type to one of: {\cf uint8}, 
{\cf sint8}, {\cf uint16}, {\cf sint16}, {\cf half}, {\cf float}, 
{\cf double}.

The types {\cf uint10} and {\cf uint12} may be used to request 10- or
12-bit unsigned integers.  If the output file format does not support
them, {\cf uint16} will be substituted.

If the {\cf -d} option is not supplied, the output data type will
be the same as the data format of the input file, if possible.

In any case, if the output file type does not support the requested
data type, it will instead use whichever supported data type results
in the least amount of precision lost.

\apiend

% FIXME -- no it doesn't!
\apiitem{-g {\rm \emph{gamma}}}
Applies a gamma correction of $1/\mathrm{gamma}$ to the pixels as they
are output.
\apiend

\apiitem{--sRGB}
Explicitly tags the image as being in sRGB color space.  Note that this
does not alter pixel values, it only marks which color space those
values refer to (and only works for file formats that understand such
things).  An example use of this command is if you have an image 
that is not explicitly marked as being in any particular color space,
but you know that the values are sRGB.
\apiend

\apiitem{--tile {\rm \emph{x}} {\rm \emph{y}}}
Requests that the output file be tiled, with the given $x \times y$ 
tile size, if tiled images are supported by the output format.
By default, the output file will take on the tiledness and tile size
of the input file.
\apiend

\apiitem{--scanline}
Requests that the output file be scanline-oriented (even if the input
file was tile-oriented), if scanline orientation is supported by the
output file format.  By default, the output file will be scanline
if the input is scanline, or tiled if the input is tiled.
\apiend

\apiitem{--separate \\
--contig}
Forces either ``separate'' (e.g., RRR...GGG...BBB) or ``contiguous''
(e.g., RGBRGBRGB...) packing of channels in the file.  If neither
of these options are present, the output file will have the same
kind of channel packing as the input file.  Of course, this is ignored
if the output file format does not support a choice or does not support
the particular choice requested.
\apiend

\apiitem{--compression {\rm \emph{method}} \\
--compression {\rm \emph{method}{\cf :}\emph{quality}}}
Sets the compression method, and optionally a quality setting, for the
output image.  Each \ImageOutput plugin will have its own set of methods
that it supports.

By default, the output image will use the same compression technique as
the input image (assuming it is supported by the output format,
otherwise it will use the default compression method of the output
plugin).
\apiend

\apiitem{--quality {\rm \emph{q}}}
Sets the compression quality, on a 1--100 floating-point scale.
This only has an effect if the particular compression method supports
a quality metric (as JPEG does).

% DEPRECATED(2.1)
This is considered deprecated, and in general we now recommend just
appending the quality metric to the {\cf compression name:qual}.
\apiend

\apiitem{--no-copy-image}
Ordinarily, {\cf iconvert} will attempt to use {\cf
  ImageOutput::copy_image}
underneath to avoid de/recompression or alteration of pixel values,
unless other settings clearly contradict this (such as any settings
that must alter pixel values).  The use of {\cf --no-copy-image} will
force all pixels to be decompressed, read, and compressed/written,
rather than copied in compressed form.  We're not exactly sure when
you would need to do this, but we put it in just in case.
\apiend

\apiitem{--adjust-time}
When this flag is present, after writing the output, the resulting
file's modification time will be adjusted to match any \qkw{DateTime}
metadata in the image.  After doing this, a directory listing will show
file times that match when the original image was created or captured,
rather than simply when {\cf iconvert} was run.  This has no effect on
image files that don't contain any \qkw{DateTime} metadata.
\apiend

\apiitem{--caption {\rm \emph{text}}}
Sets the image metadata \qkw{ImageDescription}.
This has no effect if the output image format does not support some kind
of title, caption, or description metadata field.
Be careful to enclose \emph{text} in quotes if you want your caption to
include spaces or certain punctuation!
\apiend

\apiitem{--keyword {\rm \emph{text}}}
Adds a keyword to the image metadata \qkw{Keywords}.  Any existing
keywords will be preserved, not replaced, and the new keyword will not
be added if it is an exact duplicate of existing keywords.  This has no
effect if the output image format does not support some kind of keyword
field.  

Be careful to enclose \emph{text} in quotes if you want your keyword to
include spaces or certain punctuation.  For image formats that have only
a single field for keywords, \OpenImageIO will concatenate the keywords,
separated by semicolon (`;'), so don't use semicolons within your
keywords.
\apiend

\apiitem{--clear-keywords}
Clears all existing keywords in the image.
\apiend

\apiitem{--attrib {\rm \emph{name text}}}
Sets the named image metadata attribute to a string given by
\emph{text}.  For example, you could explicitly set the IPTC location
metadata fields with:

\begin{code}
        iconvert --attrib "IPTC:City" "Berkeley" in.jpg out.jpg
\end{code}
\apiend

\apiitem{--orientation {\rm \emph{orient}}}
Explicitly sets the image's \qkw{Orientation} metadata to a numeric
value (see Section~\ref{metadata:orientation} for the numeric codes).
This only changes the metadata field that specifies
how the image should be displayed, it does NOT alter the pixels
themselves, and so has no effect for image formats that don't
support some kind of orientation metadata.
\apiend

\apiitem{--rotcw \\
--rotccw \\
--rot180}
Adjusts the image's \qkw{Orientation} metadata by rotating it $90^\circ$
clockwise, $90^\circ$ degrees counter-clockwise, or $180^\circ$,
respectively, compared to its current setting.  This only changes the
metadata field that specifies how the image should be displayed, it does
NOT alter the pixels themselves, and so has no effect for image formats
that don't support some kind of orientation metadata.
\apiend


\chapwidthend
