Table of Contents

Class YuvRaster

Namespace
Egami
Assembly
Egami.dll

A picture held as separate luma (Y) and chroma (U, V) planes, plus an optional alpha plane, the way video codecs, AVIF, lossy WebP and JPEG store it. This base class is used when the sample type is not known at compile time; YuvRaster<TSample> gives the planes. Convert to and from a Raster with ToRaster(YuvConvertOptions?), CopyTo<TPixel>(Raster<TPixel>, YuvConvertOptions?, CancellationToken) and FromRaster(Raster, ChromaFormat, YuvColor, bool, YuvConvertOptions?).

public abstract class YuvRaster : IDisposable
Inheritance
YuvRaster
Implements
Derived
YuvRaster<TSample>
Inherited Members

Examples

// A 1080p frame as video stores it: full-size luma, chroma at half width and height, BT.709 at limited range.
using YuvRaster<byte> frame = YuvRaster.Create(1920, 1080, ChromaFormat.Yuv420, YuvColor.Bt709Limited);

// 10-bit HDR planes hold samples 0 to 1023 in ushorts; an alpha plane is optional.
using YuvRaster<ushort> hdr = YuvRaster.Create(3840, 2160, ChromaFormat.Yuv420, 10, YuvColor.Bt2020Limited, alpha: true);
Console.WriteLine($"Chroma planes are {frame.U!.Width}×{frame.U.Height}");

Remarks

A YUV raster is not a Raster: one pixel is spread over planes of different sizes. Operations other than Crop and Resize run on a Raster after conversion. It is not thread-safe for writing, like a raster.

Properties

BitDepth

Gets the bits per sample: 8 for byte samples; 10, 12 or 16 for ushort samples.

public int BitDepth { get; }

Property Value

int

ChromaFormat

Gets the chroma resolution against luma.

public ChromaFormat ChromaFormat { get; }

Property Value

ChromaFormat

Color

Gets how the samples turn into RGB: matrix, range and chroma siting.

public YuvColor Color { get; }

Property Value

YuvColor

HasAlpha

Gets a value indicating whether the raster has an alpha plane.

public abstract bool HasAlpha { get; }

Property Value

bool

Height

Gets the height of the luma plane in pixels.

public int Height { get; }

Property Value

int

Metadata

Gets the metadata (EXIF, ICC, XMP and the rest), carried to and from a Raster on conversion.

public RasterMetadata Metadata { get; }

Property Value

RasterMetadata

Width

Gets the width of the luma plane in pixels.

public int Width { get; }

Property Value

int

Methods

CopyFromPacked(YuvPackedFormat, ReadOnlySpan<byte>, int, ReadOnlySpan<byte>, int)

Copies a frame in an interleaved layout into this raster's planes, with one SIMD pass. The raster must match the layout: 4:2:0 8-bit for NV12 and NV21, 4:2:0 10-bit for P010, 4:2:0 at 10, 12 or 16 bits for P016, 4:2:2 8-bit for YUYV and UYVY.

public void CopyFromPacked(YuvPackedFormat format, ReadOnlySpan<byte> data, int stride = 0, ReadOnlySpan<byte> chroma = default, int chromaStride = 0)

Parameters

format YuvPackedFormat

The layout.

data ReadOnlySpan<byte>

The frame: the luma plane for two-plane layouts, or the only plane for packed 4:2:2.

stride int

The distance between rows of data, in bytes. 0 means rows are packed.

chroma ReadOnlySpan<byte>

The interleaved chroma plane of a two-plane layout, or empty when it follows the luma rows in data (at stride × Height). Ignored for YUYV and UYVY.

chromaStride int

The distance between chroma rows, in bytes. 0 means the luma stride, or the packed chroma row when an odd width makes that longer.

Examples

// An NV12 frame from Media Foundation or MediaCodec: Y rows, then interleaved U, V rows, both at the same stride.
int width = 640, height = 360, stride = 704;
byte[] nv12 = new byte[stride * height * 3 / 2];
using YuvRaster<byte> frame = YuvRaster.Create(width, height, ChromaFormat.Yuv420, YuvColor.Bt709Limited);
frame.CopyFromPacked(YuvPackedFormat.Nv12, nv12, stride);

// A webcam's YUYV, 4:2:2 in one plane, the other way.
using YuvRaster<byte> webcam = YuvRaster.Create(width, height, ChromaFormat.Yuv422, YuvColor.Bt601Limited);
byte[] yuyv = new byte[width * 2 * height];
webcam.CopyToPacked(YuvPackedFormat.Yuyv, yuyv);

Exceptions

ArgumentException

The raster does not match the layout.

ArgumentOutOfRangeException

A stride is too small or a span too short.

