\chapter{Making Tiled MIP-Map Texture Files With \maketx or \oiiotool}
\label{chap:maketx}
\indexapi{maketx}
\index{Texture System!making textures with maketx}

\section{Overview}

The \TextureSystem (Chapter~\ref{chap:texturesystem}) will exhibit much
higher performance if the image files it uses as textures are tiled (versus
scanline) orientation, have multiple subimages at different resolutions
(MIP-mapped), and include a variety of header or metadata fields
appropriately set for texture maps. Any image that you intend to use as
input to \TextureSystem, therefore, should first be converted to have these
properties. An ordinary image will work as a texture, but without this
additional step, it will be drastically less efficient in terms of memory,
disk or network I/O, and time.

This can be accomplished programmatically using the \ImageBufAlgo\ {\cf
make_texture()} function (see Section~\ref{sec:iba:importexport} for C++ and
Section~\ref{sec:iba:py:importexport} for Python).

\product includes two command-line utilities capable of converting
ordinary images into texture files: \maketx and \oiiotool.\footnote{Why
are there two programs? Historical artifact -- \maketx existed first,
and much later \oiiotool was extended to be capable of directly writing
texture files. If you are simply converting an image into
a texture, \maketx is more straightforward and foolproof, in that you
can't accidentally forget to turn it into a texture, as you might do
with \oiiotool. On the other hand, \oiiotool is the way to go if you have
a complex series of image processing operations and want the end result
to be a texture, without having to write an intermediate file to feed
separately to \maketx.}

\section{\maketx}
\label{sec:maketx}

The \maketx program will convert ordinary images to efficient
textures. The \maketx utility is invoked as follows:

\medskip

\hspace{0.25in} {\cf maketx} [\emph{options}] \emph{input}... {\cf -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).

\medskip
\newpage

\noindent Command-line arguments are:

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

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

\apiitem{--runstats}
Print 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}} \\
--compression {\rm \emph{method}{\cf :}\emph{quality}}}
Sets the compression method, and optionally a quality setting,
for the output image (the default is to try
to use \qkw{zip} compression, if it is available).
\apiend

\apiitem{-u}
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 -u} option enables \emph{update mode}: if the output file
already exists, and has the same time stamp as the input file, and
the command-lie arguments that created it are identical to the
current ones, then the texture will be left alone and not be recreated.
If the output file does not exist, or has
a different time stamp than the input file, or was created using different
command line arguments, then the texture will be created
and 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{--sharpen {\rm \emph{contrast}}}
EXPERIMENTAL: USE AT YOUR OWN RISK!

This option will run an additional sharpening filter
when creating the successive MIP-map levels. It uses an unsharp mask
(much like in Section~\ref{sec:iba:unsharpmask}) to emphasize high-frequency
details to make features ``pop'' visually even at high MIP-map levels.
The \emph{contrast} controls the degree to which it does this. Probably
a good value to enhance detail but not go overboard is 0.5 or even 0.25.
A value of 1.0 may make strage artifacts at high MIP-map levels. Also, if
you simultaneously use {\cf --filter unsharp-median}, a slightly different
variant of unsharp masking will be used that employs a median filter to
separate out the low-frequencies, this may tend to help emphasize small
features while not over-emphasizing large edges. 
\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{--attrib {\rm \emph{name value}}}
Adds or replaces metadata with the given \emph{name} to have the
specified \emph{value}.

It will try to infer the type of the metadata from the value: if the
value contains only numerals (with optional leading minus sign), it will
be saved as {\cf int} metadata; if it also contains a decimal point, it
will be saved as {\cf float} metadata; otherwise, it will be saved as
a {\cf string} metadata.

For example, you could explicitly set the IPTC location metadata fields
with:
\begin{code}
        oiiotool --attrib "IPTC:City" "Berkeley" in.jpg out.jpg
\end{code}
\apiend

\apiitem{--sattrib {\rm \emph{name value}}}
Adds or replaces metadata with the given \emph{name} to have the
specified \emph{value}, forcing it to be interpreted as a {\cf string}.
This is helpful if you want to set a {\cf string} metadata to a value
that the {\cf --attrib} command would normally interpret as a number.
\apiend

\apiitem{--sansattrib}
When set, this edits the command line inserted in the \qkw{Software} and
\qkw{ImageHistory} metadata to omit any verbose {\cf --attrib} and
{\cf --sattrib} commands.
\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), and in the case of TIFF files will
omit the Exif directory block which will not be recognized by the older
version of libtiff used by PRMan.

