toktx(1)

πŸ“¦ version 4.4.2, in nixos 26.05, nixpkgs unstable

πŸ’– toktx πŸ’– β€” Create a KTX file from JPEG, PNG or netpbm format files

okay bestie, this is toktx, and we're reading straight out of the KTX Tools Reference manual (section 1, so you know it's official ✨). She's the one who takes your JPEGs, PNGs and netpbm girlies and turns them into a Khronos format texture file (KTX). Buckle up, there's a lot and honestly? all of it slaps. πŸŽ€


πŸ“œ SYNOPSIS

toktx [options] outfile [infile.{jpg,png,pam,pgm,ppm} ...]

🌸 DESCRIPTION

So the whole gig: create a Khronos format texture file (KTX) from a set of JPEG (.jpg), PNG (.png) or Netpbm format (.pam, .pgm, .ppm) images. She writes the destination ktx file to outfile, creating parent directories for you and appending ".ktx{,2}" if necessary. And if outfile is -? The output goes to stdout. Obsessed. πŸ’…

toktx reads each named infile, which must be in .jpg, .png, .pam, .ppm or .pgm format. Now this part is iconic: infiles prefixed with '@' get read as text files listing actual file names to process, with one file path per line. Those paths must be absolute or relative to the current directory when toktx is run. But if you use '@@' instead, the paths must be absolute or relative to the location of the list file. Sneaky and useful. Also: file paths must be encoded in UTF-8. No cap. πŸ¦‹

