# fmtconv — format conversion tools for Vapoursynth

## Abstract

Authors: |  | Firesledge (aka Cretindesalpes)
Version: |  | r17
Download: |  | http://ldesoras.free.fr/prod.html
Category: |  | Format tools
Requirements: |  | Vapoursynth
License: |  | WTFPL

## Table of contents

1. Introduction
2. Usage
   1. Loading
   2. Examples
   3. Compiling from the source code
3. Filter description
   1. bitdepth
   2. convert
   3. matrix
   4. matrix2020cl
   5. resample
   6. transfer
   7. stack16tonative, nativetostack16
4. Troubleshooting
5. Changelog

## I) Introduction

Fmtconv is a format-conversion plug-in for the Vapoursynth video processing engine. It does:

- Resizing.
- Bitdepth conversion with dithering.
- Colorspace conversion (matrix and transfer characteristics).

It supports:

- Pixel data types: 8-–12-, 14- and 16-bit integer, 32-bit float.
- Colorspaces: RGB, Y, YUV in 4:4:4, 4:2:2, 4:2:0, 4:1:1 and YCgCo with the same chroma subsampling factors.
- Progressive and interlaced content.

Fmtconv is focussed primarily on quality and exactness rather than execution speed. This does not mean it is slow or unoptimized, but fmtconv is clearly not on par with the fastest equivalent 8-bit filters.

## II) Usage

### Loading fmtconv

Using the Python 3.4 interface:

    import vapoursynth as vs
    core = vs.get_core ()
    core.std.LoadPlugin (path=r'C:\path\fmtconv.dll')

Of course you can avoid the `LoadPlugin` command by copying the plug-in file to the autoloading directory. Check the Vapoursynth manual for more information.

### Examples

#### A basic example

Requires FFmpegSource2:

    # Load Vapoursynth
    import vapoursynth as vs
    core = vs.get_core ()

    # Load the plug-ins
    core.std.LoadPlugin (path=r'C:\path\fmtconv.dll')
    core.std.LoadPlugin (path=r'C:\path\ffms2.dll')

    # Load the video clip into c using FFmpegSource
    c = core.ffms2.Source (source=r'C:\path\video.mkv')

    # Change the resolution. The output clip is now in 16 bits.
    c = core.fmtc.resample (clip=c, w=1280, h=720)

    # Dither the result, back to 8 bits
    c = core.fmtc.bitdepth (clip=c, bits=8)

    # Send the processed clip to the calling process
    c.set_output ()

#### Resizing and chroma subsampling conversions

Simple resize with 16- or 32-bit output:

    c = core.fmtc.resample (clip=c, w=1280, h=720)

Bobbing an interlaced stream (here, Top Field First):

    c = core.std.SeparateFields (clip=c, tff=True)
    c = core.fmtc.resample (clip=c, scalev=2, kernel="cubic", interlaced=True, interlacedd=False)

Converting a progressive stream from YUV 4:2:2 to 4:2:0 and back to 8 bits:

    c = core.fmtc.resample (clip=c, css="420")
    c = core.fmtc.bitdepth (clip=c, bits=8)

Same as above, with interlaced content:

    tff = True
    c = core.std.SeparateFields (clip=c, tff=tff)
    c = core.fmtc.resample (clip=c, css="420", interlaced=True)
    c = core.fmtc.bitdepth (clip=c, bits=8)
    c = core.std.DoubleWeave (clip=c, tff=tff)
    c = core.std.SelectEvery (clip=c, cycle=2, offsets=0)

#### Colorspace conversions

YUV 4:2:0 to RGB:

    c = core.fmtc.resample (clip=c, css="444")
    c = core.fmtc.matrix (clip=c, mat="601", col_fam=vs.RGB)
    c = core.fmtc.bitdepth (clip=c, bits=8)

RGB to YUV 4:2:0:

    c = core.fmtc.matrix (clip=c, mat="601", col_fam=vs.YUV, bits=16)
    c = core.fmtc.resample (clip=c, css="420")
    c = core.fmtc.bitdepth (clip=c, bits=8)

YUV colormatrix conversion from BT. 601 to BT. 709. For example to insert a DVD content in an HDTV stream. Note that we need to convert the clip to 4:4:4 in an intermediate step because `matrix` can only process 4:4:4.

    c = core.fmtc.resample (clip=c, css="444")
    c = core.fmtc.matrix (clip=c, mats="601", matd="709")
    c = core.fmtc.resample (clip=c, css="420")
    c = core.fmtc.bitdepth (clip=c, bits=8)

Conversion from full range to TV-range:

    c = core.fmtc.bitdepth (clip=c, fulls=True, fulld=False)

Displaying an anamorphic 1440x1080 HDTV content on a standard computer display:

    c = core.fmtc.resample (clip=c, w=1920, h=1080, css="444")
    c = core.fmtc.matrix (clip=c, mat="709", col_fam=vs.RGB)
    c = core.fmtc.transfer (clip=c, transs="1886", transd="srgb")
    c = core.fmtc.bitdepth (clip=c, bits=8)

### Compiling from the source code

#### Visual C++

Visual Studio 2013 or later is required, previous versions are not supported anymore. Just load `fmtconv.sln` and run the compiler.

You can also import all the `*.cpp`, `*.h` and `*.hpp` files located in the `src` directory and its subfolders. Then:

- Add `.` (the `src` directory) as include path.
- Use the `v120_xp` toolset for the 32-bit version.
- For the whole project, enable the SS2 instruction set.
- Enable the AVX2 instruction set for the `*.cpp` files containing `avx2` in their name, and the AVX set for the `avx` files.
- Enable optimizations maximizing speed and “any suitable” functions for inlining.

#### GCC