ObjectDisposedException

The raster has been disposed.

CopyFrom<TPixel>(Raster<TPixel>, YuvConvertOptions?, CancellationToken)

Converts the first frame of a raster of the same size into this one, with no allocation after the first call. The alpha plane, if any, takes the source's alpha (opaque for sources without). This raster's metadata is left alone.

public void CopyFrom<TPixel>(Raster<TPixel> source, YuvConvertOptions? options = null, CancellationToken cancellationToken = default) where TPixel : unmanaged, IPixelType<TPixel>

Parameters

source Raster<TPixel>

The raster to read.

options YuvConvertOptions

The chroma filters, or null for Default.

cancellationToken CancellationToken

Cancels between bands of rows.

Type Parameters

TPixel

The source's pixel type.

Examples

// A player converts every frame into the same raster: after the first frame, nothing is allocated.
using YuvRaster<byte> frame = YuvRaster.Create(1280, 720, ChromaFormat.Yuv420, YuvColor.Bt709Limited);
using Raster<Bgra8> screen = Raster.Create<Bgra8>(1280, 720);
for (int i = 0; i < 3; i++)
{
    // ... the decoder writes frame's planes ...
    frame.CopyTo(screen);
}

// And the other way, for an encoder: CopyFrom fills existing planes.
frame.CopyFrom(screen);

Exceptions

ArgumentNullException

source is null.

ArgumentException

The source is not the same size.

ObjectDisposedException

Either raster has been disposed.

OperationCanceledException

cancellationToken was canceled.

CopyToPacked(YuvPackedFormat, Span<byte>, int, Span<byte>, int)

Copies this raster's planes into a frame in an interleaved layout, with one SIMD pass. See CopyFromPacked(YuvPackedFormat, ReadOnlySpan<byte>, int, ReadOnlySpan<byte>, int) for the layouts each raster matches.

public void CopyToPacked(YuvPackedFormat format, Span<byte> data, int stride = 0, Span<byte> chroma = default, int chromaStride = 0)

Parameters

format YuvPackedFormat

The layout.

data Span<byte>

The frame: the luma plane for two-plane layouts, or the only plane for packed 4:2:2.

stride int

The distance between rows of data, in bytes. 0 means rows are packed.

chroma Span<byte>

The interleaved chroma plane of a two-plane layout, or empty to write it after the luma rows in data (at stride × Height). Ignored for YUYV and UYVY.

chromaStride int

The distance between chroma rows, in bytes. 0 means the luma stride, or the packed chroma row when an odd width makes that longer.

Exceptions

ArgumentException

The raster does not match the layout.

ArgumentOutOfRangeException

A stride is too small or a span too short.

ObjectDisposedException

The raster has been disposed.

CopyTo<TPixel>(Raster<TPixel>, YuvConvertOptions?, CancellationToken)

Converts into the first frame of an existing raster of the same size, with no allocation after the first call, so a video can reuse one raster for every frame. The target's metadata is left alone.

public void CopyTo<TPixel>(Raster<TPixel> target, YuvConvertOptions? options = null, CancellationToken cancellationToken = default) where TPixel : unmanaged, IPixelType<TPixel>

Parameters

target Raster<TPixel>

The raster to write.

options YuvConvertOptions

The chroma filters, or null for Default.

cancellationToken CancellationToken

Cancels between bands of rows.

Type Parameters

TPixel

The target's pixel type.

Examples

// A player converts every frame into the same raster: after the first frame, nothing is allocated.
using YuvRaster<byte> frame = YuvRaster.Create(1280, 720, ChromaFormat.Yuv420, YuvColor.Bt709Limited);
using Raster<Bgra8> screen = Raster.Create<Bgra8>(1280, 720);
for (int i = 0; i < 3; i++)
{
    // ... the decoder writes frame's planes ...
    frame.CopyTo(screen);
}

// And the other way, for an encoder: CopyFrom fills existing planes.
frame.CopyFrom(screen);

Exceptions

ArgumentNullException

target is null.

ArgumentException

The target is not the same size.

ObjectDisposedException

Either raster has been disposed.

OperationCanceledException

cancellationToken was canceled.

Create(int, int, ChromaFormat, YuvColor, bool, EgamiContext?)

Creates an 8-bit raster with every sample zero.

public static YuvRaster<byte> Create(int width, int height, ChromaFormat chromaFormat, YuvColor color, bool alpha = false, EgamiContext? context = null)

Parameters

width int

The luma width in pixels, at least 1.

height int

The luma height in pixels, at least 1.

chromaFormat ChromaFormat

The chroma resolution.

color YuvColor

How the samples turn into RGB.

alpha bool

Whether to add a full-size alpha plane.

