Skip to content

funcs

Classes:

  • FunctionUtil

    Function util to normalize common actions and boilerplate often used in functions.

FunctionUtil

FunctionUtil(
    clip: VideoNode,
    func: FuncExceptT,
    planes: PlanesT = None,
    color_family: (
        VideoFormatT
        | HoldsVideoFormatT
        | ColorFamily
        | Iterable[VideoFormatT | HoldsVideoFormatT | ColorFamily]
        | None
    ) = None,
    bitdepth: int | range | tuple[int, int] | set[int] | None = None,
    *,
    matrix: MatrixT | None = None,
    transfer: TransferT | None = None,
    primaries: PrimariesT | None = None,
    range_in: ColorRangeT | None = None,
    chromaloc: ChromaLocationT | None = None,
    order: FieldBasedT | None = None
)

Bases: baseclass, list[int]

Function util to normalize common actions and boilerplate often used in functions.

Main use is: - Automatically dither up and down as required. - Automatically check if the input clip has variable formats, resolutions, etc. - Fully type safe and removes the need for asserts or typeguards in function code. - Handy properties for common code paths, improving code readability and writability.

Examples:

.. code-block:: python

>>> func = FunctionUtil(clip, planes=0, color_family=(vs.YUV, vs.GRAY), bitdepth=16)
>>> wclip = func.work_clip
>>> txt = wclip.text.Text("This clip has been processed!")
>>> return func.return_clip(txt)

For further examples, see: https://github.com/search?q=org%3AJaded-Encoding-Thaumaturgy+FunctionUtil

Parameters:

  • clip

    (VideoNode) –

    Clip to process.

  • func

    (FuncExceptT) –

    Function returned for custom error handling. This should only be set by VS package developers.

  • planes

    (PlanesT, default: None ) –

    Planes that get processed in the function. Default: All planes.

  • color_family

    (VideoFormatT | HoldsVideoFormatT | ColorFamily | Iterable[VideoFormatT | HoldsVideoFormatT | ColorFamily] | None, default: None ) –

    Accepted color families. If the input does not adhere to these, an exception will be raised. Default: All families.

  • bitdepth

    (int | range | tuple[int, int] | set[int] | None, default: None ) –

    The bitdepth or range of bitdepths to work with. Can be an int, range, tuple, or set. Range or tuple indicates a range of allowed bitdepths, set indicates specific allowed bitdepths. If an int is provided, set the clip's bitdepth to that value. If a range or set is provided and the work clip's bitdepth is not allowed, the work clip's bitdepth will be converted to the lowest bitdepth that is greater than or equal to the work clip's current bitdepth. return_clip automatically restores the clip to the original bitdepth. If None, use the input clip's bitdepth. Default: None.

  • matrix

    (MatrixT | None, default: None ) –

    Color Matrix to work in. Used for YUV <-> RGB conversions. Default: Get matrix from the input clip.

  • transfer

    (TransferT | None, default: None ) –

    Transfer to work in. Default: Get transfer from the input clip.

  • primaries

    (PrimariesT | None, default: None ) –

    Color primaries to work in. Default: Get primaries from the input clip.

  • range_in

    (ColorRangeT | None, default: None ) –

    Color Range to work in. Default: Get the color range from the input clip.

  • chromaloc

    (ChromaLocationT | None, default: None ) –

    Chroma location to work in. Default: Get the chroma location from the input clip.

  • order

    (FieldBasedT | None, default: None ) –

    Field order to work in. Default: Get the field order from the input clip.

Methods:

  • chroma_planes

    Get a list of all chroma planes in the normalised clip.

  • chromaloc

    Get the clip's chroma location.

  • color_range

    Get the clip's color range.

  • matrix

    Get the clip's matrix.

  • norm_clip

    Get a "normalized" clip. This means color space and bitdepth are converted if necessary.

  • norm_seq

    Normalize a value or sequence to a list mapped to the clip's planes.

  • normalize_planes

    Normalize the given sequence of planes.

  • order

    Get the clip's field order.

  • primaries

    Get the clip's primaries.

  • return_clip

    Merge back the chroma if necessary and convert the processed clip back to the original clip's format.

  • transfer

    Get the clip's transfer.

  • with_planes
  • without_planes
  • work_clip

    Get the "work clip" as specified from the input planes.

