\chapter{Making Tiled MIP-Map Texture Files With {\cf maketx}}
\label{chap:maketx}
\indexapi{maketx}

\section{Overview}

The \maketx program will read an image (from any file format for
which an \ImageInput plugin can be found) and then write it in a form
in which it will have high performance when used by \TextureSystem
(Chapter~\ref{chap:texturesystem}).  This involves converting it to
tiled (versus scanline) orientation, writing multiple subimages at
different resolutions (MIP-map), and setting a variety of header or
metadata fields appropriately for texture maps.

The \maketx utility is invoked as follows:

\medskip

\hspace{0.25in} {\cf maketx} [\emph{options}] \emph{input}... -o \emph{output}

\medskip

Where \emph{input} and \emph{output} name the input image and desired
output filename.  The input files may be of any image 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).


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

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

\apiitem{-v}
Verbose status messages, including runtime statistics and timing.
\apiend

\apiitem{-o {\rm \emph{outputname}}}
Sets the name of the output texture.
\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{--format {\rm \emph{formatname}}}
Specifies the image format of the output file (e.g., ``tiff'',
``OpenEXR'', etc.).  If {\cf --format} is not used, \maketx will 
guess based on the file extension of the output filename; if it
is not a recognized format extension, TIFF will be used by default.
\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}.

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

In either case, the output file format itself (implied by the file
extension of the output filename) may trump the request if the file
format simply does not support the requested data type.
\apiend

\apiitem{--tile {\rm \emph{x}} {\rm \emph{y}}}
Specifies the tile size of the output texture.  If not specified,
\maketx will make $64 \times 64$ tiles.
\apiend

\apiitem{--separate}
Forces ``separate'' (e.g., RRR...GGG...BBB) packing of channels in the
output file.  Without this option specified, ``contiguous'' (e.g.,
RGBRGBRGB...) packing of channels will be used for those file formats
that support it.
\apiend

\apiitem{--compression {\rm \emph{method}}}
Sets the compression method for the output image (the default is to try
to use \qkw{zip} compression, if it is available).
\apiend

\apiitem{--update}
Ordinarily, textures are created unconditionally (which could take
several seconds for large input files if read over a network) and will
be stamped with the current time.

The {\cf --update} option enables \emph{update mode}I if the output file
already exists and has the same time stamp as the input file, the
texture will not be recreated.  If the output file does not exist or has
a different time than the input file, then the texture will be created
be given the time stamp of the input file.
\apiend

\apiitem{--wrap {\rm \emph{wrapmode}} \\
--swrap {\rm \emph{wrapmode}} --twrap {\rm \emph{wrapmode}}}
Sets the default \emph{wrap mode} for the texture, which determines
the behavior when the texture is sampled outside the $[0,1]$ range.
Valid wrap modes are: {\cf black}, {\cf clamp}, {\cf periodic},
{\cf mirror}.  The default, if none is set, is {\cf black}.  The
{\cf --wrap} option sets the wrap mode in both directions
simultaneously, while the {\cf --swrap} and {\cf --twrap} may be used to
set them individually in the $s$ (horizontal) and $t$ (vertical)
diretions.

Although this sets the default wrap mode for a texture, note that
the wrap mode may have an override specified in the texture lookup
at runtime.
\apiend

\apiitem{--resize}
Causes the highest-resolution level of the MIP-map to be a
power-of-two resolution in each dimension
(by rounding up the resolution of the input image).  There is no
good reason to do this for the sake of OIIO's texture system, but 
some users may require it in order to create MIP-map images
that are compatible with both OIIO and other texturing systems that
require power-of-2 textures.
\apiend

\apiitem{--filter {\rm \emph{name}}}
By default, the resizing step that generates successive MIP levels
uses a triangle filter to bilinearly combine pixels (for MIP levels
with even number of pixels, this is also equivalent to a box filter,
which merely averages groups of 4 adjacent pixels).  This is fast,
but for source images with high frequency content, can result in 
aliasing or other artifacts in the lower-resolution MIP levels.

The {\cf --filter} option selects a high-quality filter to use when
resizing to generate successive MIP levels.  Choices include
{\cf lanczos3} (our best recommendation for highest-quality filtering, a
3-lobe Lanczos filter), {\cf box}, {\cf triangle}, {\cf catrom},
{\cf blackman-harris}, {\cf gaussian}, {\cf mitchell}, {\cf bspline},
\qkw{cubic}, \qkw{keys}, \qkw{simon},
\qkw{rifman}, {\cf radial-lanczos3}, {\cf disk}, {\cf sinc}.