From the `src` directory, compile and link all these files with `g++`:

    main.cpp
    AvstpWrapper.cpp
    fmtc/*.cpp
    fmtcl/*.cpp
    fstb/*.cpp
    vsutl/*.cpp

Add `AvstpFinder.cpp` on Windows. Use the following options (on a single line):

    -std=c++11 -shared -fabi-version=6 -msse2 -mcx16 -O3 -DNDEBUG -I.
    -Wall -Wextra -Wno-unused-parameter -Wno-unused-result -Wno-missing-field-initializers -Wshadow

You’ll need to replace `-msse2` with `-mavx2` for all the `*.cpp` files containing `avx2` in their name. Same with `-mavx` and `avx` files.

Be careful, some files located in different directories have the same name. To avoid conflicts and missing symbols, keep the source directory structure for your object files.

People have reported that the `-fPIC` option was sometimes needed.

The `-mcx16` option is only need for 64-bit builds. This means that they won’t work on early AMD64 CPUs and allegedly on a few Intel-based motherboards where the CMPXCHG16B instruction doesn’t work for some reason.

To compile a debug version, replace `-O3 -DNDEBUG` with `-g`.

With MinGW, it seems you will need a specific MinGW-64 build supporting C++11 threading (not tested here yet, please report if you find something useful).

On Linux and similar GNU-based systems, the `build` directory contains autotools settings.

## III) Filters description

### bitdepth

    fmtc.bitdepth (
    	clip       : clip      ;
    	csp        : int  : opt;
    	bits       : int  : opt;
    	flt        : int  : opt;
    	planes     : int[]: opt; (all)
    	fulls      : int  : opt; (depends on the colorspace)
    	fulld      : int  : opt; (fulls)
    	dmode      : int  : opt; (3)
    	ampo       : float: opt; (1)
    	ampn       : float: opt; (0)
    	dyn        : int  : opt; (False)
    	staticnoise: int  : opt; (False)
    	cpuopt     : int  : opt; (-1)
    	patsize    : int  : opt; (32)
    )

Bitdepth conversion with optional dithering.

Dithering is performed when meeting at least one of these conditions:

- Reducing the bitdepth of integer data, or converting from float to integer.
- Doing a full-range ↔ TV-range conversion between integer formats, because the resulting values haven’t an exact representation.

Pure ordered dithering seems to be retained better than noise or error diffusion by video compression in 8 bits. Therefore this is the recommended method to avoid color banding, unless you encode at very high bitrates. If you don’t care about video compression, error diffusion gives the most accurate results. To avoid discontinuities between purely flat areas and dithered areas, you can add a bit of noise.

The internal noise generator is deterministic and will give the same result each run.

The internal processing is done in floating point as soon as the input is floating point or a range conversion is detected.

#### Parameters

clip

The input clip. Mandatory. Supported input formats:

- 8-–12-, 14- and 16-bit integer.
- 32-bit floating point.
- Any planar colorspace.

csp

The destination format, as Vapoursynth constant. Can only change the bitdepth and the data type (integer or float). Supported destination colorspaces are the same as for the input clip.

bits

Destination bitdepth. It’s sometimes more convenient to provide only the number of bits rather than the full format. When there is no ambiguity between bitdepth and data type, the data type is automatically selected depending on the bitdepth. For example, specifying 32 bits is enough to switch the output to float.

flt

Set it to 1 to convert to float, and to 0 for integer data. As long as only 32-bit floating point data is supported, you don’t need to specify the bitdepth for a float conversion.

planes

A list of planes to process (0 to 2), in any order. The content of an unprocessed plane should be considered as garbage.

fulls, fulld

Indicates if the clip is full-range (True) or TV-range (False). fulls is for input, fulld for output. Reference black and white have different values depending on the range. In 8 bits, pixel values scale from 0 to 255 in full range, and 16 to 235 in TV-range (16 to 240 for the YUV chroma planes). This value has no meaning for float data.

The default value depends on the colorspace. For example, full-range is assumed for RGB and YCgCo colorspaces. Others are assumed TV-range. These parameters are mainly intended to guide conversions between integer and floating-point data. They can also be used for range conversions. Pixel values are not clipped during a conversion between two TV-range formats.

dmode

Dithering mode, when applicable.

0 | Ordered dithering (Bayer matrix).
1 | No dither, round to the closest value.
2 | Round, may be a bit faster but possibly less accurate.
3 | Sierra-2-4A error diffusion, aka “Filter Lite”. Quick and excellent quality, similar to Floyd-Steinberg.
4 | Stucki error diffusion. Preserves delicate edges better but distorts gradients.
5 | Atkinson error diffusion. Generates distinct patterns but keeps clean the flat areas.
6 | Floyd-Steinberg error diffusion. Classic.
7 | Ostromoukhov error diffusion. Slow, available only for integer input at the moment. Avoids usual F-S artefacts.
8 | Void and cluster halftone dithering. Better visual aspect than ordered dithering.

When using error-diffusion dithering on interlaced content, you should separate the fields first before converting them.

ampo

The ordered dither peak-to-peak amplitude, depends on the target bitdepth. ≥ 0. On error diffusion algorithms, it increases the collected error amount, helping to extend the range of the dithering while preserving its natural pattern (especially Atkinson’s). This gives a better looking result than just adding noise.

ampn

The noise peak-to-peak amplitude, depends on the target bitdepth. ≥ 0. Currently, the maximum value is 4. The noise is added before dithering. It reduces the SNR but a small amount may give a better, more uniform visual appearance.

dyn

Indicates if the ordered dither pattern is dynamic (True) or static (False). If dynamic, the pattern is rotated each frame.

staticnoise

If set to 1, the noise generated with ampn is static and remains the same every frame.

cpuopt

Limits the CPU instruction set. −1: automatic (no limitation), 0: default instruction set only (depends on the compilation settings), 1: limit to SSE2, 10: limit to AVX2.

patsize

Width of the pattern used in the Void and cluster algorithm. The only valid values are 4, 8, 16 and 32.

### convert

    fmtc.convert (
    	# Input
    	clip       : clip        ;

    	# Resizing/resampling
    	w          : int    : opt;
    	h          : int    : opt;
    	sx         : float[]: opt; (0)
    	sy         : float[]: opt; (0)
    	sw         : float[]: opt; (0)
    	sh         : float[]: opt; (0)
    	scale      : float  : opt; (0)
    	scaleh     : float  : opt; (0)
    	scalev     : float  : opt; (0)
    	kernel     : data[] : opt; ("spline36")
    	kernelh    : data[] : opt; (kernel)
    	kernelv    : data[] : opt; (kernel)
    	impulse    : float[]: opt;
    	impulseh   : float[]: opt; (impulse)
    	impulsev   : float[]: opt; (impulse)
    	taps       : int[]  : opt; (4)
    	tapsh      : int[]  : opt; (taps)
    	tapsh      : int[]  : opt; (taps)
    	a1         : float[]: opt;
    	a2         : float[]: opt;
    	a3         : float[]: opt;
    	kovrspl    : int[]  : opt; (1)
    	fh         : float[]: opt; (1)
    	fv         : float[]: opt; (1)
    	cnorm      : int[]  : opt; (True)
    	totalh     : float[]: opt; (0)
    	totalv     : float[]: opt; (0)
    	invks      : int[]  : opt; (False)
    	invksh     : int[]  : opt; (invks)
    	invksv     : int[]  : opt; (invks)
    	invkstaps  : int[]  : opt; (4)
    	invkstapsh : int[]  : opt; (invkstaps)
    	invkstapsv : int[]  : opt; (invkstaps)
    	center     : int[]  : opt; (True)

    	# Output clip format
    	csp        : int    : opt;
    	css        : data   : opt;
    	col_fam    : int    : opt;
    	bits       : int    : opt;
    	flt        : int    : opt;

    	# Output dithering
    	dmode      : int    : opt; (3)
    	ampo       : float  : opt; (1)
    	ampn       : float  : opt; (0)
    	dyn        : int    : opt; (False)
    	staticnoise: int    : opt; (False)

    	# Common sub-format spec
    	cplace     : data   : opt; ("mpeg2")
    	mat        : data   : opt;
    	coef       : float[]: opt;
    	interlaced : int    : opt; (2)
    	tff        : int    : opt; (2)
    	useflt     : int    : opt; (False)

    	# Input clip sub-format spec
    	fulls      : int    : opt; (depends on the colorspace)
    	cplaces    : data   : opt; (cplace)
    	mats       : data   : opt;

    	# Output clip sub-format spec
    	fulld      : int    : opt; (fulls)
    	cplaced    : data   : opt; (cplace)
    	matd       : data   : opt;

    	# Transfert curve parameters
    	transs     : data[] : opt;
    	transd     : data[] : opt;
    	cont       : float  : opt;
    	gcor       : float  : opt;

    	cpuopt     : int    : opt; (-1)
    )

Multi-purpose conversion function.

Not available yet.

### matrix

    fmtc.matrix (
    	clip     : clip        ;
    	mat      : data   : opt;
    	mats     : data   : opt;
    	matd     : data   : opt;
    	fulls    : int    : opt; (depends on the colorspace)
    	fulld    : int    : opt; (fulls)
    	coef     : float[]: opt;
    	csp      : int    : opt;
    	col_fam  : int    : opt;
    	bits     : int    : opt;
    	singleout: int    : opt; (-1)
    	cpuopt   : int    : opt; (-1)
    )

Colorspace conversion or simple cross-plane matrix.

For Y’Cb’Cr’ and Y’Cg’Co’ colorspaces, 4:4:4 is required (no chroma subsampling). To process a subsampled colorspace, you must convert it to 4:4:4 first.

The output is not dithered, therefore you should output at a higher bitdepth than the input and dither afterward with `bitdepth` to avoid potential banding.

When the destination color family (R’G’B’, Y’Cb’Cr’ or Y’Cg’Co’) is not specified (via col_fam or csp), the function tries to deduce it from the matrix settings and the source color family. If it cannot be deduced, the color family remains unchanged.

Please note that this function doesn’t do conversions based on the color primaries. The R’G’B’ data are always releative to their specified standard. For example, converting Y’Cb’Cr’ data straight from BT.2020 to BT.709 doesn’t make sense as these colorspaces are defined with different primaries. For meaningful results, convert to R’G’B’ and use a 3-D LUT to perform the intermediary conversion.

#### Parameters

clip

The input clip. Mandatory. Supported input formats:

- 8-, 9-, 10-, 12- and 16-bit integer.
- 32-bit floating point.
- Any planar colorspace with 3 planes.

mat

Predefined matrix for conversions to and from R’G’B’. The direction is deduced from the specified input and output colorspaces. Possible values are:

`"601"` | ITU-R BT.601 / ITU-R BT.470-2 / SMPTE 170M. For Standard Definition content.
`"709"` | ITU-R BT.709. For High Definition content.
`"2020"` | ITU-R BT.2020, non constant luminance mode. For UHDTV content.
`"240"` | SMPTE 240M
`"FCC"` | FCC
`"YCgCo"` | Y’Cg’Co’
`"RGB"` | RGB. Identity, no cross-plane calculations.

mats, matd

Source and destinations matrices for YUV. Use both when you want to do a conversion between BT.601 and BT.709. Values are the same as mat.

fulls, fulld

Indicates if the clip is full-range (True) or TV-range (False). fulls is for input, fulld for output. Reference black and white have different values depending on the range. In 8 bits, pixel values scale from 0 to 255 in full range, and 16 to 235 in TV-range (16 to 240 for the YUV chroma planes). This value has no meaning for float data.

The default value depends on the colorspace. For example, full-range is assumed for R’G’B’ and Y’Cg’Co’ colorspaces. Others are assumed TV-range. These parameters are mainly intended to guide conversions between integer and floating-point data. They can also be used for range conversions. Pixel values are not clipped during a conversion between two TV-range formats.

coef

A list of 12 coefficients for a custom matrix. The coefficients should be scaled assuming the input is floating point, even if the actual input is integer. This means luma and R’G’B’ signals range from 0 to 1, and chroma signals from −0.5 to +0.5. Coefficients are listed by rows. Each row is terminated with a fourth coefficient, the additive constant (still in floating-point range). This means the matrix is actually 4×3 and during the multiplication, the input column-vector has an implicit 1 appended to its end. For example, with an R’G’B’ input:

| Y |
| Cb |
| Cr |

=

| c0 | c1 | c2 | c3 |
| c4 | c5 | c6 | c7 |
| c8 | c9 | c10 | c11 |

×

| R |
| G |
| B |
| 1 |

| Y | = | R × c0 + G × c1 + B × c2 + c3
Cb | = | R × c4 + G × c5 + B × c6 + c7
Cr | = | R × c8 + G × c9 + B × c10 + c11

csp

The destination format, as Vapoursynth constant. It cannot change the data type (integer or float) nor the chroma subsampling. If the colorspace family is set to GRAY, single-plane processing is enabled. The output plane is selected with singleout (0 if not specified).

col_fam

Explicit specification of the destination color family, as Vapoursynth constant. Supersedes the color family from csp. You can only specify colorspace with the same number of planes as the input clip.

bits

Explicit specification of the destination bitdepth. The only allowed values are 8, 9, 10, 12, 16 and 32. However you cannot reduce the bitdepth, only keep or increase it. Supersedes the bitdepth from csp.

singleout

Enable single-plane processing. This is useful to obtain only the luma from an R’G’B’ input, for example. The parameter is the plane index, ranging from 0 to 2. A negative value specifies that all planes should be processed. If singleout is ≥ 0, it supersedes the colorspace family specified in csp.

Note: when extracting a chroma plane, results between int with TV range and float data type may slightly differ. This is because in float, a neutral chroma (0%) is converted to the exact value of a medium gray (50%). In integer, the chroma output value is mapped 1–1 to the luma channel. However in TV-range, medium gray is not located exactly at the half of the data range, it lies slightly below.

cpuopt

Limits the CPU instruction set. −1: automatic (no limitation), 0: default instruction set only (depends on the compilation settings), 1: limit to SSE2, 7: limit to AVX, 10: limit to AVX2.

### matrix2020cl

    fmtc.matrix2020cl (
    	clip    : clip      ;
    	full    : int  : opt; (False)
    	csp     : int  : opt;
    	bits    : int  : opt;
    	cpuopt  : int  : opt; (-1)
    )

Colorspace conversion using the ITU-R BT.2020 constant luminance matrix.

The function converts between linear RGB and Y’Cb’Cr’ colorspaces. This conversion cannot be achieve with a classic linear matrix. The output colorspace, hence the direction of the conversion, is automatically deduced from the input colorspace.

For Y’Cb’Cr’ colorspaces, 4:4:4 is required (no chroma subsampling). To process a subsampled colorspace, you must convert it to 4:4:4 first.

The RGB colorspace is always 16 bits when using integers, or 32 bits in float. The output is not dithered, therefore you should output at a higher bitdepth than the input and dither afterward with `bitdepth` to avoid potential banding.

Please note that the RGB content is always considered as linear light. The BT.2020 gamma curve is used in both directions. When operating on floating point data, the function uses the 12-bit variant of the scaling coefficients.

#### Parameters

clip

The input clip. Mandatory. Supported input formats:

- 8-, 9-, 10-, 12- and 16-bit integer for Y’Cb’Cr’, 16-bit integer for RGB.
- 32-bit floating point.
- YUV and RGB colorspaces.

full

Indicates if the Y’Cb’Cr’ clip is full-range (True) or TV-range (False). Reference black and white have different values depending on the range. In 8 bits, pixel values scale from 0 to 255 in full range, and 16 to 235 in TV-range (16 to 240 for the YUV chroma planes). This value has no meaning for float data.

csp

The destination format, as Vapoursynth constant. It must be compatible with what is logically expected as output (RGB or YUV). It cannot change the data type (integer or float) nor the chroma subsampling. If the output is integer RGB, the bitdepth must be 16.

bits

Explicit specification of the destination bitdepth. The only allowed values are 8, 9, 10, 12, 16 and 32. They are restricted by the output data type and format (16 bits for integer RGB). Supersedes the bitdepth from csp.

cpuopt

Limits the CPU instruction set. −1: automatic (no limitation), 0: default instruction set only (depends on the compilation settings).

### resample

    fmtc.resample (
    	clip      : clip        ;
    	w         : int    : opt;
    	h         : int    : opt;
    	sx        : float[]: opt; (0)
    	sy        : float[]: opt; (0)
    	sw        : float[]: opt; (0)
    	sh        : float[]: opt; (0)
    	scale     : float  : opt; (0)
    	scaleh    : float  : opt; (0)
    	scalev    : float  : opt; (0)
    	kernel    : data[] : opt; ("spline36")
    	kernelh   : data[] : opt; (kernel)
    	kernelv   : data[] : opt; (kernel)
    	impulse   : float[]: opt;
    	impulseh  : float[]: opt; (impulse)
    	impulsev  : float[]: opt; (impulse)
    	taps      : int[]  : opt; (4)
    	tapsh     : int[]  : opt; (taps)
    	tapsv     : int[]  : opt; (taps)
    	a1        : float[]: opt;
    	a2        : float[]: opt;
    	a3        : float[]: opt;
    	kovrspl   : int[]  : opt; (1)
    	fh        : float[]: opt; (1)
    	fv        : float[]: opt; (1)
    	cnorm     : int[]  : opt; (True)
    	totalh    : float[]: opt; (0)
    	totalv    : float[]: opt; (0)
    	invks     : int[]  : opt; (False)
    	invksh    : int[]  : opt; (invks)
    	invksv    : int[]  : opt; (invks)
    	invkstaps : int[]  : opt; (4)
    	invkstapsh: int[]  : opt; (invkstaps)
    	invkstapsv: int[]  : opt; (invkstaps)
    	csp       : int    : opt;
    	css       : data   : opt;
    	planes    : float[]: opt; (all)
    	fulls     : int    : opt; (depends on the colorspace)
    	fulld     : int    : opt; (fulls)
    	center    : int[]  : opt; (True)
    	cplace    : data   : opt; ("mpeg2")
    	cplaces   : data   : opt; (cplace)
    	cplaced   : data   : opt; (cplace)
    	interlaced: int    : opt; (2)
    	tff       : int    : opt; (2)
    	flt       : int    : opt; (False)
    	cpuopt    : int    : opt; (-1)
    )

Resizes the planes of a clip. This function can change the chroma subsampling.

Output is always 16-bit integer (default for integer input) or 32-bit float. Use `fmtc.bitdepth` to convert the result to a lower bitdepth. It is possible to select the internal precision: float, or 16-bit integers with a 32-bit accumulator for the convolution. Internal conversion from float or 32-bit integers to 16 bits is done by quick rounding (no dithering). The integer operation path is available only when input and output formats are integer too.

The function can resize interlaced content, but only if presented as separated, interleaved fields. It uses the `_Field` and `_FieldBased` frame properties to detect interlaced content and field parity, maintaining the correct chroma and luma relative positions. If this automatic detection is not desired, you can specify manually the interlaced and tff parameters. Simple intra-field deinterlacing (“bob”) can be achieved this way, by specifying scalev=2.

Excepted impulse*, array parameters allow to specify plane-specific values. When specifying less than 3 values, the last specified value will be reused for the next planes. However planes works slightly differently, check the related paragraph for details.

Note: field resizing is not always the best way to handle interlaced content, especially for upscales. You’ll probably have better results by using a “smart” deinterlacer (making use of temporal information and anti-aliasing), resizing the progressive content at double rate then reinterlacing. Simple field resampling is more or less equivalent to this method, using a naive bob.

The function can also be used to compute horizontal and vertical convolutions. If you do so, don’t forget to set:

- fh or fv to −1 to make sure the clip is processed even if its size doesn’t change,
- cnorm to false to avoid automatic kernel normalisation if your impulse is already normalised, or specify totalv or totalh if the normalisation factor is not the sum of the impulse
- and center to False to keep the desired spacing between the sampling points.

#### Parameters

clip

Clip to be resized. Mandatory. Supported input formats:

- 8-, 9-, 10-, 12- and 16-bit integer.
- 32-bit floating point.
- Any planar colorspace.

w, h

New picture width and height in pixels, > 0. If not specified, it will keep the original dimensions. The dimensions must be compatible with the destination chroma subsampling. They take precedence over the scale, scaleh and scalev parameters.

sx, sy

Coordinate of the top-left corner of the picture sub-area used as source for the resizing. They can be fractional. If negative, the picture is extended by replicating the left pixel column.

These parameters are arrays, so it’s possible to specify a different value for each plane. The last value is used for the unspecified planes. The coordinates are always related to the pixel dimensions, you don’t need to scale them with the chroma subsampling.

sw, sh

Size in pixels of the sub-area to resize. They can be fractional. If 0, the area has the same size as the source clip. If negative, they define coordinates relative to the bottom-right corner, in a `Crop`-like manner. These parameters are arrays like sx and sy.

scale, scaleh, scalev

Use these parameters to set relative dimensions, > 0. For example scale=0.5 will halve the picture size. The computed dimensions will be compatible with the destination chroma subsampling. Zero is ignored.

kernel

Kernel used by the resizer. Possible values are:

`"point"` | Nearest neighbour interpolation. Same as Avisynth’s `PointResize`.
`"rect"` or `"box"` | Box filter.
`"linear"` or `"bilinear"` | Bilinear interpolation. Same as Avisynth’s `BilinearResize`.
`"cubic"` or `"bicubic"` | Bicubic interpolation. Same as `BicubicResize`. The b and c variables are mapped on a1 and a2 and are both set to 1/3 by default.
`"lanczos"` | Sinc function windowed by the central lobe of a sinc. Use taps to specify its impulse length. Same as `LanczosResize`.
`"blackman"` | Blackman-Harris windowed sinc. Use taps to control its length. Same as `BlackmanResize`.
`"blackmanminlobe"` | Another kind of Blackman windowed sinc, with a bit less ringing. Use taps for you know what.
`"spline16"` | Cubic spline based kernel, 4 sample points. Same as `Spline16Resize`.
`"spline36"` | Spline, 6 sample points. Same as `Spline36Resize`.
`"spline64"` | Spline, 8 sample points. Same as `Spline64Resize`.
`"spline"` | Generic splines, number of sample points is twice the taps parameter, so you can use taps = 6 to get a `Spline144Resize` equivalent.
`"gauss"` or `"gaussian"` | Gaussian kernel. The p parameter is mapped on a1 and controls the curve width. The higher p, the sharper. It is set to 30 by default. This resizer is the same as `GaussResize`, but taps offers a control on the filter impulse length. For low p values (soft and blurry), it’s better to increase the number of taps to avoid truncating the gaussian curve too early and creating artifacts.
`"sinc"` | Truncated sinc function. Use taps to control its length. Same as `SincResize`.

impulse, impulsew, impulseh

Offers the possibility to create your own kernel (useful for convolutions). Add your coefficents in the array. The number of coefficients must be odd. The curve is linearly interpolated between the provided points. You can oversample the impulse by setting kovrspl to a value > 1.

taps, tapsh, tapsv

Some kernels have a variable number of sample points, given by this parameter. Actually this counts half the number of lobes (or equivalent); in case of downscaling, the actual number of sample points may be greater than the specified value. Range: 1–128

a1, a2, a3

Specific parameters, depending on the selected kernel.

kovrspl

Specifies here how many times the kernel is oversampled when you provide a custom impluse response. ≥ 1.

fh, fv

Horizontal and vertical frequency factors, also known as inverse kernel support. They are multipliers on the theoretical kernel cutoff frequency in both directions. Values below 1.0 spatially expand the kernel and blur the picture. Values over 1.0 shrink the kernel and let higher frequencies pass. The result will look sharper but more aliased. The multiplicator is applied after the kernel scaling in case of downsizing. Negative values force the processing, even if the horizontal size doesn’t change. The filter will use the absolute parameter value.

cnorm

If set to `true`, the impulse sum is normalised to 1 for each pixel. This is the normal behaviour when resizing, to make sure the energy is constant for all pixels. If you use the resizer as a convolution engine, it is advised to disable the normalisation.

totalh, totalv

When cnorm is activated, these parameters specify the normalisation value for the corresponding kernel. 0 means that the normalisation value is the sum of the coefficients. The Masktools’`mt_convolution` function has a single parameter for this use: total = totalh × totalv. Because the convolution is computed with floating point data, there is no saturation of intermediate results, therefore the balance between totalh and totalv is not important, only their product will be taken into account.

invks, invksh, invksv

Set these parameter to True to activate the kernel inversion mode for the specified direction (use invks for both). Inverting the kernel allows to “undo” a previous upsizing by compensating the loss in high frequencies, giving a sharper and more accurate output than classic kernels, closer to the original. This is particularly useful for clips upscaled with a bilinear kernel. All the kernel-related parameters specify the kernel to undo. The target resolution must be as close as possible to the initial resolution. The kernel inversion is mainly intended to downsize an upscaled picture. Using it for upsizing will not restore details but will give a sligthly sharper look, at the cost of a bit of aliasing and ringing. This mode is somewhat equivalent to the `debilinear` plug-in but works with a different principle.

invkstaps, invkstapsh, invkstapsv

In kernel inversion mode (invks=True), this parameter sets the number of taps for the inverted kernel. Use it as a tradeof between softness and ringing. Range: 1–128

csp

The destination format, as Vapoursynth constant. Can only change the bitdepth and the data type (integer or float). Only 16-bit integer (xxxP16) and 32-bit float data types are allowed.

css

Destination chroma subsampling, for YUV and YCgCo colorspaces. Supersedes the chroma subsampling from csp. You can also specify the subsampling with the predefined values or with a two-digit string. The first digit for the horizontal subsampling, and the second for the vertical subsampling. Only power-of-2 numbers are allowed. For example `"41"` is equivalent to 4:1:1 and `"22"` to 4:2:0.

The predefined values are:

`"444"` or `"4:4:4"` | 4:4:4, no chroma subsampling.
`"422"` or `"4:2:2"` | 4:2:2, horizontal 2x chroma subsampling.
`"420"` or `"4:2:0"` | 4:2:0, horizontal and vertical 2x chroma subsampling.
`"411"` or `"4:1:1"` | 4:1:1, horizontal 4x chroma subsampling.

planes

This array decribes how each plane should be processed. It’s similar to the y, u and v parameters in Masktools 2.

−65535 to +0.5 | All the pixels of the plane will be set to −x (the opposite of the specified value). The range depends on the output data type. Remember, in floating-point YUV, the chroma planes range from −0.5 to +0.5.
1 | The plane will not be processed. This means that the content of the output plane is pure garbage.
2 | The plane of the input clip will be copied and possibly cropped. Areas out of the input picture are left unprocessed. Range (full or TV) conversions are ignored.
3 | The plane will be processed.

fulls, fulld

Indicates if the clip is full-range (True) or TV-range (False). fulls is for input, fulld for output. Reference black and white have different values depending on the range. In 8 bits, pixel values scale from 0 to 255 in full range, and 16 to 235 in TV-range (16 to 240 for the YUV chroma planes). This value has no meaning for float data.

The default value depends on the colorspace. For example, full-range is assumed for RGB and YCgCo colorspaces. Others are assumed TV-range. These parameters are mainly intended to guide conversions between integer and floating-point data. They can also be used for range conversions. Pixel values are not clipped during a conversion between two TV-range formats.

center

Like the Avisynth resizers, this resizer preserves the position of the picture center. Disable this parameter if you may want to resize by preserving the top-left corner position. Similarly, if you are convolving without resizing, setting it to `false` ensures you that the same kernel will be applied to all pixels.

cplace, cplaces, cplaced

Placement of the chroma samples. cplaces specifies the source clip only, cplaced the destination clip. Can be one of these strings:

`"MPEG1"` | 4:2:0 subsampling used in MPEG-1 and JPEG. Chroma samples are located on the center of each group of 4 pixels.
`"MPEG2"` | Subsampling used in MPEG-2 4:2:x and most other formats. Chroma samples are located on the left pixel column of the group.
`"DV"` | For 4:2:0 modes, it’s like MPEG-2 but U and V channels are “co-sited” vertically: V on the top row, and U on the bottom row. For 4:1:1, chroma is located on the leftmost column.

The chroma placement is ignored when center is set to `False` or kernel to `"point"`. You’ll find below an overview of common chroma placement and subsampling combinations:

interlaced, interlacedd

Specifies if the clip is made of frames or fields. interlacedd overrides interlaced for output.

0 | Frames are progressive content.
1 | Frames are actually the separated fields of an interlaced stream. Specify tff or provide the `_Field` property in all the frames.
2 | Automatic detection, depends on the `_FieldBased` frame property. If not found, the frame is considered progressive.

tff, tffd

When processing interlaced content, specifies the field parity. tffd overrides tff for output.

0 | Bottom field first (BFF). This means all even fields are top, and all odd fields are bottom.
1 | Top field first (TFF). This means all even fields are bottom, and all odd fields are top.
2 | Automatic detection, depends on the `_Field` frame property. If not found, the frame is considered progressive.

flt

Flag to force floating point operations. When set to False, integer operations are used, but only if both input and output formats are integer. If it’s not the case, floating point operations are silently used as fallback.

cpuopt

Limits the CPU instruction set. −1: automatic (no limitation), 0: default instruction set only (depends on the compilation settings), 1: limit to SSE2, 10: limit to AVX2.

### transfer

    fmtc.transfer (
    	clip       : clip        ;
    	transs     : data[] : opt;
    	transd     : data[] : opt;
    	cont       : float  : opt;
    	gcor       : float  : opt;
    	bits       : int    : opt;
    	flt        : int    : opt;
    	fulls      : int    : opt; (True)
    	fulld      : int    : opt; (True)
    	cpuopt     : int    : opt; (-1)
    	blacklvl   : float  : opt; (0)
    )

Applies electro-optical and opto-electrical transfer characteristics to the video signal to convert between linear and gamma-corrected modes.

The function offers four conversions in a row; all are optional:

- an electro-optical transfer converting the signal to linear,
- a contrast adjustement,
- a gamma correction operating on the linear signal,
- and an opto-electrical transfer to encode the signal back to a non-linear domain.

As input, the function accepts only RGB and grayscale colorspaces.

As output, the data type can be changed while the colorspace is kept. Only 16-bit integer and 32-bit float are supported. Use `bitdepth` to properly convert the output to a lower bitdepth.

The signal is clipped depending on the transfer specification or the domain requirement of the functions.

#### Parameters

clip

The input clip. Supported input formats:

- 8- to 16-bit integer.
- 32-bit floating point.
- RGB or grayscale.

transs, transd

Transfer characteristics for input and output, respectively. The characteristic is direct or inverted according to where it is applied (output or input). The curve set is the same as in ISO/IEC 23008-2 (HEVC), with a few additions.

Most curves map their value from the 0–1 range to 0–1, but some are for high dynamic range or wide gamut signals and locate their value for peak white much higher.

Value | Linear range | Description
--- | --- | ---
`"709"` | 0…1 | ITU-R BT.709
`"470m"` | 0…1 | ITU-R BT.470-6 System M, FCC (assumed display gamma 2.2) Actually uses the same curve as IEC 61966-2-1.
`"470bg"` | 0…1 | ITU-R BT.470-6 System B, G (assumed display gamma 2.8)
`"601"` | 0…1 | ITU-R BT.601
`"240"` | 0…1 | SMPTE 240M
`"linear" ""` | Unspecified | Linear (bypass)
`"log100"` | 0…1 | Logarithmic transfer characteristic (100:1 range)
`"log316"` | 0…1 | Logarithmic transfer characteristic (100*Sqrt(10):1 range)
`"61966-2-4"` | Unspecified | IEC 61966-2-4, xvYCC. Same as BT.709, but with an extended range, inlcuding negative values.
`"1361"` | −0.25…1.33 | ITU-R BT.1361 extended colour gamut system
`"61966-2-1" "srgb" "sycc"` | 0…1 | IEC 61966-2-1, sRGB or sYCC
`"2020_10"` | 0…1 | ITU-R BT.2020 for 10-bit system
`"2020_12" "2020"` | 0…1 | ITU-R BT.2020 for 12-bit system
`"2084"` | 0…1 | SMPTE ST 2084 for 10, 12, 14 and 16-bit systems Linear 1.0 is peak white and corresponds to a display luminance level of 10 000 cd/m2.
`"428"` | 0…1 | SMPTE ST 428-1 Linear 1.0 is peak white and corresponds to a display luminance level of 48 cd/m2.
`"1886"` | 0…1 | ITU-R BT.1886
`"1886a"` | 0…1 | ITU-R BT.1886, alternative approximation
`"filmstream"` | 0…1 | Thomson FilmStream Linear 1.0 is the sensor clipping level, corresponding to 3840 on a linear 12-bit scale.
`"slog"` | 0…10 | Sony S-Log Linear 1.0 is the reference white, peak white is at 10.0.
`"logc2"` | Unspecified | Arri Log C Alexa 2.x (800 EI), linear scene exposure Peak white is 57.45 linear. The negative part of the range allows coding sensor noise.
`"logc3"` | Unspecified | Arri Log C Alexa 3.x (800 EI), linear scene exposure Peak white is 55.08 linear. The negative part of the range allows coding sensor noise.
`"canonlog"` | 0…8.00903 | Canon-Log Peak white is 8.00903 in linear scale and 1.08676 in compressed scale.

cont

Optional contrast adjustment to apply to the linear signal. This is a multiplicative value, 1 is neutral. Contrast is modified before the gamma correction. This parameter is useful to match the reference or peak white points between transfer functions which have not the same reference.

gcor

Optional gamma correction to apply to the linear signal. This is a power value, 1 is neutral. Comes after contrast adjustment.

bits

Sets the output bitdepth. Currently only 16-bit integer and 32-bit float are supported. The data type is adapted automatically if required. This parameter shouldn’t conflict with flt.

flt

Set it to 0 to convert the output to integer, or to 1 to convert to floating point data.

fulls, fulld

Indicates if the clip is full-range (True) or TV-range (False). fulls is for input, fulld for output. Reference black and white have different values depending on the range. In 8 bits, pixel values scale from 0 to 255 in full range, and 16 to 235 in TV-range (16 to 240 for the YUV chroma planes). This value has no meaning for float data.

cpuopt

Limits the CPU instruction set. −1: automatic (no limitation), 0: default instruction set only (depends on the compilation settings), 1: limit to SSE2, 10: limit to AVX2.

blacklvl

Black level value (linear range) for the electro-optical transfer function. It shifts and stretches the transfer curve in order to make the black value in gamma-encoded range match the specified level in linear range. Raising the black level is equivalent to increasing the brightness setting combined with a slight contrast reduction not to alter the white. The parameter should be ≥ 0. There is no specific unit, it’s just a value from the target linear range, generally in 0–1.

### stack16tonative, nativetostack16

    fmtc.stack16tonative (
    	clip: clip;
    )
    fmtc.nativetostack16 (
    	clip: clip;
    )

Converts between 16-bit clips and stack16 clips. A stack16 clip is a 8-bit clip containing the picture made of the most significant byte of each pixel, stacked on the top of a picture made of their least significant byte. These functions are meant to offer interoperability with Avisynth plug-ins using this format.

#### Parameters

clip

The input clip. Mandatory. Can be only 8-bit integer for `stack16tonative` and 16-bit integer for `nativetostack16`.

## IV) Troubleshooting

I’m waiting for your complaints.

## V) Changelog

r17, 2015.07.08

- `bitdepth`: added “Void and cluster” dithering method and its patsize parameter.
- `bitdepth`: added floating point implementation for the Ostromoukhov dithering
- `bitdepth`: added SSE2 optimizations for halftone modes (0, 1 and 8).
- `bitdepth`: fixed incorrect conversion from float to 8-bit integer using the “fast” modes with SSE2 instruction set.

r16, 2015.07.01

- `bitdepth`: added support for 11-bit and 14-bit integer input.
- `bitdepth`: fixed a slight plane inconsistency when dithering grey multi-plane pictures using an error diffusion algorithm.
- `matrix2020cl`: added SSE2 optimisations for the floating point path.
- `resample`: sx, sy, sw and sh parameters passed as arrays are now correctly taken into account. Thanks to mawen1250 for the bug report.
- `transfer`: added the blacklvl parameter.

r15, 2015.05.22

- `resample` and `bitdepth`: fixed a bug creating dark lines or weird patterns. Was introduced in r13 while trying to fix the buffer overflow problem. Thanks to feisty2 for spotting it.
- `resample`: fixed the non-SIMD code path, causing crashes.

r14, 2015.05.20

- `matrix`: fixed a bug introducing wrong offsets in custom matrix coefficients, thanks to mawen1250 for the report.

r13, 2015.05.18

- `matrix`: optimized the SSE2 and AVX2 paths for integer data.
- Added cpuopt to some functions, to manually limit the instruction set optimizations.
- Added build files for the unix-like systems, thanks to jackoneill.
- Fixed a buffer overflow bug in the SSE2 and AVX2 code of `bitdepth` and `resample`, thanks to jackoneill for reporting it.
- Removed the `int16tofloat` and `floattoint16` temporary functions.

r12, 2015.05.08

- `resample`: fixed a crash in the AVX2 code path, thanks to HolyWu for spotting it.

r11, 2015.05.07

- `transfer`: fixed a bug in the SSE2 code path.

r10, 2015.05.06

- fmtconv is compatible with the older Vapoursynth versions again until API 3.2 is out.
- Source code: fixed compilation problems.

r9, 2015.05.06

- Added the `transfer` function.
- `resample`: Most kernel-related parameters are now arrays, allowing to specify different values for each plane.
- `resample`: Allows horizontal and vertical values for taps and invkstap.
- `resample`: AVX2 optimizations.
- `matrix`: Tries to deduce the target colorspace from simple matrix settings, sets the new `_Matrix` frame property, AVX2 optimizations.
- `bitdepth`: SSE2 optimizations for the “fast” algorithm.

r8, 2013.11.30

- `resample`: Fixed bugs introduced in r7.
- Fixed a range conversion issue in “plane copy” modes with source and destination formats are the same.

r7, 2013.11.27

- 64-bit windows version.
- `resample`: A few optimizations for special cases.
- `resample`: fixed the coefficients used in integer resizing, whose sum was sometimes off by a few units.

r6, 2013.08.24

- `matrix`: single-plane output now works correctly.

r5, 2013.08.18

- Added 12-bit support for all the functions.
- Added `matrix2020cl` to convert between linear RGB and Y’Cb’Cr’ colorspaces using the BT.2020 constant luminance matrix.
- `matrix`: Added the BT.2020 matrix, non constant luminance mode only.
- `matrix`: Added single-plane output with the singleout parameter.
- `resample`: allows x:y:z form for specifying the colorspace subsampling css.
- `resample`: added SSE2 integer calculations for slight speed improvement. Activated by default, use flt=1 to compute everything in float (previous operating mode).

r4, 2012.12.09

- Added a documentation.
- Filters now write some frame properties when known.
- Fixed the code so it can be compiled on Linux. Thanks to Jackoneill/Nodame for testing.
- `bitdepth`: no need to specify any bitdepth or colorspace (for simple range conversions).
- `matrix`: Added SSE2 implementation for integer processing.
- `matrix`: Allows the destination bitdepth to be higher than the input (added the bits parameter).
- `matrix`: col_fam completes csp instead of replacing it.
- `resample`: Added interlacedd to specify if output is interlaced (allows simple bobbing).
- `resample`: Added tff and tffd to specify field parity.
- `resample`: Added scale, scaleh and scalev for easier magnification.
- `resample`: Added a two-digit mode to css.
- `resample`: Fixed a typo preventing to select 4:1:1 chroma subsampling.
- Added `nativetostack16`.

r3, 2012.11.23

- `bitdepth`: changed the bitdepth parameter to bits.
- `bitdepth`: added SSE2 optimizations for upconversions.
- `resample`: added interlaced resizing (interlaced parameter).
- `resample`: now sets `_ColorRange` and `_ChromaLocation` properties when known.
- `resample`: fixed the planes parameter previously interpreted as 0 (black or green screen).

r2, 2012.11.18

- `bitdepth`: implemented fast dither mode (but not in SSE2 yet).
- `bitdepth`: optimized float-to-integer path.
- `bitdepth`: faster dithering when ampo = 1 and ampn = 0.
- `matrix`: enabled the SSE path for float operations.
- `resample`: optimized paths involving float input or output.
- `resample`: fixed white/magenta screen with 8-bit input and float output.

r1, 2012.11.16

- Initial release.