Attributes:

Source code
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
def __init__(
    self, clip: vs.VideoNode, func: FuncExceptT, planes: PlanesT = None,
    color_family: VideoFormatT | HoldsVideoFormatT | vs.ColorFamily | Iterable[
        VideoFormatT | HoldsVideoFormatT | vs.ColorFamily
    ] | None = None, bitdepth: int | range | tuple[int, int] | set[int] | None = None,
    *, matrix: MatrixT | None = None, transfer: TransferT | None = None,
    primaries: PrimariesT | None = None, range_in: ColorRangeT | None = None,
    chromaloc: ChromaLocationT | None = None, order: FieldBasedT | None = None
) -> None:
    """
    :param clip:            Clip to process.
    :param func:            Function returned for custom error handling.
                            This should only be set by VS package developers.
    :param planes:          Planes that get processed in the function. Default: All planes.
    :param color_family:    Accepted color families. If the input does not adhere to these,
                            an exception will be raised.
                            Default: All families.
    :param bitdepth:        The bitdepth or range of bitdepths to work with. Can be an int, range, tuple, or set.
                            Range or tuple indicates a range of allowed bitdepths,
                            set indicates specific allowed bitdepths.
                            If an int is provided, set the clip's bitdepth to that value.

                            If a range or set is provided and the work clip's bitdepth is not allowed,
                            the work clip's bitdepth will be converted to the lowest bitdepth that is greater than
                            or equal to the work clip's current bitdepth.

                            `return_clip` automatically restores the clip to the original bitdepth.
                            If None, use the input clip's bitdepth. Default: None.
    :param matrix:          Color Matrix to work in. Used for YUV <-> RGB conversions.
                            Default: Get matrix from the input clip.
    :param transfer:        Transfer to work in.
                            Default: Get transfer from the input clip.
    :param primaries:       Color primaries to work in.
                            Default: Get primaries from the input clip.
    :param range_in:        Color Range to work in.
                            Default: Get the color range from the input clip.
    :param chromaloc:       Chroma location to work in.
                            Default: Get the chroma location from the input clip.
    :param order:           Field order to work in.
                            Default: Get the field order from the input clip.
    """
    from ..utils import get_color_family

    assert check_variable(clip, func)

    all_color_family: list[vs.ColorFamily] | None

    if color_family is not None:
        all_color_family = [get_color_family(c) for c in to_arr(color_family)]  # type: ignore[arg-type]
        if not set(all_color_family) & {vs.YUV, vs.RGB}:
            planes = 0
    else:
        all_color_family = color_family

    if isinstance(bitdepth, tuple):
        bitdepth = range(bitdepth[0], bitdepth[1] + 1)

    self.clip = clip
    self.planes = planes
    self.func = func
    self.allowed_cfamilies = all_color_family
    self.cfamily_converted = False
    self.bitdepth = bitdepth

    self._matrix = Matrix.from_param(matrix, self.func)
    self._transfer = Transfer.from_param(transfer, self.func)
    self._primaries = Primaries.from_param(primaries, self.func)
    self._range_in = ColorRange.from_param(range_in, self.func)
    self._chromaloc = ChromaLocation.from_param(chromaloc, self.func)
    self._order = FieldBased.from_param(order, self.func)

    self.norm_planes = normalize_planes(self.norm_clip, self.planes)

    super().__init__(self.norm_planes)

    self.num_planes = self.work_clip.format.num_planes

allowed_cfamilies instance-attribute

allowed_cfamilies = all_color_family

bitdepth instance-attribute

bitdepth = bitdepth

cfamily_converted instance-attribute

cfamily_converted = False

chroma property

chroma: bool

Whether any chroma planes get processed.

chroma_only property

chroma_only: bool

Whether only chroma planes get processed.

chroma_pplanes property

chroma_pplanes: list[int]