context EgamiContext

The context to allocate from, or null for Default.

Returns

YuvRaster<byte>

The new raster. The caller must dispose it.

Exceptions

ArgumentOutOfRangeException

A size is less than 1, or an enum value is undefined.

LimitExceededException

The size or memory breaks the context's SafetyLimits.

Create(int, int, ChromaFormat, int, YuvColor, bool, EgamiContext?)

Creates a 10-, 12- or 16-bit raster with every sample zero.

public static YuvRaster<ushort> Create(int width, int height, ChromaFormat chromaFormat, int bitDepth, YuvColor color, bool alpha = false, EgamiContext? context = null)

Parameters

width int

The luma width in pixels, at least 1.

height int

The luma height in pixels, at least 1.

chromaFormat ChromaFormat

The chroma resolution.

bitDepth int

The bits per sample: 10, 12 or 16.

color YuvColor

How the samples turn into RGB.

alpha bool

Whether to add a full-size alpha plane.

context EgamiContext

The context to allocate from, or null for Default.

Returns

YuvRaster<ushort>

The new raster. The caller must dispose it.

Exceptions

ArgumentOutOfRangeException

A size is less than 1, the bit depth is not 10, 12 or 16, or an enum value is undefined.

LimitExceededException

The size or memory breaks the context's SafetyLimits.

Crop(Rect)

Returns a new raster holding rect of this one. The rectangle's corner must fall on a chroma sample: even x and y for 4:2:0, even x for 4:2:2, x a multiple of 4 for 4:1:1, and x and y multiples of 4 for 4:1:0. Chroma is copied exactly, with no filtering.

public YuvRaster Crop(Rect rect)

Parameters

rect Rect

The area to keep, in luma pixels.

Returns

YuvRaster

The new raster, with a copy of the metadata. The caller must dispose it.

Examples

using YuvRaster<byte> frame = YuvRaster.Create(1920, 1080, ChromaFormat.Yuv420, YuvColor.Bt709Limited);

// Scale the planes before converting, as video does; crops start on a chroma sample (even x and y at 4:2:0).
using YuvRaster<byte> small = frame.Resize(1280, 720, ResampleFilter.Bicubic);
using YuvRaster<byte> center = small.Crop(new Rect(320, 180, 640, 360));

// A player scales every frame into the same raster.
using YuvRaster<byte> screen = YuvRaster.Create(960, 540, ChromaFormat.Yuv420, YuvColor.Bt709Limited);
frame.ResizeTo(screen);

// Everything else (rotate, color adjustments, drawing) runs on a Raster after conversion.
using Raster<Rgba8> rgb = center.ToRaster<Rgba8>();
rgb.Apply(ops => ops.Rotate(90));

Exceptions

ArgumentOutOfRangeException

The rectangle is empty or reaches outside the raster.

ArgumentException

The rectangle's corner is not on a chroma sample.

ObjectDisposedException

The raster has been disposed.

Dispose()

Returns the planes' memory to its source, or disposes the owner of wrapped planes. Calling it again does nothing.

public void Dispose()

FromRaster(Raster, ChromaFormat, YuvColor, bool, YuvConvertOptions?)

Converts the first frame of a raster to a new 8-bit YUV raster. Metadata is copied.

public static YuvRaster<byte> FromRaster(Raster source, ChromaFormat chromaFormat, YuvColor color, bool alpha = false, YuvConvertOptions? options = null)

Parameters

source Raster

The raster to convert, of any pixel type.

chromaFormat ChromaFormat

The chroma resolution.

color YuvColor

The matrix, range and siting to encode with.

alpha bool

Whether to add an alpha plane, holding the source's alpha (opaque for sources without). Defaults to false: alpha is dropped.

options YuvConvertOptions

The chroma filters, or null for Default.

Returns

YuvRaster<byte>

The new raster, allocated from the source's context. The caller must dispose it.

Examples

using Raster photo = Raster.Load("duck.png");

// RGB to planes and back. RGB comes out in the picture's own transfer (BT.709 video gives BT.709-encoded RGB).
using YuvRaster<byte> yuv = YuvRaster.FromRaster(photo, ChromaFormat.Yuv420, YuvColor.Bt709Limited);
using Raster rgba = yuv.ToRaster();                        // Rgba8 for 8-bit planes, Rgba16 for more
using Raster<Rgb8> rgb = yuv.ToRaster<Rgb8>();             // or any pixel type

Exceptions

ArgumentNullException

source is null.

ObjectDisposedException

source has been disposed.

FromRaster(Raster, ChromaFormat, int, YuvColor, bool, YuvConvertOptions?)

Converts the first frame of a raster to a new 10-, 12- or 16-bit YUV raster. Metadata is copied.

