1.. _chap-maketx:
2
3Making Tiled MIP-Map Texture Files With `maketx` or `oiiotool`
4##############################################################
5
6
7Overview
8========
9
10The TextureSystem (Chapter :ref:`chap-texturesystem_`) will exhibit much
11higher performance if the image files it uses as textures are tiled (versus
12scanline) orientation, have multiple subimages at different resolutions
13(MIP-mapped), and include a variety of header or metadata fields
14appropriately set for texture maps. Any image that you intend to use as
15input to TextureSystem, therefore, should first be converted to have these
16properties. An ordinary image will work as a texture, but without this
17additional step, it will be drastically less efficient in terms of memory,
18disk or network I/O, and time.
19
20This can be accomplished programmatically using the ImageBufAlgo
21`make_texture()` function (see Section :ref:`sec-iba-importexport` for C++
22and Section :ref:`sec-iba-py-importexport` for Python).
23
24OpenImageIO includes two command-line utilities capable of converting
25ordinary images into texture files: :program:`maketx` and
26:program:`oiiotool`. [#]_
27
28.. [#] Why are there two programs? Historical artifact -- :program:`maketx`
29       existed first, and much later :program:`oiiotool` was extended to be
30       capable of directly writing texture files. If you are simply
31       converting an image into a texture, :program:`maketx` is more
32       straightforward and foolproof, in that you can't accidentally forget
33       to turn it into a texture, as you might do with and much later
34       :program:`oiiotool` was extended to be capable of directly writing
35       texture files.
36
37
38
39.. sec-maketx:
40
41`maketx`
42========
43
44The :program:`maketx` program will convert ordinary images to efficient
45textures. The :program:`maketx` utility is invoked as follows:
46
47    ``maketx`` [*options*] *input*... ``-o`` *output*
48
49
50Where *input* and *output* name the input image and desired output filename.
51The input files may be of any image format recognized by OpenImageIO (i.e.,
52for which ImageInput plugins are available).  The file format of the output
53image will be inferred from the file extension of the output filename (e.g.,
54:filename:`foo.tif` will write a TIFF file).
55
56Command-line arguments are:
57
58.. option:: --help
59
60    Prints usage information to the terminal.
61
62.. option:: -v
63
64    Verbose status messages, including runtime statistics and timing.
65
66.. option:: --runstats
67
68    Print runtime statistics and timing.
69
70.. option:: -o outputname
71
72    Sets the name of the output texture.
73
74.. option:: --threads <n>
75
76    Use *n* execution threads if it helps to speed up image operations. The
77    default (also if n=0) is to use as many threads as there are cores
78    present in the hardware.
79
80.. option:: --format <formatname>
81
82    Specifies the image format of the output file (e.g., "tiff", "OpenEXR",
83    etc.).  If `--format` is not used, :program:`maketx` will guess based on
84    the file extension of the output filename; if it is not a recognized
85    format extension, TIFF will be used by default.
86
87.. option:: -d <datatype>
88
89    Attempt to sets the output pixel data type to one of: `UINT8`, `sint8`,
90    `uint16`, `sint16`, `half`, `float`, `double`.
91
92    If the `-d` option is not supplied, the output data type will be the
93    same as the data format of the input file.
94
95    In either case, the output file format itself (implied by the file
96    extension of the output filename) may trump the request if the file
97    format simply does not support the requested data type.
98
99.. option:: --tile <x> <y>
100
101    Specifies the tile size of the output texture.  If not specified,
102    :program:`maketx` will make 64 x 64 tiles.
103
104.. option:: --separate
105
106    Forces "separate" (e.g., RRR...GGG...BBB) packing of channels in the
107    output file.  Without this option specified, "contiguous" (e.g.,
108    RGBRGBRGB...) packing of channels will be used for those file formats
109    that support it.
110
111.. option:: --compression <method>
112            --compression <method:quality>
113
114    Sets the compression method, and optionally a quality setting, for the
115    output image (the default is to try to use "zip" compression, if it is
116    available).
117
118.. option:: -u
119
120    Ordinarily, textures are created unconditionally (which could take
121    several seconds for large input files if read over a network) and will
122    be stamped with the current time.
123
124    The `-u` option enables *update mode*: if the output file already
125    exists, and has the same time stamp as the input file, and the
126    command-lie arguments that created it are identical to the current ones,
127    then the texture will be left alone and not be recreated. If the output
128    file does not exist, or has a different time stamp than the input file,
129    or was created using different command line arguments, then the texture
130    will be created and given the time stamp of the input file.
131
132.. option:: --wrap <wrapmode>
133            --swrap <wrapmode>, --twrap <wrapmode>
134
135    Sets the default *wrap mode* for the texture, which determines the
136    behavior when the texture is sampled outside the [0,1] range. Valid wrap
137    modes are: `black`, `clamp`, `periodic`, `mirror`.  The default, if none
138    is set, is `black`.  The `--wrap` option sets the wrap mode in both
139    directions simultaneously, while the `--swrap` and `--twrap` may be used
140    to set them individually in the *s* (horizontal) and *t* (vertical)
141    diretions.
142
143    Although this sets the default wrap mode for a texture, note that the
144    wrap mode may have an override specified in the texture lookup at
145    runtime.
146
147.. option:: --resize
148
149    Causes the highest-resolution level of the MIP-map to be a power-of-two
150    resolution in each dimension (by rounding up the resolution of the input
151    image).  There is no good reason to do this for the sake of OIIO's
152    texture system, but some users may require it in order to create MIP-map
153    images that are compatible with both OIIO and other texturing systems
154    that require power-of-2 textures.
155
156.. option:: --filter <name>
157
158    By default, the resizing step that generates successive MIP levels uses
159    a triangle filter to bilinearly combine pixels (for MIP levels with even
160    number of pixels, this is also equivalent to a box filter, which merely
161    averages groups of 4 adjacent pixels).  This is fast, but for source
162    images with high frequency content, can result in aliasing or other
163    artifacts in the lower-resolution MIP levels.
164
165    The `--filter` option selects a high-quality filter to use when resizing
166    to generate successive MIP levels.  Choices include `lanczos3` (our best
167    recommendation for highest-quality filtering, a 3-lobe Lanczos filter),
168    `box`, `triangle`, `catrom`, `blackman-harris`, `gaussian`, `mitchell`,
169    `bspline`, `cubic`, `keys`, `simon`, `rifman`, `radial-lanczos3`,
170    `disk`, `sinc`.
171
172    If you select a filter with negative lobes (including `lanczos3`,
173    `sinc`, `lanczos3`, `keys`, `simon`, `rifman`, or `catrom`), and your
174    source image is an HDR image with very high contrast regions that
175    include pixels with values >1, you may also wish to use the
176    `--rangecompress` option to avoid ringing artifacts.
177
178.. option:: --hicomp
179
180    Perform highlight compensation.  When HDR input data with high-contrast
181    highlights is turned into a MIP-mapped texture using a high-quality
182    filter with negative lobes (such as `lanczos3`), objectionable ringing
183    could appear near very high-contrast regions with pixel values >1. This
184    option improves those areas by using range compression (transforming
185    values from a linear to a logarithmic scale that greatly compresses the
186    values > 1) prior to each image filtered-resize step, and then expanded
187    back to a linear format after the resize, and also clamping resulting
188    pixel values to be non-negative.  This can result in some loss of
189    energy, but often this is a preferable alternative to ringing artifacts
190    in your upper MIP levels.
191
192.. option:: --sharpen <contrast>
193
194    EXPERIMENTAL: USE AT YOUR OWN RISK!
195
196    This option will run an additional sharpening filter when creating the
197    successive MIP-map levels. It uses an unsharp mask (much like in Section
198    :ref:`sec-iba-unsharpmask`) to emphasize high-frequency details to make
199    features "pop" visually even at high MIP-map levels. The *contrast*
200    controls the degree to which it does this. Probably a good value to
201    enhance detail but not go overboard is 0.5 or even 0.25. A value of 1.0
202    may make strage artifacts at high MIP-map levels. Also, if you
203    simultaneously use `--filter unsharp-median`, a slightly different
204    variant of unsharp masking will be used that employs a median filter to
205    separate out the low-frequencies, this may tend to help emphasize small
206    features while not over-emphasizing large edges.
207
208.. option:: --nomipmap
209
210    Causes the output to *not* be MIP-mapped, i.e., only will have the
211    highest-resolution level.
212
213.. option:: --nchannels <n>
214
215    Sets the number of output channels.  If *n* is less than the number of
216    channels in the input image, the extra channels will simply be ignored.
217    If *n* is greater than the number of channels in the input image, the
218    additional channels will be filled with 0 values.
219
220.. option:: --chnames a,b,...
221
222    Renames the channels of the output image.  All the channel names are
223    concatenated together, separated by commas.  A "blank" entry will cause
224    the channel to retain its previous value (for example, `--chnames ,,,A`
225    will rename channel 3 to be "A" and leave channels 0-2 as they were.
226
227.. option:: --checknan
228
229    Checks every pixel of the input image to ensure that no `NaN` or `Inf`
230    values are present.  If such non-finite pixel values are found, an error
231    message will be printed and `maketx` will terminate without writing the
232    output image (returning an error code).
233
234.. option:: --fixnan streategy
235
236    Repairs any pixels in the input image that contained `NaN` or `Inf`
237    values (hereafter referred to collectively as "nonfinite"). If
238    *strategy* is `black`, nonfinite values will be replaced with 0.  If
239    *strategy* is `box3`, nonfinite values will be replaced by the average
240    of all the finite values within a 3x3 region surrounding the pixel.
241
242.. option:: --fullpixels
243
244    Resets the "full" (or "display") pixel range to be the "data" range.
245    This is used to deal with input images that appear, in their headers, to
246    be crop windows or overscanned images, but you want to treat them as
247    full 0--1 range images over just their defined pixel data.
248
249.. option:: --Mcamera <...16 floats...>
250            --Mscreen <...16 floats...>
251
252    Sets the camera and screen matrices (sometimes called `Nl` and `NP`,
253    respectively, by some renderers) in the texture file, overriding any
254    such matrices that may be in the input image (and would ordinarily be
255    copied to the output texture).
256
257.. option:: --prman-metadata
258
259    Causes metadata "PixarTextureFormat" to be set, which is useful if you
260    intend to create an OpenEXR texture or environment map that can be used
261    with PRMan as well as OIIO.
262
263.. option:: --attrib <name> <value>
264
265    Adds or replaces metadata with the given *name* to have the
266    specified *value*.
267
268    It will try to infer the type of the metadata from the value: if the
269    value contains only numerals (with optional leading minus sign), it will
270    be saved as `int` metadata; if it also contains a decimal point, it
271    will be saved as `float` metadata; otherwise, it will be saved as
272    a `string` metadata.
273
274    For example, you could explicitly set the IPTC location metadata fields
275    with::
276
277        oiiotool --attrib "IPTC:City" "Berkeley" in.jpg out.jpg
278
279
280.. option:: --sattrib <name> <value>
281
282    Adds or replaces metadata with the given *name* to have the specified
283    *value*, forcing it to be interpreted as a `string`. This is helpful if
284    you want to set a `string` metadata to a value that the `--attrib`
285    command would normally interpret as a number.
286
287.. option:: --sansattrib
288
289    When set, this edits the command line inserted in the "Software" and
290    "ImageHistory" metadata to omit any verbose `--attrib` and `--sattrib`
291    commands.
292
293.. option:: --constant-color-detect
294
295    Detects images in which all pixels are identical, and outputs the
296    texture at a reduced resolution equal to the tile size, rather than
297    filling endless tiles with the same constant color.  That is, by
298    substituting a low-res texture for a high-res texture if it's a constant
299    color, you could save a lot of save disk space, I/O, and texture cache
300    size. It also sets the `"ImageDescription"` to contain a special message
301    of the form `ConstantColor=[r,g,...]`.
302
303.. option:: --monochrome-detect
304
305    Detects multi-channel images in which all color components are
306    identical, and outputs the texture as a single-channel image instead.
307    That is, it changes RGB images that are gray into single-channel gray
308    scale images.
309
310.. option:: --opaque-detect
311
312    Detects images that have a designated alpha channel for which the alpha
313    value for all pixels is 1.0 (fully opaque), and omits the alpha channel
314    from the output texture.  So, for example, an RGBA input texture where
315    A=1 for all pixels will be output just as RGB.  The purpose is to save
316    disk space, texture I/O bandwidth, and texturing time for those textures
317    where alpha was present in the input, but clearly not necessary.
318
319.. option:: --ignore-unassoc
320
321    Ignore any header tags in the input images that indicate that the input
322    has "unassociated" alpha.  When this option is used, color channels with
323    unassociated alpha will not be automatically multiplied by alpha to turn
324    them into associated alpha. This is also a good way to fix input images
325    that really are associated alpha, but whose headers incorrectly indicate
326    that they are unassociated alpha.
327
328.. option:: --prman
329
330    PRMan is will crash in strange ways if given textures that don't have
331    its quirky set of tile sizes and other specific metadata.  If you want
332    :program:`maketx` to generate textures that may be used with either
333    OpenImageIO or PRMan, you should use the `--prman` option, which will
334    set several options to make PRMan happy, overriding any contradictory
335    settings on the command line or in the input texture.
336
337    Specifically, this option sets the tile size (to 64x64 for 8 bit, 64x32
338    for 16 bit integer, and 32x32 for float or `half` images), uses
339    "separate" planar configuration (`--separate`), and sets PRMan-specific
340    metadata (`--prman-metadata`).  It also outputs sint16 textures if
341    uint16 is requested (because PRMan for some reason does not accept true
342    uint16 textures), and in the case of TIFF files will omit the Exif
343    directory block which will not be recognized by the older version of
344    libtiff used by PRMan.
345
346    OpenImageIO will happily accept textures that conform to PRMan's
347    expectations, but not vice versa.  But OpenImageIO's TextureSystem has
348    better performance with textures that use :program:`maketx`'s default
349    settings rather than these oddball choices.  You have been warned!
350
351.. option:: --oiio
352
353    This sets several options that we have determined are the optimal values
354    for OpenImageIO's TextureSystem, overriding any contradictory settings
355    on the command line or in the input texture.
356
357    Specifically, this is the equivalent to using
358
359        `--separate --tile 64 64`
360
361.. option:: --colorconvert <inspace> <outspace>
362
363    Convert the color space of the input image from *inspace* to *tospace*.
364    If OpenColorIO is installed and finds a valid configuration, it will be
365    used for the color conversion.  If OCIO is not enabled (or cannot find a
366    valid configuration, OIIO will at least be able to convert among linear,
367    sRGB, and Rec709.
368
369.. option:: --colorconfig <name>
370
371    Explicitly specify a custom OpenColorIO configuration file. Without this,
372    the default is to use the `$OCIO` environment variable as a guide for
373    the location of the OpenColorIO configuration file.
374
375.. option:: --unpremult
376
377    When undergoing some color conversions, it is helpful to
378    "un-premultiply" the alpha before converting color channels, and then
379    re-multiplying by alpha.  Caveat emptor -- if you don't know exactly
380    when to use this, you probably shouldn't be using it at all.
381
382
383.. option:: --mipimage <filename>
384
385    Specifies the name of an image file to use as a custom MIP-map level,
386    instead of simply downsizing the last one.  This option may be used
387    multiple times to specify multiple levels.  For example::
388
389        maketx 256.tif --mipimage 128.tif --mipimage 64.tif -o out.tx
390
391    This will make a texture with the first MIP level taken from `256.tif`,
392    the second level from `128.tif`, the third from `64.tif`, and then
393    subsequent levels will be the usual downsizings of `64.tif`.
394
395.. option:: --envlatl
396
397    Creates a latitude-longitude environment map, rather than an ordinary
398    texture map.
399
400.. option:: --lightprobe
401
402    Creates a latitude-longitude environment map, but in contrast to
403    `--envlatl`, the original input image is assumed to be formatted as a
404    *light probe* image. (See http://www.pauldebevec.com/Probes/ for
405    examples and an explanation of the geometric layout.)
406
407.. option:: --bumpslopes
408
409    For a single channel input image representing height (that you would
410    ordinarily use for a bump or displacement), this produces a 6-channel
411    texture that contains the first and second moments of bump slope, which
412    can be used to implement certain bump-to-roughness techniques.
413    The channel layout is as follows:
414
415    +------+--------------+-------------------------------------------------------------------+
416    |index | channel name | data at MIP level 0                                               |
417    +------+--------------+-------------------------------------------------------------------+
418    |0     | `b0_h`       | :math:`h`  (height)                                               |
419    +------+--------------+-------------------------------------------------------------------+
420    |1     | `b1_dhds`    | :math:`\partial h / \partial s`                                   |
421    +------+--------------+-------------------------------------------------------------------+
422    |2     | `b2_dhdt`    | :math:`\partial h / \partial t`                                   |
423    +------+--------------+-------------------------------------------------------------------+
424    |3     | `b3_dhds2`   | :math:`(\partial h / \partial s)^2`                               |
425    +------+--------------+-------------------------------------------------------------------+
426    |4     | `b4_dhdt2`   | :math:`(\partial h / \partial t)^2`                               |
427    +------+--------------+-------------------------------------------------------------------+
428    |5     | `b5_dhdsdt`  | :math:`(\partial h / \partial s) \cdot (\partial h / \partial t)` |
429    +------+--------------+-------------------------------------------------------------------+
430
431    (The strange channel names are to guarantee they are in alphabetical
432    order, to prevent reordering by OpenEXR. And also note that the simple
433    relationships between channels 1 & 2, and 3-6, is only for the highest-
434    resolution level of the MIP-map, and will differ for the lower-res
435    filtered versions, and those differences is what gives us the slope
436    momets that we need.)
437
438    A reference for explaining how this can be used is here:
439
440    Christophe Hery, Michael Kass, and Junhi Ling. "Geometry into Shading."
441    Technical Memo 14-04, Pixar Animation Studios, 2014.
442    https://graphics.pixar.com/library/BumpRoughness
443
444.. option:: --bumpformat <bformat>
445
446    In conjunction with `--bumpslopes`, this option can specify the strategy
447    for determining whether a 3-channel source image specifies a height map
448    or a normal map. The value "height" indicates it is a height map (only
449    the first channel will be used). The value "normal" indicates it is a
450    normal map (all three channels will be used for x, y, z). The default
451    value, "auto", indicates that it should be interpreted as a height map
452    if and only if the R, G, B channel values are identical in all pixels,
453    otherwise it will be interpreted as a 3-channel normal map.
454
455
456
457
458.. sec-oiiotooltex:
459
460`oiiotool`
461=========
462
463The :program:`oiiotool` utility (Chapter :ref:`chap-oiiotool`) is capable of
464writing textures using the `-otex` option, and lat-long environment maps
465using the `-oenv` option. Roughly speaking,
466
467    `maketx` [*maketx-options*] *input* `-o` *output*
468
469is equivalent to
470
471    `oiiotool` *input* [*oiiotool-options*] `-otex` *output*
472
473and
474
475    `maketx -envlatl` [*maketx-options*] *input* `-o` *output*
476
477is equivalent to
478
479    `oiiotool` *input* [*oiiotool-options*] `-oenv` *output*
480
481However, the notation for the various options are not identical between the
482two programs, as will be explained by the remainder of this section.
483
484The most important difference between :program:`oiiotool` and
485:program:`maketx` is that :program:`oiiotool` can do so much more than
486convert an existing input image to a texture -- literally any image
487creation or manipulation you can do via :program:`oiiotool` may be output
488directly as a full texture file using `-otex` (or as a lat-long environment
489map using `-oenv`).
490
491Note that it is vitally important that you use one of the texture output
492commands (`-otex` or `-oenv`) when creating textures with :program:`oiiotool`
493--- if you inadvertently forget and use an ordinary `-o`, you will end
494up with an output image that is much less efficient to use as a texture.
495
496Command line arguments useful when creating textures
497----------------------------------------------------
498
499As with any use of :program:`oiiotool`, you may use the following to control the
500run generally:
501
502.. option:: --help
503            -v
504            --runstats
505            --threads <n>
506
507    and as with any use of :program:`oiiotool`, you may use the following
508    command-line options to control aspects of the any output files
509    (including those from `-otex` and `-oenv`, as well as `-o`). Only brief
510    descriptions are given below, please consult Chapter :ref:`oiiotool` for
511    detailed explanations.
512
513.. option:: -d <datatype>
514
515    Specify the pixel data type (`UINT8`, `uint16`, `half`, `float`, etc.)
516    if you wish to override the default of writing the same data type as the
517    first input file read.
518
519.. option:: --tile <x> <y>
520
521    Explicitly override the tile size (though you are strongly urged to use
522    the default, and not use this command).
523
524.. option:: --compression <method>
525
526    Explicitly override the default compression methods when writing the
527    texture file.
528
529.. option:: --ch <channellist>
530
531    Shuffle, add, delete, or rename channels (see :ref:`sec-oiiotool-ch`).
532
533.. option:: --chnames a,b,...
534
535    Renames the channels of the output image.
536
537.. option:: --fixnan <stretegy>
538
539    Repairs any pixels in the input image that contained `NaN` or `Inf`
540    values (if the *strategy* is `box3` or `black`), or to simply abort with
541    an error message (if the *strategy* is `error`).
542
543.. option:: --fullpixels
544
545    Resets the "full" (or "display") pixel range to be the "data" range.
546
547.. option:: --planarconfig separate
548
549    Forces "separate" (e.g., RRR...GGG...BBB) packing of channels in the
550    output texture.  This is almost always a bad choice, unless you know
551    that the texture file must be readable by PRMan, in which case it is
552    required.
553
554.. option:: --attrib <name> <value>
555
556    :program:`oiiotool`'s `--attrib` command may be used to set attributes
557    in the metadata of the output texture.
558
559.. option:: --attrib:type=matrix worldtocam <...16 comma-separated floats...>
560            --attrib:type=matrix screentocam <...16 comma-separated floats...>
561
562    Set/override the camera and screen matrices.
563
564
565Optional arguments to `-otex` and `-oenv`
566-----------------------------------------
567
568As with many :program:`oiiotool` commands, the `-otex` and `-oenv` may
569have various optional arguments appended, in the form `:name=value`
570(see Section :ref:`sec-oiiotooloptionalargs`).
571
572Optional arguments supported by `-otex` and `-oenv` include all the same
573options as `-o` (Section :ref:`sec-oiiotool-o`) and also the following
574(explanations are brief, please consult Section :ref:`sec-maketx` for more
575detailed explanations of each, for the corresponding :program:`maketx`
576option):
577
578
579=======================   ============================================
580Appended Option           `maketx` equivalent
581=======================   ============================================
582`wrap=` *string*          `--wrap`
583`swrap=` *string*         `--swrap`
584`twrap=` *string*         `--twrap`
585`resize=1`                `--resize`
586`nomipmap=1`              `--nomipmap`
587`updatemode=1`            `-u`
588`monochrome_detect=1`     `--monochrome-detect`
589`opaque_detect=1`         `--opaque-detect`
590`unpremult=1`             `--unpremult`
591`incolorspace=` *name*    `--incolorspace`
592`outcolorspace=` *name*   `--outcolorspace`
593`hilightcomp=1`           `--hicomp`
594`sharpen=` *float*        `--sharpen`
595`filter=` *string*        `--filter`
596`prman_metadata=1`        `--prman`
597`prman_options=1`         `--prman-metadata`
598=======================   ============================================
599
600
601Examples
602--------
603
604.. code-block::
605
606    oiiotool in.tif -otex out.tx
607
608    oiiotool in.jpg --colorconvert sRGB linear -d uint16 -otex out.tx
609
610    oiiotool --pattern:checker 512x512 3 -d uint8 -otex:wrap=periodic checker.tx
611
612    oiiotool in.exr -otex:hilightcomp=1:sharpen=0.5 out.exr
613
614
615
616