\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}.
\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{--colorconfig {\rm \emph{name}}}
Explicitly specify a custom OpenColorIO configuration file. Without this,
the default is to use the {\cf \$OCIO} environment variable as a guide for
the location of the OpenColorIO configuration file.
\apiend

\apiitem{--unpremult}
When undergoing some color 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 --mipimage 128.tif --mipimage 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

\apiitem{--bumpslopes}
\index{bump mapping} \index{bump to roughness}
For a single channel input image representing height (that you would
ordinarily use for a bump or displacement), this produces a 6-channel
texture that contains the first and second moments of bump slope, which
can be used to implement certain bump-to-roughness techniques.
The channel layout is as follows:

\begin{tabular}{cll}
index & channel name & data at MIP level 0 \\
\hline
0 & \qkw{b0_h} & $h$   ~~~ (height)\\
1 & \qkw{b1_dhds} & $\partial h / \partial s$ \\
2 & \qkw{b2_dhdt} & $\partial h / \partial t$ \\
3 & \qkw{b3_dhds2} & $(\partial h / \partial s)^2$ \\
4 & \qkw{b4_dhdt2} & $(\partial h / \partial t)^2$ \\
5 & \qkw{b5_dhdsdt} & $(\partial h / \partial s) \cdot (\partial h / \partial t)$ \\
\end{tabular}

(The strange channel names are to guarantee they are in alphabetical order,
to prevent reordering by OpenEXR. And also note that the simple
relationships between channels 1 \& 2, and 3--6, is only for the highest-
resolution level of the MIP-map, and will differ for the lower-res filtered
versions, and those differences is what gives us the slope momets that we
need.)