public static YuvRaster<ushort> FromRaster(Raster source, ChromaFormat chromaFormat, int bitDepth, YuvColor color, bool alpha = false, YuvConvertOptions? options = null)

Parameters

source Raster

The raster to convert, of any pixel type.

chromaFormat ChromaFormat

The chroma resolution.

bitDepth int

The bits per sample: 10, 12 or 16.

color YuvColor

The matrix, range and siting to encode with.

alpha bool

Whether to add an alpha plane, holding the source's alpha (opaque for sources without). Defaults to false: alpha is dropped.

options YuvConvertOptions

The chroma filters, or null for Default.

Returns

YuvRaster<ushort>

The new raster, allocated from the source's context. The caller must dispose it.

Examples

using Raster photo = Raster.Load("duck.png");

// RGB to planes and back. RGB comes out in the picture's own transfer (BT.709 video gives BT.709-encoded RGB).
using YuvRaster<byte> yuv = YuvRaster.FromRaster(photo, ChromaFormat.Yuv420, YuvColor.Bt709Limited);
using Raster rgba = yuv.ToRaster();                        // Rgba8 for 8-bit planes, Rgba16 for more
using Raster<Rgb8> rgb = yuv.ToRaster<Rgb8>();             // or any pixel type

Exceptions

ArgumentNullException

source is null.

ArgumentOutOfRangeException

The bit depth is not 10, 12 or 16.

ObjectDisposedException

source has been disposed.

Load(Stream, EgamiContext?, ReaderOptions?)

Decodes a format's own planes, with no color conversion or chroma upsampling: for JPEG, a YCbCr file's planes at its own sampling (4:2:0, 4:2:2 or 4:4:4; other samplings are replicated up to 4:4:4) and a gray file's as 4:0:0, all Jpeg. MinimumSize decodes at a reduced scale (1/2, 1/4 or 1/8).

public static YuvRaster Load(Stream stream, EgamiContext? context = null, ReaderOptions? options = null)

Parameters

stream Stream

The encoded image. It is read from its current position and left open.

context EgamiContext

The context, or null for Default.

options ReaderOptions

How to read, or null for Default.

Returns

YuvRaster

The raster. The caller must dispose it.

Examples

// A JPEG's own planes, as decoded: no chroma upsampling and no color conversion.
YuvRasterInfo info = YuvRaster.Probe("duck.jpg");
Console.WriteLine($"{info.Info.Width}×{info.Info.Height}, planes: {info.ChromaFormat}");
using YuvRaster planes = YuvRaster.Load("duck.jpg");

// Saving JPEG-colored 8-bit planes skips color conversion and downsampling; other planes are converted first.
planes.Save("copy.jpg", new JpegWriterOptions { Quality = 90 });

Exceptions

NotSupportedException

The format, or this file (a CMYK, YCCK or RGB JPEG), has no YUV planes; Load(Stream, EgamiContext?, ReaderOptions?) converts it. Also thrown for Region and ConvertColorTo.

UnsupportedFormatException

No registered format matches the data.

CorruptDataException

The data breaks the format's rules.

LimitExceededException

The image breaks a safety limit.

ArgumentNullException

stream is null.

Load(ReadOnlyMemory<byte>, EgamiContext?, ReaderOptions?)

Loads an image's planes from bytes in memory. See Load(Stream, EgamiContext?, ReaderOptions?).

public static YuvRaster Load(ReadOnlyMemory<byte> data, EgamiContext? context = null, ReaderOptions? options = null)

Parameters

data ReadOnlyMemory<byte>

The encoded image.

context EgamiContext

The context, or null for Default.

options ReaderOptions

How to read, or null for Default.

Returns

YuvRaster

The raster. The caller must dispose it.

Examples

// A JPEG's own planes, as decoded: no chroma upsampling and no color conversion.
YuvRasterInfo info = YuvRaster.Probe("duck.jpg");
Console.WriteLine($"{info.Info.Width}×{info.Info.Height}, planes: {info.ChromaFormat}");
using YuvRaster planes = YuvRaster.Load("duck.jpg");

// Saving JPEG-colored 8-bit planes skips color conversion and downsampling; other planes are converted first.
planes.Save("copy.jpg", new JpegWriterOptions { Quality = 90 });

Exceptions

NotSupportedException

The format or file has no YUV planes.

UnsupportedFormatException

No registered format matches the data.

CorruptDataException

The data breaks the format's rules.

LimitExceededException

The image breaks a safety limit.

Load(string, EgamiContext?, ReaderOptions?)

Loads an image file's planes. See Load(Stream, EgamiContext?, ReaderOptions?).

public static YuvRaster Load(string path, EgamiContext? context = null, ReaderOptions? options = null)