If you select a filter with negative lobes (including
{\cf lanczos3}, {\cf sinc}, {\cf lanczos3}, {\cf keys}, {\cf simon},
{\cf rifman}, or {\cf catrom}), and your
source image is an HDR image with very high contrast regions that
include pixels with values $>1$, you may also wish to use the
{\cf --rangecompress} option to avoid ringing artifacts.
\apiend

\apiitem{--hicomp}
Perform highlight compensation.  When HDR input data with high-contrast
highlights is turned into a MIP-mapped texture using a high-quality
filter with negative lobes (such as {\cf lanczos3}), objectionable
ringing could appear near very high-contrast regions with pixel values
$>1$. This option improves those areas by using range compression
(transforming values from a linear to a logarithmic scale that greatly
compresses the values $> 1$) prior to each
image filtered-resize step, and then expanded back to a linear format
after the resize, and also clamping resulting pixel values to be
non-negative.  This can result in some loss of energy, but often this is
a preferable alternative to ringing artifacts in your upper MIP levels.
\apiend

\apiitem{--nomipmap}
Causes the output to \emph{not} be MIP-mapped, i.e., only will have
the highest-resolution level.
\apiend

\apiitem{--nchannels {\rm \emph{n}}}
Sets the number of output channels.  If \emph{n} is less than the 
number of channels in the input image, the extra channels will simply
be ignored.  If \emph{n} is greater than the number of channels in the
input image, the additional channels will be filled with 0 values.
\apiend