A list of which chroma planes get processed based on the work clip.

This means that if you pass [0, 1, 2] but passed a GRAY clip, it will only return [0]. Similarly, if you pass GRAY and it gets converted to RGB, this will return [0, 1, 2].

clip instance-attribute

clip = clip

func instance-attribute

func = func

is_float property

is_float: bool

Whether the clip is of a float sample type.

is_hd property

is_hd: bool

Whether the clip is of an HD resolution (>= 1280x720).

is_integer property

is_integer: bool

Whether the clip is of an integer sample type.

luma property

luma: bool

Whether the luma gets processed.

luma_only property

luma_only: bool

Whether luma is the only channel that gets processed.

norm_planes instance-attribute

norm_planes = normalize_planes(norm_clip, planes)

num_planes instance-attribute

num_planes = num_planes

planes instance-attribute

planes = planes

chroma_planes

chroma_planes() -> list[VideoNode]

Get a list of all chroma planes in the normalised clip.

Source code
181
182
183
184
185
186
187
188
@cachedproperty
def chroma_planes(self) -> list[vs.VideoNode]:
    """Get a list of all chroma planes in the normalised clip."""

    if self != [0] or self.norm_clip.format.num_planes == 1:
        return []

    return [plane(self.norm_clip, i) for i in (1, 2)]

chromaloc

chromaloc() -> ChromaLocation

Get the clip's chroma location.

Source code
214
215
216
217
218
@cachedproperty
def chromaloc(self) -> ChromaLocation:
    """Get the clip's chroma location."""

    return ChromaLocation.from_param_or_video(self._chromaloc, self.clip, True, self.func)

color_range

color_range() -> ColorRange

Get the clip's color range.

Source code
208
209
210
211
212
@cachedproperty
def color_range(self) -> ColorRange:
    """Get the clip's color range."""

    return ColorRange.from_param_or_video(self._range_in, self.clip, True, self.func)

matrix

matrix() -> Matrix

Get the clip's matrix.

Source code
190
191
192
193
194
@cachedproperty
def matrix(self) -> Matrix:
    """Get the clip's matrix."""

    return Matrix.from_param_or_video(self._matrix, self.clip, True, self.func)

norm_clip

norm_clip() -> ConstantFormatVideoNode

Get a "normalized" clip. This means color space and bitdepth are converted if necessary.

Source code
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
@cachedproperty
def norm_clip(self) -> ConstantFormatVideoNode:
    """Get a "normalized" clip. This means color space and bitdepth are converted if necessary."""

    if isinstance(self.bitdepth, (range, set)) and self.clip.format.bits_per_sample not in self.bitdepth:
        from .. import get_depth

        src_depth = get_depth(self.clip)
        target_depth = next((bits for bits in self.bitdepth if bits >= src_depth), max(self.bitdepth))

        clip = depth(self.clip, target_depth)
    elif isinstance(self.bitdepth, int):
        clip = depth(self.clip, self.bitdepth)
    else:
        clip = self.clip

    assert check_variable(clip, self.func)

    cfamily = clip.format.color_family

    if not self.allowed_cfamilies or cfamily in self.allowed_cfamilies:
        return clip

    if cfamily is vs.RGB:
        if not self._matrix:
            raise UndefinedMatrixError(
                'You must specify a matrix for RGB to {} conversions!'.format(
                    '/'.join(cf.name for cf in sorted(self.allowed_cfamilies, key=lambda x: x.name))
                ),
                self.func
            )

        self.cfamily_converted = True

        clip = clip.resize.Bicubic(format=clip.format.replace(color_family=vs.YUV).id, matrix=self._matrix)

    elif cfamily in (vs.YUV, vs.GRAY) and not set(self.allowed_cfamilies) & {vs.YUV, vs.GRAY} or self.planes not in (0, [0]):
        self.cfamily_converted = True

        clip = clip.resize.Bicubic(
            format=clip.format.replace(color_family=vs.RGB, subsampling_h=0, subsampling_w=0).id,
            matrix_in=self._matrix, chromaloc_in=self._chromaloc,
            range_in=self._range_in.value_zimg if self._range_in else None
        )

        InvalidColorspacePathError.check(self.func, clip)

    return clip