Parameters

path string

The file path.

context EgamiContext

The context, or null for Default.

options ReaderOptions

How to read, or null for Default.

Returns

YuvRaster

The raster. The caller must dispose it.

Examples

// A JPEG's own planes, as decoded: no chroma upsampling and no color conversion.
YuvRasterInfo info = YuvRaster.Probe("duck.jpg");
Console.WriteLine($"{info.Info.Width}×{info.Info.Height}, planes: {info.ChromaFormat}");
using YuvRaster planes = YuvRaster.Load("duck.jpg");

// Saving JPEG-colored 8-bit planes skips color conversion and downsampling; other planes are converted first.
planes.Save("copy.jpg", new JpegWriterOptions { Quality = 90 });

Exceptions

NotSupportedException

The format or file has no YUV planes.

UnsupportedFormatException

No registered format matches the data.

CorruptDataException

The data breaks the format's rules.

LimitExceededException

The image breaks a safety limit.

FileNotFoundException

The file does not exist.

Probe(Stream, EgamiContext?, ReaderOptions?)

Reads only the header, as Probe(Stream, EgamiContext?, ReaderOptions?) does, and says whether Load(Stream, EgamiContext?, ReaderOptions?) would give planes and in what chroma format.

public static YuvRasterInfo Probe(Stream stream, EgamiContext? context = null, ReaderOptions? options = null)

Parameters

stream Stream

The encoded image.

context EgamiContext

The context, or null for Default.

options ReaderOptions

How to read, or null for Default.

Returns

YuvRasterInfo

What the header says.

Examples

// A JPEG's own planes, as decoded: no chroma upsampling and no color conversion.
YuvRasterInfo info = YuvRaster.Probe("duck.jpg");
Console.WriteLine($"{info.Info.Width}×{info.Info.Height}, planes: {info.ChromaFormat}");
using YuvRaster planes = YuvRaster.Load("duck.jpg");

// Saving JPEG-colored 8-bit planes skips color conversion and downsampling; other planes are converted first.
planes.Save("copy.jpg", new JpegWriterOptions { Quality = 90 });

Exceptions

UnsupportedFormatException

No registered format matches the data.

CorruptDataException

The header breaks the format's rules.

ArgumentNullException

stream is null.

Probe(ReadOnlyMemory<byte>, EgamiContext?, ReaderOptions?)

Reads only the header of an image in memory. See Probe(Stream, EgamiContext?, ReaderOptions?).

public static YuvRasterInfo Probe(ReadOnlyMemory<byte> data, EgamiContext? context = null, ReaderOptions? options = null)

Parameters

data ReadOnlyMemory<byte>

The encoded image.

context EgamiContext

The context, or null for Default.

options ReaderOptions

How to read, or null for Default.

Returns

YuvRasterInfo

What the header says.

Examples

// A JPEG's own planes, as decoded: no chroma upsampling and no color conversion.
YuvRasterInfo info = YuvRaster.Probe("duck.jpg");
Console.WriteLine($"{info.Info.Width}×{info.Info.Height}, planes: {info.ChromaFormat}");
using YuvRaster planes = YuvRaster.Load("duck.jpg");

// Saving JPEG-colored 8-bit planes skips color conversion and downsampling; other planes are converted first.
planes.Save("copy.jpg", new JpegWriterOptions { Quality = 90 });

Exceptions

UnsupportedFormatException

No registered format matches the data.

CorruptDataException

The header breaks the format's rules.

Probe(string, EgamiContext?, ReaderOptions?)

Reads only the header of an image file. See Probe(Stream, EgamiContext?, ReaderOptions?).

public static YuvRasterInfo Probe(string path, EgamiContext? context = null, ReaderOptions? options = null)

Parameters

path string

The file path.

context EgamiContext

The context, or null for Default.

options ReaderOptions

How to read, or null for Default.

Returns

YuvRasterInfo

What the header says.

Examples

// A JPEG's own planes, as decoded: no chroma upsampling and no color conversion.
YuvRasterInfo info = YuvRaster.Probe("duck.jpg");
Console.WriteLine($"{info.Info.Width}×{info.Info.Height}, planes: {info.ChromaFormat}");
using YuvRaster planes = YuvRaster.Load("duck.jpg");

// Saving JPEG-colored 8-bit planes skips color conversion and downsampling; other planes are converted first.
planes.Save("copy.jpg", new JpegWriterOptions { Quality = 90 });

Exceptions

UnsupportedFormatException

No registered format matches the data.

CorruptDataException

The header breaks the format's rules.

FileNotFoundException

The file does not exist.

Resize(int, int, ResampleFilter)