\apiitem{--chnames {\rm \emph{a,b,...}}}
Renames the channels of the output image.  All the channel names are
concatenated together, separated by commas.  A ``blank'' entry will cause
the channel to retain its previous value (for example, {\cf --chnames ,,,A}
will rename channel 3 to be \qkw{A} and leave channels 0--2 as they were.
\apiend

\apiitem{--checknan}
Checks every pixel of the input image to ensure that no NaN or Inf
values are present.  If such non-finite pixel values are found, 
an error message will be printed and {\cf maketx} will terminate without
writing the output image (returning an error code).
\apiend

\apiitem{--fixnan {\rm \emph{streategy}}}
Repairs any pixels in the input image that contained {\cf NaN} or 
{\cf Inf} values (hereafter referred to collectively as ``nonfinite'').
If \emph{strategy} is {\cf black}, nonfinite values will be replaced
with {\cf 0}.  If \emph{strategy} is {\cf box3}, nonfinite values will
be replaced by the average of all the finite values within a $3 \times 3$
region surrounding the pixel.
\apiend

\apiitem{--fullpixels}
Resets the ``full'' (or ``display'') pixel range to be the ``data''
range.  This is used to deal with input images that appear, in their
headers, to be crop windows or overscanned images, but you want to treat
them as full 0--1 range images over just their defined pixel data.
\apiend

%\apiitem{--ingamma {\rm \emph{value}} \\
%--outgamma {\rm \emph{value}}}
%Not currently implemented
%\apiend

\apiitem{--Mcamera {\rm \emph{...16 floats...}} \\
--Mscreen {\rm \emph{...16 floats...}}}
Sets the camera and screen matrices (sometimes called {\cf Nl} and
{\cf NP}, respectively, by some renderers) in the texture file, 
overriding any such matrices that may be in the input image (and would
ordinarily be copied to the output texture).
\apiend

\apiitem{--prman-metadata}
Causes metadata \qkw{PixarTextureFormat} to be set, which is useful if
you intend to create an OpenEXR texture or environment map that can be
used with PRMan as well as OIIO.
\apiend

\apiitem{--constant-color-detect}
Detects images in which all pixels are identical, and outputs the
texture at a reduced resolution equal to the tile size, rather than
filling endless tiles with the same constant color.  That is, by
substituting a low-res texture for a high-res texture if it's a constant
color, you could save a lot of save disk space, I/O, and texture cache size.
It also sets the \qkw{ImageDescription} to contain a
special message of the form \qkw{ConstantColor=[r,g,...]}.  
\apiend

\apiitem{--monochrome-detect}
Detects multi-channel images in which all color components are
identical, and outputs the texture as a single-channel image instead.
That is, it changes RGB images that are gray into single-channel gray
scale images.

Use with caution!  This is a great optimization if such textures will
only have their first channel accessed, but may cause unexpected behavior
if the ``client'' application will attempt to access those other
channels that will no longer exist.
\apiend

\apiitem{--opaque-detect}
Detects images that have a designated alpha channel for which the alpha value
for all pixels is 1.0 (fully opaque), and omits the alpha channel from
the output texture.  So, for example, an RGBA input texture where A=1
for all pixels will be output just as RGB.  The purpose is to save disk
space, texture I/O bandwidth, and texturing time for those textures
where alpha was present in the input, but clearly not necessary.

Use with caution!  This is a great optimization only if your use of such
textures will assume that missing alpha channels are equivalent to
textures whose alpha is 1.0 everywhere.
\apiend

\apiitem{--ignore-unassoc}
Ignore any header tags in the input images that indicate that the
input has ``unassociated'' alpha.  When this option is used, color
channels with unassociated alpha will not be automatically multiplied
by alpha to turn them into associated alpha. This is also a good way
to fix input images that really are associated alpha, but whose headers
incorrectly indicate that they are unassociated alpha. 
\apiend

\apiitem{--prman}
PRMan is will crash in strange ways if given textures that don't have
its quirky set of tile sizes and other specific metadata.  If you want
\maketx to generate textures that may be used with either \OpenImageIO
or PRMan, you should use the {\cf --prman} option, which will set
several options to make PRMan happy, overriding any contradictory
settings on the command line or in the input texture.  

Specifically, this option sets the tile size (to 64x64 for 8 bit,
64x32 for 16 bit integer, and 32x32 for float or {\cf half} images),
uses ``separate'' planar configuration ({\cf --separate}), and sets
PRMan-specific metadata ({\cf --prman-metadata}).  It also outputs 
sint16 textures if uint16 is requested (because PRMan for some reason
does not accept true uint16 textures).

\OpenImageIO will happily accept textures that conform to PRMan's
expectations, but not vice versa.  But \OpenImageIO's \TextureSystem
has better performance with textures that use \maketx's default settings
rather than these oddball choices.  You have been warned!
\apiend

\apiitem{--oiio}
This sets several options that we have determined are the 
optimal values for \OpenImageIO's \TextureSystem, overriding any
contradictory settings on the command line or in the input texture.

Specifically, this is the equivalent to using \\
 {\cf --separate --tile 64 64 --hash}.
\apiend

\apiitem{--colorconvert {\rm \emph{inspace outspace}}}
Convert the color space of the input image from \emph{inspace} to
\emph{tospace}.  If OpenColorIO is installed and finds a valid
configuration, it will be used for the color conversion.  If OCIO
is not enabled (or cannot find a valid configuration, OIIO will at
least be able to convert among linear, sRGB, and Rec709.
\apiend

\apiitem{--unpremult}
When undergoing color some conversions, it is helpful to
``un-premultiply'' the alpha before converting color channels, and then
re-multiplying by alpha.  Caveat emptor -- if you don't know exactly
when to use this, you probably shouldn't be using it at all.
\apiend


\apiitem{--mipimage {\rm \emph{filename}}}
Specifies the name of an image file to use as a custom MIP-map level, 
instead of simply downsizing the last one.  This option may be used
multiple times to specify multiple levels.  For example:
\begin{code}
    maketx 256.tif --miplevel 128.tif --miplevel 64.tif -o out.tx
\end{code}
This will make a texture with the first MIP level taken from {\cf 256.tif},
the second level from {\cf 128.tif}, the third from {\cf 64.tif}, and
then subsequent levels will be the usual downsizings of {\cf 64.tif}.
\apiend

\apiitem{--envlatl}
Creates a latitude-longitude environment map, rather than an ordinary
texture map.
\apiend

\apiitem{--lightprobe}
Creates a latitude-longitude environment map, but in contrast to
{\cf --envlatl}, the original input image is assumed to be formatted
as a \emph{light probe} image\footnote{See
{\cf http://www.pauldebevec.com/Probes/} for examples and an explanation
of the geometric layout.}.
\apiend


% --shadow --shadcube
% --volshad --envlatl --envcube --lightprobe --latl2envcube --vertcross
% --fov
% --opaquewidth


\begin{comment}

\section{{\cf maketx} Recipes}

% FIXME

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

\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 maketx} utility will simply infer the file format from the
file extension. The following example converts a PNG image to JPEG:

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

\end{comment}