norm_seq

norm_seq(seq: T | Sequence[T], null: T) -> list[T]

Normalize a value or sequence to a list mapped to the clip's planes. Unprocessed planes will be set to the given "null" value.

Source code
320
321
322
323
324
325
326
327
328
329
def norm_seq(self, seq: T | Sequence[T], null: T) -> list[T]:
    """
    Normalize a value or sequence to a list mapped to the clip's planes.
    Unprocessed planes will be set to the given "null" value.
    """

    return [
        x if i in self else null
        for i, x in enumerate(normalize_seq(seq, self.num_planes))
    ]

normalize_planes

normalize_planes(planes: PlanesT) -> list[int]

Normalize the given sequence of planes.

Source code
279
280
281
282
def normalize_planes(self, planes: PlanesT) -> list[int]:
    """Normalize the given sequence of planes."""

    return normalize_planes(self.work_clip, planes)

order

order() -> FieldBased

Get the clip's field order.

Source code
220
221
222
223
224
@cachedproperty
def order(self) -> FieldBased:
    """Get the clip's field order."""

    return FieldBased.from_param_or_video(self._order, self.clip, True, self.func)

primaries

primaries() -> Primaries

Get the clip's primaries.

Source code
202
203
204
205
206
@cachedproperty
def primaries(self) -> Primaries:
    """Get the clip's primaries."""

    return Primaries.from_param_or_video(self._primaries, self.clip, True, self.func)

return_clip

return_clip(processed: VideoNode) -> ConstantFormatVideoNode

Merge back the chroma if necessary and convert the processed clip back to the original clip's format. If bitdepth != None, the bitdepth will also be converted if necessary.

Parameters:

  • processed

    (VideoNode) –

    The clip with all the processing applied to it.

Returns:

  • ConstantFormatVideoNode

    Processed clip converted back to the original input clip's format.

Source code
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
def return_clip(self, processed: vs.VideoNode) -> ConstantFormatVideoNode:
    """
    Merge back the chroma if necessary and convert the processed clip back to the original clip's format.
    If `bitdepth != None`, the bitdepth will also be converted if necessary.

    :param processed:       The clip with all the processing applied to it.

    :return:                Processed clip converted back to the original input clip's format.
    """

    assert check_variable(processed, self.func)

    if len(self.chroma_planes):
        processed = join([processed, *self.chroma_planes], self.norm_clip.format.color_family)

    if self.chroma_only:
        processed = join(self.norm_clip, processed)

    if self.bitdepth:
        processed = depth(processed, self.clip)

    if self.cfamily_converted:
        processed = processed.resize.Bicubic(
            format=self.clip.format.id,
            matrix=self.matrix if self.norm_clip.format.color_family is vs.RGB else None,
            chromaloc=self.chromaloc, range=self.color_range.value_zimg
        )

    return processed

transfer

transfer() -> Transfer

Get the clip's transfer.

Source code
196
197
198
199
200
@cachedproperty
def transfer(self) -> Transfer:
    """Get the clip's transfer."""

    return Transfer.from_param_or_video(self._transfer, self.clip, True, self.func)

with_planes

with_planes(planes: PlanesT) -> list[int]
Source code
284
285
def with_planes(self, planes: PlanesT) -> list[int]:
    return self.normalize_planes(sorted(set(self + self.normalize_planes(planes))))

without_planes

without_planes(planes: PlanesT) -> list[int]
Source code
287
288
def without_planes(self, planes: PlanesT) -> list[int]:
    return self.normalize_planes(sorted(set(self) - {*self.normalize_planes(planes)}))

work_clip

work_clip() -> ConstantFormatVideoNode

Get the "work clip" as specified from the input planes.

Source code
175
176
177
178
179
@cachedproperty
def work_clip(self) -> ConstantFormatVideoNode:
    """Get the "work clip" as specified from the input planes."""

    return plane(self.norm_clip, 0) if self.luma_only else self.norm_clip