Returns a new raster with every plane resized by filter, as a Gray8 or Gray16 resize would, keeping the chroma format, siting and color. Samples are clamped to the bit depth, since some filters overshoot. Scaling planes before converting costs half as much at 4:2:0 as scaling RGB after.

public YuvRaster Resize(int width, int height, ResampleFilter filter = ResampleFilter.Bicubic)

Parameters

width int

The new luma width, at least 1.

height int

The new luma height, at least 1.

filter ResampleFilter

The resampling kernel. Defaults to Bicubic.

Returns

YuvRaster

The new raster, with a copy of the metadata. The caller must dispose it.

Examples

using YuvRaster<byte> frame = YuvRaster.Create(1920, 1080, ChromaFormat.Yuv420, YuvColor.Bt709Limited);

// Scale the planes before converting, as video does; crops start on a chroma sample (even x and y at 4:2:0).
using YuvRaster<byte> small = frame.Resize(1280, 720, ResampleFilter.Bicubic);
using YuvRaster<byte> center = small.Crop(new Rect(320, 180, 640, 360));

// A player scales every frame into the same raster.
using YuvRaster<byte> screen = YuvRaster.Create(960, 540, ChromaFormat.Yuv420, YuvColor.Bt709Limited);
frame.ResizeTo(screen);

// Everything else (rotate, color adjustments, drawing) runs on a Raster after conversion.
using Raster<Rgba8> rgb = center.ToRaster<Rgba8>();
rgb.Apply(ops => ops.Rotate(90));

Exceptions

ArgumentOutOfRangeException

A size is less than 1.

LimitExceededException

The new raster breaks the context's SafetyLimits.

ObjectDisposedException

The raster has been disposed.

ResizeTo(YuvRaster, ResampleFilter)

Resizes every plane into an existing raster of the size wanted, as Resize(int, int, ResampleFilter) does, so a video can scale every frame into the same raster. The target must have the same sample type, chroma format, bit depth and color. An alpha plane is resized when both have one; a target alpha plane with no source alpha is made opaque. The target's metadata is left alone.

public void ResizeTo(YuvRaster target, ResampleFilter filter = ResampleFilter.Bicubic)

Parameters

target YuvRaster

The raster to write, of any size.

filter ResampleFilter

The resampling kernel. Defaults to Bicubic.

Examples

using YuvRaster<byte> frame = YuvRaster.Create(1920, 1080, ChromaFormat.Yuv420, YuvColor.Bt709Limited);

// Scale the planes before converting, as video does; crops start on a chroma sample (even x and y at 4:2:0).
using YuvRaster<byte> small = frame.Resize(1280, 720, ResampleFilter.Bicubic);
using YuvRaster<byte> center = small.Crop(new Rect(320, 180, 640, 360));

// A player scales every frame into the same raster.
using YuvRaster<byte> screen = YuvRaster.Create(960, 540, ChromaFormat.Yuv420, YuvColor.Bt709Limited);
frame.ResizeTo(screen);

// Everything else (rotate, color adjustments, drawing) runs on a Raster after conversion.
using Raster<Rgba8> rgb = center.ToRaster<Rgba8>();
rgb.Apply(ops => ops.Rotate(90));

Exceptions

ArgumentNullException

target is null.

ArgumentException

The target is this raster, or differs in sample type, chroma format, bit depth or color.

ObjectDisposedException

Either raster has been disposed.

Save(Stream, FormatInfo, WriterOptions?)

Encodes the picture in format. JPEG encodes the planes straight, with no color conversion or chroma downsampling, when they are 8-bit BT.601 at full range (4:2:0, 4:2:2 and 4:4:4 keep their sampling, 4:0:0 is gray); other planes are converted to that first, 4:1:1 to 4:2:2 and 4:1:0 to 4:2:0. AVIF encodes planes of 8, 10 or 12 bits straight, their matrix, range and chroma siting written into the file, and alpha as an alpha item; AV1 has no 4:1:1 or 4:1:0, so those are saved from RGB. Other formats are saved from ToRaster(YuvConvertOptions?).

public void Save(Stream stream, FormatInfo format, WriterOptions? options = null)

Parameters

stream Stream

Where to write, from its current position. It is left open.

format FormatInfo

The format.

options WriterOptions

The format's options, or null for its defaults. JPEG's subsampling comes from the planes.

Examples

// A JPEG's own planes, as decoded: no chroma upsampling and no color conversion.
YuvRasterInfo info = YuvRaster.Probe("duck.jpg");
Console.WriteLine($"{info.Info.Width}×{info.Info.Height}, planes: {info.ChromaFormat}");
using YuvRaster planes = YuvRaster.Load("duck.jpg");