A reference for explaining how this can be used is here: \\
Christophe Hery, Michael Kass, and Junhi Ling. "Geometry into Shading."
Technical Memo 14-04, Pixar Animation Studios, 2014.
\url{https://graphics.pixar.com/library/BumpRoughness}
\apiend

\apiitem{--bumpformat {\rm \emph{bformat}}}
\index{bump mapping} \index{bump to roughness}
In conjunction with {\cf --bumpslopes}, this option can specify the strategy
for determining whether a 3-channel source image specifies a height map or a
normal map. The value \qkw{height} indicates it is a height map (only the
first channel will be used). The value \qkw{normal} indicates it is a normal
map (all three channels will be used for $x, y, z$). The default value,
\qkw{auto}, indicates that it should be interpreted as a height map if and
only if the R, G, B channel values are identical in all pixels, otherwise
it will be interpreted as a 3-channel normal map.
\apiend


% --shadow --shadcube
% --volshad --envcube --latl2envcube --vertcross
% --fov


\begin{comment}

\subsection{{\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}

\newpage
\section{\oiiotool}
\label{sec:oiiotooltex}

The \oiiotool utility (Chapter~\ref{chap:oiiotool}) is capable of writing
textures using the {\cf -otex} option, and lat-long environment maps using
the {\cf -oenv} option. Roughly speaking,

\medskip

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

\medskip

\noindent is equivalent to

\medskip

\hspace{0.25in} {\cf oiiotool} \emph{input} [\emph{oiiotool-options}] {\cf -otex} \emph{output}

\medskip

\noindent and

\medskip

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

\medskip

\noindent is equivalent to

\medskip

\hspace{0.25in} {\cf oiiotool} \emph{input} [\emph{oiiotool-options}] {\cf -oenv} \emph{output}

\medskip

\noindent However, the notation for the various options are not identical
between the two programs, as will be explained by the remainder of this
section.

The most important difference between \oiiotool and \maketx is that
\oiiotool can do so much more than convert an existing input image to a
texture -- literally any image creation or manipulation you can do via
\oiiotool may be output directly as a full texture file using {\cf -otex}
(or as a lat-long environment map using {\cf -oenv}).

Note that it is vitally important that you use one of the texture output
commands ({\cf -otex} or {\cf -oenv}) when creating textures with \oiiotool
--- if you inadvertently forget and use an ordinary {\cf -o}, you will end
up with an output image that is much less efficient to use as a texture.

\subsubsection*{Command line arguments useful when creating textures}

As with any use of \oiiotool, you may use the following to control the
run generally:

\apiitem{{--help \\
-v \\
--runstats \\
--threads} \emph{n}}
\apiend

\noindent and as with any use of \oiiotool, you may use the following
command-line options to control aspects of the any output files (including
those from {\cf -otex} and {\cf -oenv}, as well as {\cf -o}). Only brief
descriptions are given below, please consult Chapter~\ref{chap:oiiotool} for
detailed explanations.

\apiitem{{-d} {\rm \emph{datatype}}}
Specify the pixel data type ({\cf uint8}, {\cf uint16}, {\cf half}, {\cf float},
etc.) if you wish to override the default of writing the same data type as
the first input file read.
\apiend

\apiitem{{--tile} {\rm \emph{x}} {\rm \emph{y}}}
Explicitly override the tile size (though you are strongly urged to use
the default, and not use this command).
\apiend

\apiitem{{--compression} {\rm \emph{method}}}
Explicitly override the default compression methods when writing
the texture file.
\apiend

\apiitem{--ch {\rm \emph{channellist}}}
Shuffle, add, delete, or rename channels (see \ref{sec:oiiotool:ch}).
\apiend

\apiitem{--chnames {\rm \emph{a,b,...}}}
Renames the channels of the output image.
\apiend

\apiitem{--fixnan {\rm \emph{stretegy}}}
Repairs any pixels in the input image that contained {\cf NaN} or 
{\cf Inf} values (if the \emph{strategy} is {\cf box3} or {\cf black}),
or to simply abort with an error message (if the \emph{strategy} is {\cf error}).
\apiend

\apiitem{--fullpixels}
Resets the ``full'' (or ``display'') pixel range to be the ``data'' range.
\apiend

\apiitem{--planarconfig separate}
Forces ``separate'' (e.g., RRR...GGG...BBB) packing of channels in the
output texture.  This is almost always a bad choice, unless you know that
the texture file must be readable by PRMan, in which case it is required.
\apiend

\apiitem{--attrib {\rm \emph{name ~ value}}}
\oiiotool's {\cf --attrib} command may be used to set attributes
in the metadata of the output texture.
\apiend

\apiitem{--attrib:type=matrix worldtocam {\rm \emph{...16 comma-separated floats...}} \\
--attrib:type=matrix screentocam {\rm \emph{...16 comma-separated floats...}}}
Set/override the camera and screen matrices.
\apiend

\subsubsection*{Optional arguments to {\cf -otex} and {\cf -oenv}}

As with many \oiiotool commands, the {\cf -otex} and {\cf -oenv} may
have various optional arguments appended, in the form {\cf :name=value}
(see Section~\ref{sec:oiiotooloptionalargs}).

Optional arguments supported by {\cf -otex} and {\cf -oenv} include all
the same options as {\cf -o} (Section~\ref{sec:oiiotool:o}) and also the
following (explanations are brief, please consult Section~\ref{sec:maketx}
for more detailed explanations of each, for the corresponding \maketx
option):

\medskip

\noindent \begin{tabular}{p{2in} p{3in}}
Appended Option & \maketx equivalent \\ \hline
{\cf wrap=}\emph{string} & {\cf --wrap} \\
{\cf swrap=}\emph{string} & {\cf --swrap} \\
{\cf twrap=}\emph{string} & {\cf --twrap} \\[.5ex]
{\cf resize=1} & {\cf --resize} \\
{\cf nomipmap=1} & {\cf --nomipmap} \\
{\cf updatemode=1} & {\cf -u} \\
{\cf monochrome_detect=1} & {\cf --monochrome-detect} \\
{\cf opaque_detect=1} & {\cf --opaque-detect} \\
{\cf unpremult=1} & {\cf --unpremult} \\
{\cf incolorspace=}\emph{name} & {\cf --incolorspace} \\
{\cf outcolorspace=}\emph{name} & {\cf --outcolorspace} \\
{\cf hilightcomp=1} & {\cf --hicomp} \\
{\cf sharpen=}\emph{float} & {\cf --sharpen} \\
{\cf filter=}\emph{string} & {\cf --filter} \\
%{\cf oiio_options=1} &  {\cf --oiio} \\
{\cf prman_metadata=1} & {\cf --prman} \\
{\cf prman_options=1} & {\cf --prman-metadata} \\
\end{tabular}


\subsubsection*{Examples}

\begin{code}
oiiotool in.tif -otex out.tx

oiiotool in.jpg --colorconvert sRGB linear -d uint16 -otex out.tx

oiiotool --pattern:checker 512x512 3 -d uint8 -otex:wrap=periodic checker.tx

oiiotool in.exr -otex:hilightcomp=1:sharpen=0.5 out.exr
\end{code}