The target texture type (that's the number of components in the output texture) is chosen via --target_type. Swizzling of the components of the input file is specified with --input_swizzle, and swizzle metadata can be specified with --swizzle. πŸ’«

The defaults live in a table, and they're based on the components of the input file plus whether the target texture format is uncompressed or block-compressed (including the universal formats). Input components get arbitrarily labeled r, g, b & a. The manpage's table got a lil smooshed in the rendering, so here it is laid out properly for you 🫢:

Uncompressed formats

  • input components 1 (greyscale) β†’ target type R, input swizzle -, swizzle rrr1
  • input components 2 (greyscale alpha) β†’ target type RG, input swizzle -, swizzle rrrg
  • input components 3 β†’ target type RGB, input swizzle -, swizzle -
  • input components 4 β†’ target type RGBA, input swizzle -, swizzle -

Block-compressed formats

  • input components 1 β†’ target type RGB, input swizzle rrr1, swizzle -
  • input components 2 β†’ target type RGBA, input swizzle rrrg, swizzle -
  • input components 3 β†’ target type RGB, input swizzle -, swizzle -
  • input components 4 β†’ target type RGBA, input swizzle -, swizzle -

As you can see from that table (iconic of her honestly), one- and two-component inputs are treated as luminance{,-alpha} in accordance with the JPEG and PNG specifications. And for consistency, Netpbm inputs are handled the same way. πŸ’–

Using R & RG types for uncompressed formats saves space, but heads up: the sRGB versions of these formats are not widely supported, so a warning will be issued prompting you to convert the input to linear. Don't say she didn't warn you. πŸ™ˆ


🎨 the color / OETF situation (iykyk)

The primaries, transfer function (OETF) and the texture's sRGB-ness are set based on the input file β€” unless --assign_oetf linear or --assign_oetf srgb is specified.

  • For .jpg files, toktx always sets BT709/sRGB primaries and the sRGB OETF in the output file, and creates sRGB format textures.
  • Netpbm files always use BT.709/sRGB primaries and the BT.709 OETF. toktx transforms these images to the sRGB OETF, sets BT709/sRGB primaries and the sRGB OETF in the output file, and creates sRGB format textures.

For .png files, the OETF is set as follows:

No color-info chunks or sRGB chunk present:

  • primaries are set to BT.709 and OETF to sRGB.

sRGB chunk present:

  • primaries are set to BT.709 and OETF to sRGB. gAMA and cHRM chunks are ignored.

iCCP chunk present:

  • General ICC profiles are not yet supported by toktx or the KTX2 format. In future these images may be transformed to linear or sRGB OETF as appropriate for the profile. sRGB chunk must not be present.

gAMA and/or cHRM chunks present without sRGB or iCCP:

  • If gAMA is < 60000 the image is transformed to and the OETF is set to sRGB. Otherwise the image is transformed to and the OETF is set to linear. The color primaries in cHRM are matched to one of the standard sets listed in the Khronos Data Format Specification (the KHR_DF_PRIMARIES values from khr_df.h) and the primaries field of the output file's DFD is set to the matched value. If no match is found the primaries field is set to UNSPECIFIED.

✨ OPTIONS ✨ β€” the ones that are always available

bestie these are the always-on-the-menu options, so let's go through every single one πŸ’…
  • --2d β€” if the image height is 1, by default a KTX file for a 1D texture is created. With this option, one for a 2D texture is created instead.
  • --automipmap β€” causes the KTX file to be marked to request generation of a mipmap pyramid when the file is loaded. This option is mutually exclusive with --genmipmap, --levels and --mipmap.
  • --cubemap β€” the KTX file is for a cubemap. At least 6 infiles must be provided, more if --mipmap or --layers is also specified. Provide the images in the order +X, -X, +Y, -Y, +Z, -Z, where the arrangement is a left-handed coordinate system with +Y up. So if you're facing +Z, -X will be on your left and +X on your right. If --layers > 1 is specified, provide the faces for layer 0 first then for layer 1, etc. Images must have an upper left origin so --lower_left_maps_to_s0t0 is ignored with this option. 🧊
  • --depth <number> β€” the KTX file is for a 3D texture with a depth of number where number > 0. Provide the file(s) for z=0 first then those for z=1, etc. It is an error to specify this together with --layers or --cubemap.
  • --genmipmap β€” causes mipmaps to be generated for each input file. This option is mutually exclusive with --automipmap and --mipmap. When set, the following mipmap-generation related options become valid, otherwise they are ignored. πŸ‘‘
    • --filter <name> β€” specifies the filter to use when generating the mipmaps. name is a string. The default is lanczos4. The following names are recognized: box, tent, bell, b-spline, mitchell, lanczos3, lanczos4, lanczos6, lanczos12, blackman, kaiser, gaussian, catmullrom, quadratic_interp, quadratic_approx and quadratic_mix.
    • --fscale <floatVal> β€” the filter scale to use. The default is 1.0.
    • --wmode <mode> β€” specify how to sample pixels near the image boundaries. Values are wrap, reflect and clamp. The default is clamp.
  • --layers <number> β€” the KTX file is for an array texture with number of layers where number > 0. Provide the file(s) for layer 0 first then those for layer 1, etc. It is an error to specify this together with --depth. 🍰
  • --levels <number> β€” the KTX file is for a mipmap pyramid with number of levels rather than a full pyramid. number must be > 1 and <= the maximum number of levels determined from the size of the base level image. Provide the base level image first, if using --mipmap. This option is mutually exclusive with --automipmap.
  • --mipmap β€” the KTX file is for a mipmap pyramid with one infile being explicitly provided for each level. Provide the images in the order of layer then face or depth slice then level, with the base-level image first then in order down to the 1x1 image or the level specified by --levels.
Note β€” this ordering differs from that in the created texture as it is felt to be more user-friendly. (she's thinking of you 🫢)

This option is mutually exclusive with --automipmap and --genmipmap.

  • --nometadata β€” do not write KTXorientation metadata into the output file. Metadata is written by default. Use of this option is not recommended. ⚠️
  • --nowarn β€” silence warnings which are issued when certain transformations are performed on input images. 🀫
  • --upper_left_maps_to_s0t0 β€” map the logical upper left corner of the image to s0,t0. Although opposite to the OpenGL convention, this is the DEFAULT BEHAVIOUR. netpbm and PNG files have an upper left origin so this option does not flip the input images. When this option is in effect, toktx writes a KTXorientation value of S=r,T=d into the output file to inform loaders of the logical orientation. If an OpenGL {,ES} loader ignores the orientation value, the image will appear upside down. 😭
  • --lower_left_maps_to_s0t0 β€” map the logical lower left corner of the image to s0,t0. This causes the input netpbm and PNG images to be flipped vertically to a lower-left origin. When this option is in effect, toktx writes a KTXorientation value of S=r,T=u into the output file to inform loaders of the logical orientation. If a Vulkan loader ignores the orientation value, the image will appear upside down. This option is ignored with --cubemap. πŸ™ƒ
  • --assign_oetf <linear|srgb> β€” force the created texture to have the specified transfer function. If this is specified, implicit or explicit color space information from the input file(s) will be ignored and no color transformation will be performed. USE WITH CAUTION β€” preferably only when you know the file format information is wrong. 🚨
  • --assign_primaries <bt709|none|srgb> β€” force the created texture to have the specified primaries. If this is specified, implicit or explicit color space information from the input file(s) will be ignored and no color transformation will be performed. USE WITH CAUTION β€” preferably only when you know the file format information is wrong. 🚨
  • --convert_oetf <linear|srgb> β€” convert the input images to the specified transfer function, if the current transfer function is different. If both this and --assign_oetf are specified, conversion will be performed from the assigned transfer function to the transfer function specified by this option, if different. 🌈
  • --convert_primaries <primaries> β€” convert the image images to the specified color primaries, if different from the color primaries of the input file(s) or the one specified by --assign-primaries. If both this and --assign-primaries are specified, conversion will be performed from the assigned primaries to the primaries specified by this option, if different. This option is not allowed to be specified when --assign-primaries is set to 'none'. Case insensitive. Possible options are: bt709 | srgb | bt601-ebu | bt601-smpte | bt2020 | ciexyz | aces | acescc | ntsc1953 | pal525 | displayp3 | adobergb. 🌸
  • --linear β€” Deprecated. Use --assign_oetf linear. πŸ’€
  • --srgb β€” Deprecated. Use --assign_oetf srgb. πŸ’€
  • --resize <width>x<height> β€” resize images to width X height. This should not be used with --mipmap as it would resize all the images to the same size. Resampler options can be set via --filter and --fscale. πŸ“
  • --scale <value> β€” scale images by value as they are read. Resampler options can be set via --filter and --fscale. πŸ“
  • --swizzle <swizzle> β€” add swizzle metadata to the file being created. swizzle has the same syntax as the parameter for --input_swizzle. Not recommended for use with block-cmpressed textures, including Basis Universal formats, because something like rabb may yield drastically different error metrics if done after compression. πŸ™ˆ
  • --target_type <type> β€” specify the number of components in the created texture. type is one of the following strings: R, RG, RGB or RGBA. Excess input components will be dropped. Output components with no mapping from the input will be set to 0 or, if the alpha component, 1.0. 🎯
  • --t2 β€” output in KTX2 format. Default is KTX. ⭐
  • --encode <astc | etc1s | uastc> β€” this is the big β€œpick your compression vibe” switch, bestie. It compresses the image data into ASTC, transcodable ETC1S / BasisLZ, or high-quality transcodable UASTC format. It implies --t2. Each encoding choice unlocks its own little crew of encoder-specific options below β€” use them with a different encoder and they’re just ignored, no cap.

astc: high-quality ASTC format ✨

Create a texture in high-quality ASTC format. Iconic.

  • --astc_blk_d <XxY | XxYxZ> β€” tells the compressor which block dimension to use for the textures. Like --astc_blk_d 6x5 for 2D or --astc_blk_d 6x6x6 for 3D. 6x6 is the default for 2D. The supported 2D block dimensions are:
    • 4x4 β€” 8.00 bpp
    • 5x4 β€” 6.40 bpp
    • 5x5 β€” 5.12 bpp
    • 6x5 β€” 4.27 bpp
    • 6x6 β€” 3.56 bpp
    • 8x5 β€” 3.20 bpp
    • 8x6 β€” 2.67 bpp
    • 10x5 β€” 2.56 bpp
    • 10x6 β€” 2.13 bpp
    • 8x8 β€” 2.00 bpp
    • 10x8 β€” 1.60 bpp
    • 10x10 β€” 1.28 bpp
    • 12x10 β€” 1.07 bpp
    • 12x12 β€” 0.89 bpp

The supported 3D block dimensions are:

  • 3x3x3 β€” 4.74 bpp
  • 4x3x3 β€” 3.56 bpp
  • 4x4x3 β€” 2.67 bpp
  • 4x4x4 β€” 2.00 bpp
  • 5x4x4 β€” 1.60 bpp
  • 5x5x4 β€” 1.28 bpp
  • 5x5x5 β€” 1.02 bpp
  • 6x5x5 β€” 0.85 bpp
  • 6x6x5 β€” 0.71 bpp
  • 6x6x6 β€” 0.59 bpp
  • --astc_mode <ldr | hdr> β€” picks the encoding mode. LDR is the default unless the input image is 16-bit, in which case the default is HDR. Slay.
  • --astc_quality <level> β€” this is the quality-performance tradeoff knob. More complete searches of the search space improve image quality at the expense of compression time. Default is medium. You can set it between fastest (0) and exhaustive (100) using these fixed quality presets:
    • fastest β€” equivalent to quality = 0
    • fast β€” equivalent to quality = 10
    • medium β€” equivalent to quality = 60
    • thorough β€” equivalent to quality = 98
    • exhaustive β€” equivalent to quality = 100
  • --astc_perceptual β€” tells the codec to optimize for perceptual error instead of direct RMS error. This aims to improve perceived image quality, but typically lowers the measured PSNR score. Perceptual methods are currently only available for normal maps and RGB color data. PSNR girlies, be warned.

etc1s: supercompress szn πŸ’…

Supercompress the image data with ETC1S / BasisLZ. RED images will become RGB with RED in each component. RG images will have R in the RGB part and G in the alpha part of the compressed texture. When this is set, the following BasisLZ-related options become valid β€” otherwise they’re ignored.

  • --no_multithreading β€” disables multithreading. Deprecated. For backward compatibility. Use --threads 1 instead.
  • --clevel <level> β€” ETC1S / BasisLZ compression level, aka the encoding speed vs. quality tradeoff. Range is [0,5], default is 1. Higher values are slower but give higher quality.
  • --qlevel <level> β€” ETC1S / BasisLZ quality level. Range is [1,255]. Lower gives better compression/lower quality/faster. Higher gives less compression/higher quality/slower.

--qlevel automatically determines values for --max_endpoints, --max-selectors, --endpoint_rdo_threshold and --selector_rdo_threshold for the target quality level. Setting these options overrides the values determined by -qlevel which defaults to 128 if neither it nor both of --max_endpoints and --max_selectors have been set.

Note that both of --max_endpoints and --max_selectors must be set for them to have any effect. If all three options are set, a warning will be issued that --qlevel will be ignored.
Note also that --qlevel will only determine values for --endpoint_rdo_threshold and --selector_rdo_threshold when its value exceeds 128, otherwise their defaults will be used.
  • --max_endpoints <arg> β€” manually set the maximum number of color endpoint clusters. Range is [1,16128]. Default is 0, unset.
  • --endpoint_rdo_threshold <arg> β€” set endpoint RDO quality threshold. The default is 1.25. Lower is higher quality but less quality per output bit (try [1.0,3.0]). This will override the value chosen by --qlevel.
  • --max_selectors <arg> β€” manually set the maximum number of color selector clusters from [1,16128]. Default is 0, unset.
  • --selector_rdo_threshold <arg> β€” set selector RDO quality threshold. The default is 1.25. Lower is higher quality but less quality per output bit (try [1.0,3.0]). This will override the value chosen by --qlevel.
  • --no_endpoint_rdo β€” disable endpoint rate distortion optimizations. Slightly faster, less noisy output, but lower quality per output bit. Default is to do endpoint RDO.
  • --no_selector_rdo β€” disable selector rate distortion optimizations. Slightly faster, less noisy output, but lower quality per output bit. Default is to do selector RDO.

uastc: high-quality transcodable UASTC ✨

Create a texture in high-quality transcodable UASTC format. Main character energy.

  • --uastc_quality <level> β€” this optional parameter selects a speed vs quality tradeoff as shown in the following table:
    • 0 β€” Fastest β€” 43.45dB
    • 1 β€” Faster β€” 46.49dB
    • 2 β€” Default β€” 47.47dB
    • 3 β€” Slower β€” 48.01dB
    • 4 β€” Very slow β€” 48.24dB

You are strongly encouraged to also specify --zcmp to losslessly compress the UASTC data. This and any LZ-style compression can be made more effective by conditioning the UASTC texture data using the Rate Distortion Optimization (RDO) post-process stage. When uastc encoding is set the following options become available for controlling RDO:

  • --uastc_rdo_l [<lambda>] β€” enable UASTC RDO post-processing and optionally set UASTC RDO quality scalar (lambda) to lambda. Lower values yield higher quality/larger LZ compressed files, higher values yield lower quality/smaller LZ compressed files. A good range to try is [.25,10]. For normal maps a good range is [.25,.75]. The full range is [.001,10.0]. Default is 1.0.
Note that previous versions used the --uastc_rdo_q option which was removed because the RDO algorithm changed.
  • --uastc_rdo_d <dictsize> β€” set UASTC RDO dictionary size in bytes. Default is 4096. Lower values=faster, but give less compression. Range is [64,65536].
  • --uastc_rdo_b <scale> β€” set UASTC RDO max smooth block error scale. Range is [1.0,300.0]. Default is 10.0, 1.0 is disabled. Larger values suppress more artifacts (and allocate more bits) on smooth blocks.
  • --uastc_rdo_s <deviation> β€” set UASTC RDO max smooth block standard deviation. Range is [.01,65536.0]. Default is 18.0. Larger values expand the range of blocks considered smooth.
  • --uastc_rdo_f β€” do not favor simpler UASTC modes in RDO mode.
  • --uastc_rdo_m β€” disable RDO multithreading (slightly higher compression, deterministic).

  • --input_swizzle <swizzle> β€” swizzle the input components according to swizzle, which is an alhpanumeric sequence matching the regular expression ^[rgba01]{4}$. Regex girlies rise.
  • --normal_mode β€” only valid for linear textures with two or more components. If the input texture has three or four linear components it is assumed to be a three component linear normal map storing unit length normals as (R=X, G=Y, B=Z). A fourth component will be ignored. The map will be converted to a two component X+Y normal map stored as (RGB=X, A=Y) prior to encoding. If unsure that your normals are unit length, use --normalize. If the input has 2 linear components it is assumed to be an X+Y map of unit normals.

The Z component can be recovered programmatically in shader code by using the equations:

          nml.xy = texture(...).ga;              // Load in [0,1]
          nml.xy = nml.xy * 2.0 - 1.0;           // Unpack to [-1,1]
          nml.z = sqrt(1 - dot(nml.xy, nml.xy)); // Compute Z

For ASTC encoding, --encode astc, encoder parameters are tuned for better quality on normal maps. For ETC1S encoding, --encode etc1s, RDO is disabled (no selector RDO, no endpoint RDO) to provide better quality.

In toktx you can prevent conversion of the normal map to two components by specifying --input_swizzle rgb1.

  • --normalize β€” normalize input normals to have a unit length. Only valid for linear textures with 2 or more components. For 2-component inputs 2D unit normals are calculated. Do not use these 2D unit normals to generate X+Y normals for --normal_mode. For 4-component inputs a 3D unit normal is calculated. 1.0 is used for the value of the 4th component.
  • --no_sse β€” forbid use of the SSE instruction set. Ignored if CPU does not support SSE. Only the Basis Universal compressor uses SSE.
  • --bcmp β€” Deprecated. Use --encode etc1s instead.
  • --uastc [<level>] β€” Deprecated. Use --encode uastc instead.
  • --zcmp [<compressionLevel>] β€” supercompress the data with Zstandard. Implies --t2. Can be used with data in any format except ETC1S / BasisLZ. Most effective with RDO-conditioned UASTC or uncompressed formats. The optional compressionLevel range is 1 - 22 and the default is 3. Lower values=faster but give less compression. Values above 20 should be used with caution as they require more memory.
  • --threads <count> β€” explicitly set the number of threads to use during compression. By default, ETC1S / BasisLZ and ASTC compression will use the number of threads reported by thread::hardware_concurrency or 1 if value returned is 0.
  • --verbose β€” print encoder/compressor activity status to stdout. Currently only the astc, etc1s and uastc encoders emit status.
  • -h, --help β€” print this usage message and exit.
  • -v, --version β€” print the version number of this program and exit.

In case of ambiguity, such as when the last option is one with an optional parameter, separate options from file names with --.

Any specified ASTC, ETC1S / BasisLZ, UASTC and supercompression options are recorded in the metadata item KTXwriterScParams in the output file.

Options can also be set in the environment variable TOKTX_OPTIONS. TOKTX_OPTIONS is parsed first. If conflicting options appear in TOKTX_OPTIONS or the command line, the last one seen wins. However if both --automipmap and --mipmap are seen, it is always flagged as an error. You can, for example, set TOKTX_OPTIONS=--lower_left_maps_to_s0t0 to change the default mapping of the logical image origin to match the GL convention.

πŸ’₯ EXIT STATUS πŸ’₯

toktx exits 0 on success, 1 on command line errors and 2 on functional errors. That’s the whole vibe check.

✨ HISTORY ✨

okay bestie, story time πŸŽ€ this is the whole glow-up timeline of toktx, and honestly the character development is real. let's get into it πŸ’…

Version 4.0 (using new version numbering system) πŸŽ‰

  • Add KTX version 2 support including Basis Universal encoding. πŸ’–
  • Add .png and .jpg readers. πŸ“Έ
  • Transform NetPBM input files to sRGB OETF. 🌈
  • Add mipmap generation. ✨
  • Remove legacy items. πŸ—‘οΈ

Version 1.3 πŸ¦‹

  • Switch to ktxTexture API. πŸ”„
  • Add --levels option. πŸ‘‘
  • Add --2d option. 🫢

Version 1.2 🌸

  • Remove --sized; always create sized format. 😭
  • Write metadata by default. πŸ“
  • Bug fixes. πŸ›

Version 1.1 ⭐

  • Moved --alpha and --luminance to legacy. πŸ‘΅

πŸ‘‘ AUTHOR πŸ‘‘

Mark Callow, github.com/MarkCallow β€” literally the icon behind all of this, no cap 🫢✨


and that's the whole page, bestie!! you made it to the end, so proud of you fr fr πŸ₯ΉπŸ’– go forth and toktx responsibly πŸ’…

signing off from toktx(1), source/version Version 0.0.0, dated Tue Jan 1 1980 00:00:00 πŸŽ€βœ¨ iykyk πŸ¦‹

πŸ“¦ where this page comes from