// Saving JPEG-colored 8-bit planes skips color conversion and downsampling; other planes are converted first.
planes.Save("copy.jpg", new JpegWriterOptions { Quality = 90 });

Exceptions

UnsupportedFormatException

The format has no writer.

ObjectDisposedException

The raster has been disposed.

ArgumentNullException

stream or format is null.

Save(Stream, string, WriterOptions?)

Encodes the picture in the registered format with this name or file extension. See Save(Stream, FormatInfo, WriterOptions?).

public void Save(Stream stream, string formatNameOrExtension, WriterOptions? options = null)

Parameters

stream Stream

Where to write, from its current position. It is left open.

formatNameOrExtension string

The format's name or one of its extensions, ignoring case.

options WriterOptions

The format's options, or null for its defaults.

Examples

// A JPEG's own planes, as decoded: no chroma upsampling and no color conversion.
YuvRasterInfo info = YuvRaster.Probe("duck.jpg");
Console.WriteLine($"{info.Info.Width}×{info.Info.Height}, planes: {info.ChromaFormat}");
using YuvRaster planes = YuvRaster.Load("duck.jpg");

// Saving JPEG-colored 8-bit planes skips color conversion and downsampling; other planes are converted first.
planes.Save("copy.jpg", new JpegWriterOptions { Quality = 90 });

Exceptions

UnsupportedFormatException

No registered format matches, or it has no writer.

ObjectDisposedException

The raster has been disposed.

Save(string, WriterOptions?)

Encodes the picture to a file, choosing the format from the extension. An existing file is replaced; if encoding fails, the partly written file is deleted. See Save(Stream, FormatInfo, WriterOptions?).

public void Save(string path, WriterOptions? options = null)

Parameters

path string

The file path.

options WriterOptions

The format's options, or null for its defaults.

Examples

// A JPEG's own planes, as decoded: no chroma upsampling and no color conversion.
YuvRasterInfo info = YuvRaster.Probe("duck.jpg");
Console.WriteLine($"{info.Info.Width}×{info.Info.Height}, planes: {info.ChromaFormat}");
using YuvRaster planes = YuvRaster.Load("duck.jpg");

// Saving JPEG-colored 8-bit planes skips color conversion and downsampling; other planes are converted first.
planes.Save("copy.jpg", new JpegWriterOptions { Quality = 90 });

Exceptions

UnsupportedFormatException

No registered format uses the extension, or it has no writer.

ObjectDisposedException

The raster has been disposed.

IOException

The file cannot be written.

ToRaster(YuvConvertOptions?)

Converts to a new raster in the natural pixel type: Rgba8 for 8-bit samples, Rgba16 for more. RGB comes out in the picture's own transfer function; nothing is linearized or tone mapped.

public Raster ToRaster(YuvConvertOptions? options = null)

Parameters

options YuvConvertOptions

The chroma filters, or null for Default.

Returns

Raster

The new raster, with a copy of the metadata. The caller must dispose it.

Examples

using Raster photo = Raster.Load("duck.png");

// RGB to planes and back. RGB comes out in the picture's own transfer (BT.709 video gives BT.709-encoded RGB).
using YuvRaster<byte> yuv = YuvRaster.FromRaster(photo, ChromaFormat.Yuv420, YuvColor.Bt709Limited);
using Raster rgba = yuv.ToRaster();                        // Rgba8 for 8-bit planes, Rgba16 for more
using Raster<Rgb8> rgb = yuv.ToRaster<Rgb8>();             // or any pixel type

Exceptions

ObjectDisposedException

The raster has been disposed.

ToRaster<TPixel>(YuvConvertOptions?)

Converts to a new raster of TPixel. See ToRaster(YuvConvertOptions?).

public Raster<TPixel> ToRaster<TPixel>(YuvConvertOptions? options = null) where TPixel : unmanaged, IPixelType<TPixel>

Parameters

options YuvConvertOptions

The chroma filters, or null for Default.

Returns

Raster<TPixel>

The new raster, with a copy of the metadata. The caller must dispose it.

Type Parameters

TPixel

The pixel type.

Examples

using Raster photo = Raster.Load("duck.png");

// RGB to planes and back. RGB comes out in the picture's own transfer (BT.709 video gives BT.709-encoded RGB).
using YuvRaster<byte> yuv = YuvRaster.FromRaster(photo, ChromaFormat.Yuv420, YuvColor.Bt709Limited);
using Raster rgba = yuv.ToRaster();                        // Rgba8 for 8-bit planes, Rgba16 for more
using Raster<Rgb8> rgb = yuv.ToRaster<Rgb8>();             // or any pixel type

Exceptions

ObjectDisposedException

The raster has been disposed.

LimitExceededException

The new raster breaks the context's MaxTotalBytes.

Wrap<TSample>(Memory<TSample>, int, Memory<TSample>, int, Memory<TSample>, int, int, int, ChromaFormat, int, YuvColor, IDisposable?, EgamiContext?)

Creates a raster over planes the caller owns, such as a decoder's or the operating system's frame buffers, without copying. When owner is given, disposing the raster disposes it; otherwise the caller keeps the memory alive while the raster is used. Sizes and strides are checked up front; SafetyLimits do not apply to wrapped memory.

public static YuvRaster<TSample> Wrap<TSample>(Memory<TSample> y, int yStride, Memory<TSample> u, int uStride, Memory<TSample> v, int vStride, int width, int height, ChromaFormat chromaFormat, int bitDepth, YuvColor color, IDisposable? owner = null, EgamiContext? context = null) where TSample : unmanaged

Parameters

y Memory<TSample>

The luma plane.

yStride int

The distance between luma rows, in samples. 0 means rows are packed.

u Memory<TSample>

The U (Cb) plane, or empty for 4:0:0.

uStride int

The distance between U rows, in samples. 0 means rows are packed.

v Memory<TSample>

The V (Cr) plane, or empty for 4:0:0.

vStride int

The distance between V rows, in samples. 0 means rows are packed.

width int

The luma width in pixels, at least 1.

height int

The luma height in pixels, at least 1.

chromaFormat ChromaFormat

The chroma resolution.

bitDepth int

The bits per sample: 8 for bytes; 10, 12 or 16 for ushort.

color YuvColor

How the samples turn into RGB.

owner IDisposable

What to dispose with the raster, or null.

context EgamiContext

The context for later allocations, or null for Default.

Returns

YuvRaster<TSample>

The raster.

Type Parameters

TSample

byte for 8 bits, ushort for 10, 12 and 16 bits.

Examples

// A decoder's 10-bit frame, rows padded to 64 samples: wrapped without a copy. Disposing the raster disposes the owner.
int width = 50, height = 30, stride = 64, chromaStride = 32;
ushort[] y = new ushort[stride * height], u = new ushort[chromaStride * 15], v = new ushort[chromaStride * 15];
using YuvRaster<ushort> wrapped = YuvRaster.Wrap<ushort>(
    y, stride, u, chromaStride, v, chromaStride, width, height, ChromaFormat.Yuv420, bitDepth: 10, YuvColor.Bt2020Limited, owner: null);

Exceptions

ArgumentOutOfRangeException

A size, stride or bit depth is out of range, or a plane is too short.

ArgumentException

Chroma planes are given for 4:0:0, or missing for another format.

NotSupportedException

TSample is not byte or ushort.

Wrap<TSample>(Memory<TSample>, int, Memory<TSample>, int, Memory<TSample>, int, Memory<TSample>, int, int, int, ChromaFormat, int, YuvColor, IDisposable?, EgamiContext?)

public static YuvRaster<TSample> Wrap<TSample>(Memory<TSample> y, int yStride, Memory<TSample> u, int uStride, Memory<TSample> v, int vStride, Memory<TSample> alpha, int alphaStride, int width, int height, ChromaFormat chromaFormat, int bitDepth, YuvColor color, IDisposable? owner = null, EgamiContext? context = null) where TSample : unmanaged

Parameters

y Memory<TSample>

The luma plane.

yStride int

The distance between luma rows, in samples. 0 means rows are packed.

u Memory<TSample>

The U (Cb) plane, or empty for 4:0:0.

uStride int

The distance between U rows, in samples. 0 means rows are packed.

v Memory<TSample>

The V (Cr) plane, or empty for 4:0:0.

vStride int

The distance between V rows, in samples. 0 means rows are packed.

alpha Memory<TSample>

The full-size alpha plane, straight (not premultiplied), at the same bit depth.

alphaStride int

The distance between alpha rows, in samples. 0 means rows are packed.

width int

The luma width in pixels, at least 1.

height int

The luma height in pixels, at least 1.

chromaFormat ChromaFormat

The chroma resolution.

bitDepth int

The bits per sample: 8 for bytes; 10, 12 or 16 for ushort.

color YuvColor

How the samples turn into RGB.

owner IDisposable

What to dispose with the raster, or null.

context EgamiContext

The context for later allocations, or null for Default.

Returns

YuvRaster<TSample>

The raster.

Type Parameters

TSample

byte for 8 bits, ushort for 10, 12 and 16 bits.

Exceptions

ArgumentOutOfRangeException

A size, stride or bit depth is out of range, or a plane is too short.

ArgumentException

Chroma planes are given for 4:0:0, or missing for another format.

NotSupportedException

TSample is not byte or ushort.