Table of Contents

Class JxlImage

Namespace
Egami.Formats.Jxl
Assembly
Egami.dll

Reads what JPEG XL holds besides the image Load gives: the layers before blending, and the preview.

public static class JxlImage
Inheritance
JxlImage
Inherited Members

Examples

// An animation loads as its frames, blended onto the canvas, each with its delay.
using Raster animation = Raster.Load("sprite.jxl");
int frames = animation.FrameCount;

// The layers before blending, for an editor: each at its own size and place.
IReadOnlyList<JxlLayer> layers = JxlImage.ReadLayers("sprite.jxl");
foreach (JxlLayer layer in layers)
{
    Console.WriteLine($"{layer.Raster.Width}x{layer.Raster.Height} at {layer.X},{layer.Y}: {layer.Blend}, {layer.Duration.TotalMilliseconds} ms");
    layer.Dispose();
}

// The preview some files carry for quick display, or null.
using Raster? preview = JxlImage.ReadPreview("duck.jxl");

// A lossy still at an eighth of its size, from its LF image alone.
using Raster thumbnail = Raster.Load("duck.jxl", options: new JxlReaderOptions { MaxDownscale = 8 });

Methods

ReadExtraChannel(Stream, int, ReaderOptions?, EgamiContext?)

Reads one extra channel from a stream; see ReadExtraChannel(string, int, ReaderOptions?, EgamiContext?).

public static Raster<GrayF32> ReadExtraChannel(Stream stream, int index, ReaderOptions? options = null, EgamiContext? context = null)

Parameters

stream Stream

The file's data, from its start.

index int

The channel's index in ExtraChannels.

options ReaderOptions

The general options, with the frame range.

context EgamiContext

The context, or null for Default.

Returns

Raster<GrayF32>

The channel's samples. The caller must dispose it.

Examples

// Alpha joins the pixels (straight, even when the file premultiplies); other extra channels are listed in the details.
using Raster image = Raster.Load("sprite.jxl");
JxlDetails details = (JxlDetails)image.Metadata.FormatDetails!;
foreach (JxlExtraChannel channel in details.ExtraChannels)
{
    Console.WriteLine($"{channel.Kind} '{channel.Name}', {channel.BitsPerSample} bits");
}

// Any one of them alone, such as depth or a selection mask, as gray floats.
using Raster<GrayF32> alpha = JxlImage.ReadExtraChannel("sprite.jxl", 0);

// Spot colors are mixed into the color as djxl does, unless turned off.
using Raster plain = Raster.Load("sprite.jxl", options: new JxlReaderOptions { RenderSpotColors = false });

Exceptions

ArgumentOutOfRangeException

The image has no extra channel index.

CorruptDataException

The data breaks the format's rules, including data of another format.

ReadExtraChannel(string, int, ReaderOptions?, EgamiContext?)

Reads one extra channel, such as depth, a selection mask, thermal data or a spot color, into a gray raster at the image size: as stored, scaled to 0 to 1 for integer samples, with a frame for each frame Load shows.

public static Raster<GrayF32> ReadExtraChannel(string path, int index, ReaderOptions? options = null, EgamiContext? context = null)

Parameters

path string

The file.

index int

The channel's index in ExtraChannels.

options ReaderOptions

The general options, with the frame range.

context EgamiContext

The context, or null for Default.

Returns

Raster<GrayF32>

The channel's samples. The caller must dispose it.

Examples

// Alpha joins the pixels (straight, even when the file premultiplies); other extra channels are listed in the details.
using Raster image = Raster.Load("sprite.jxl");
JxlDetails details = (JxlDetails)image.Metadata.FormatDetails!;
foreach (JxlExtraChannel channel in details.ExtraChannels)
{
    Console.WriteLine($"{channel.Kind} '{channel.Name}', {channel.BitsPerSample} bits");
}

// Any one of them alone, such as depth or a selection mask, as gray floats.
using Raster<GrayF32> alpha = JxlImage.ReadExtraChannel("sprite.jxl", 0);

// Spot colors are mixed into the color as djxl does, unless turned off.
using Raster plain = Raster.Load("sprite.jxl", options: new JxlReaderOptions { RenderSpotColors = false });

Exceptions

ArgumentOutOfRangeException

The image has no extra channel index.

CorruptDataException

The data breaks the format's rules, including data of another format.

ReadLayers(Stream, ReaderOptions?, EgamiContext?)

Reads every regular frame before blending from a stream; see ReadLayers(string, ReaderOptions?, EgamiContext?).

public static IReadOnlyList<JxlLayer> ReadLayers(Stream stream, ReaderOptions? options = null, EgamiContext? context = null)

Parameters

stream Stream

The file's data, from its start.

options ReaderOptions

The general options; the frame range is ignored.

context EgamiContext

The context, or null for Default.

Returns

IReadOnlyList<JxlLayer>

The layers, in the file's order. The caller must dispose each.

Examples

// An animation loads as its frames, blended onto the canvas, each with its delay.
using Raster animation = Raster.Load("sprite.jxl");
int frames = animation.FrameCount;

// The layers before blending, for an editor: each at its own size and place.
IReadOnlyList<JxlLayer> layers = JxlImage.ReadLayers("sprite.jxl");
foreach (JxlLayer layer in layers)
{
    Console.WriteLine($"{layer.Raster.Width}x{layer.Raster.Height} at {layer.X},{layer.Y}: {layer.Blend}, {layer.Duration.TotalMilliseconds} ms");
    layer.Dispose();
}

// The preview some files carry for quick display, or null.
using Raster? preview = JxlImage.ReadPreview("duck.jxl");

// A lossy still at an eighth of its size, from its LF image alone.
using Raster thumbnail = Raster.Load("duck.jxl", options: new JxlReaderOptions { MaxDownscale = 8 });

Exceptions

CorruptDataException

The data breaks the format's rules, including data of another format.

ReadLayers(string, ReaderOptions?, EgamiContext?)

Reads every regular frame as it is before blending, for editors: each in the file's color space and natural pixel type, at its own size, with where it goes on the canvas and how it blends. Load gives the frames already blended.

public static IReadOnlyList<JxlLayer> ReadLayers(string path, ReaderOptions? options = null, EgamiContext? context = null)

Parameters

path string

The file.

options ReaderOptions

The general options; the frame range is ignored.

context EgamiContext

The context, or null for Default.

Returns

IReadOnlyList<JxlLayer>

The layers, in the file's order. The caller must dispose each.

Examples

// An animation loads as its frames, blended onto the canvas, each with its delay.
using Raster animation = Raster.Load("sprite.jxl");
int frames = animation.FrameCount;

// The layers before blending, for an editor: each at its own size and place.
IReadOnlyList<JxlLayer> layers = JxlImage.ReadLayers("sprite.jxl");
foreach (JxlLayer layer in layers)
{
    Console.WriteLine($"{layer.Raster.Width}x{layer.Raster.Height} at {layer.X},{layer.Y}: {layer.Blend}, {layer.Duration.TotalMilliseconds} ms");
    layer.Dispose();
}

// The preview some files carry for quick display, or null.
using Raster? preview = JxlImage.ReadPreview("duck.jxl");

// A lossy still at an eighth of its size, from its LF image alone.
using Raster thumbnail = Raster.Load("duck.jxl", options: new JxlReaderOptions { MaxDownscale = 8 });

Exceptions

CorruptDataException

The data breaks the format's rules, including data of another format.

ReadPreview(Stream, ReaderOptions?, EgamiContext?)

Reads the preview from a stream; see ReadPreview(string, ReaderOptions?, EgamiContext?).

public static Raster? ReadPreview(Stream stream, ReaderOptions? options = null, EgamiContext? context = null)

Parameters

stream Stream

The file's data, from its start.

options ReaderOptions

The general options; the frame range is ignored.

context EgamiContext

The context, or null for Default.

Returns

Raster

The preview, or null when the file has none. The caller must dispose it.

Examples

// An animation loads as its frames, blended onto the canvas, each with its delay.
using Raster animation = Raster.Load("sprite.jxl");
int frames = animation.FrameCount;

// The layers before blending, for an editor: each at its own size and place.
IReadOnlyList<JxlLayer> layers = JxlImage.ReadLayers("sprite.jxl");
foreach (JxlLayer layer in layers)
{
    Console.WriteLine($"{layer.Raster.Width}x{layer.Raster.Height} at {layer.X},{layer.Y}: {layer.Blend}, {layer.Duration.TotalMilliseconds} ms");
    layer.Dispose();
}

// The preview some files carry for quick display, or null.
using Raster? preview = JxlImage.ReadPreview("duck.jxl");

// A lossy still at an eighth of its size, from its LF image alone.
using Raster thumbnail = Raster.Load("duck.jxl", options: new JxlReaderOptions { MaxDownscale = 8 });

Exceptions

CorruptDataException

The data breaks the format's rules, including data of another format.

ReadPreview(string, ReaderOptions?, EgamiContext?)

Reads the preview: a small image some files carry for quick display, in the natural pixel type.

public static Raster? ReadPreview(string path, ReaderOptions? options = null, EgamiContext? context = null)

Parameters

path string

The file.

options ReaderOptions

The general options; the frame range is ignored.

context EgamiContext

The context, or null for Default.

Returns

Raster

The preview, or null when the file has none. The caller must dispose it.

Examples

// An animation loads as its frames, blended onto the canvas, each with its delay.
using Raster animation = Raster.Load("sprite.jxl");
int frames = animation.FrameCount;

// The layers before blending, for an editor: each at its own size and place.
IReadOnlyList<JxlLayer> layers = JxlImage.ReadLayers("sprite.jxl");
foreach (JxlLayer layer in layers)
{
    Console.WriteLine($"{layer.Raster.Width}x{layer.Raster.Height} at {layer.X},{layer.Y}: {layer.Blend}, {layer.Duration.TotalMilliseconds} ms");
    layer.Dispose();
}

// The preview some files carry for quick display, or null.
using Raster? preview = JxlImage.ReadPreview("duck.jxl");

// A lossy still at an eighth of its size, from its LF image alone.
using Raster thumbnail = Raster.Load("duck.jxl", options: new JxlReaderOptions { MaxDownscale = 8 });

Exceptions

CorruptDataException

The data breaks the format's rules, including data of another format.

RecompressJpeg(Stream, Stream, EgamiContext?)

Recompresses a JPEG from a stream; see RecompressJpeg(string, string, EgamiContext?).

public static void RecompressJpeg(Stream stream, Stream output, EgamiContext? context = null)

Parameters

stream Stream

The JPEG's data, from its start.

output Stream

Where to write the JPEG XL file.

context EgamiContext

The context, or null for Default.

Examples

// A JPEG becomes a JPEG XL file about a fifth smaller with the same pixels, and comes back byte for byte.
JxlImage.RecompressJpeg("duck.jpg", "duck.jxl");
JxlImage.ReconstructJpeg("duck.jxl", "duck-again.jpg");

Exceptions

UnsupportedFormatException

The JPEG uses something JPEG XL cannot keep.

CorruptDataException

The JPEG breaks the format's rules.

RecompressJpeg(string, string, EgamiContext?)

Recompresses a JPEG into JPEG XL without loss, about a fifth smaller (design question 8): the JPEG's quantized coefficients become the JPEG XL image, so Load shows the same pixels a JPEG decoder would, and ReconstructJpeg(string, string, EgamiContext?) gives the original file back byte for byte. The file is what cjxl makes at its default effort, with the ICC profile in the codestream and Exif and XMP in boxes.

public static void RecompressJpeg(string path, string outputPath, EgamiContext? context = null)

Parameters

path string

The JPEG file.

outputPath string

The JPEG XL file to write.

context EgamiContext

The context, or null for Default.

Examples

// A JPEG becomes a JPEG XL file about a fifth smaller with the same pixels, and comes back byte for byte.
JxlImage.RecompressJpeg("duck.jpg", "duck.jxl");
JxlImage.ReconstructJpeg("duck.jxl", "duck-again.jpg");

Exceptions

UnsupportedFormatException

The JPEG uses something JPEG XL cannot keep: arithmetic coding, 12-bit samples, CMYK or four components, or sampling other than 4:4:4, 4:2:0, 4:2:2 and 4:4:0.

CorruptDataException

The JPEG breaks the format's rules.

ReconstructJpeg(Stream, Stream, EgamiContext?)

Writes the original JPEG of a recompressed JPEG XL file to a stream; see ReconstructJpeg(string, string, EgamiContext?).

public static void ReconstructJpeg(Stream stream, Stream output, EgamiContext? context = null)

Parameters

stream Stream

The JPEG XL file's data, from its start.

output Stream

Where to write the JPEG.

context EgamiContext

The context, or null for Default.

Examples

// A JPEG recompressed into JPEG XL loads as pixels like any other file, and gives its JPEG back byte for byte.
using Raster image = Raster.Load("recompressed.jxl");
if (((JxlDetails)image.Metadata.FormatDetails!).HasJpegReconstruction)
{
    JxlImage.ReconstructJpeg("recompressed.jxl", "original.jpg");
}

Exceptions

UnsupportedFormatException

The file has no JPEG reconstruction data, or its frame is not one Egami can rebuild a JPEG from.

CorruptDataException

The data breaks the format's rules, including data of another format.

ReconstructJpeg(string, string, EgamiContext?)

Writes the JPEG a JPEG XL file was losslessly recompressed from, byte for byte (design question 8). Load decodes such a file to pixels like any other; this gives the original JPEG back instead, when HasJpegReconstruction.

public static void ReconstructJpeg(string path, string outputPath, EgamiContext? context = null)

Parameters

path string

The JPEG XL file.

outputPath string

The JPEG file to write.

context EgamiContext

The context, or null for Default.

Examples

// A JPEG recompressed into JPEG XL loads as pixels like any other file, and gives its JPEG back byte for byte.
using Raster image = Raster.Load("recompressed.jxl");
if (((JxlDetails)image.Metadata.FormatDetails!).HasJpegReconstruction)
{
    JxlImage.ReconstructJpeg("recompressed.jxl", "original.jpg");
}

Exceptions

UnsupportedFormatException

The file has no JPEG reconstruction data, or its frame is not one Egami can rebuild a JPEG from.

CorruptDataException

The data breaks the format's rules, including data of another format.

WriteLayers(Stream, int, int, IReadOnlyList<JxlLayer>, JxlWriterOptions?, EgamiContext?)

public static void WriteLayers(Stream stream, int width, int height, IReadOnlyList<JxlLayer> layers, JxlWriterOptions? options = null, EgamiContext? context = null)

Parameters

stream Stream

Where to write the file.

width int

The canvas width.

height int

The canvas height.

layers IReadOnlyList<JxlLayer>

The layers, bottom first.

options JxlWriterOptions

The options, or null for lossless at the default effort.

context EgamiContext

The context, or null for Default.

Examples

// Layers for an editor: each at its own place, blended onto the ones below, and named. ReadLayers gives them back.
using Raster<Rgba8> photo = Raster.Load<Rgba8>("duck.png");
Raster<Rgba8> badge = Raster.Create<Rgba8>(120, 60, new Rgba8(255, 200, 0, 160));
List<JxlLayer> layers =
[
    new(photo.As<Rgba8>(), name: "photo"),
    new(badge, x: -20, y: 30, blend: JxlLayerBlend.Blend, name: "badge"),
];
JxlImage.WriteLayers("layered.jxl", photo.Width, photo.Height, layers);
foreach (JxlLayer layer in layers)
{
    layer.Dispose();
}

// Load gives them blended; ReadLayers as they were written.
using Raster flat = Raster.Load("layered.jxl");
IReadOnlyList<JxlLayer> read = JxlImage.ReadLayers("layered.jxl");

Exceptions

ArgumentNullException

stream or layers is null, or holds null.

ArgumentOutOfRangeException

width or height is not positive, or above 2³⁰.

ArgumentException

layers is empty, or a layer lasts longer than 2³² − 1 ms.

WriteLayers(string, int, int, IReadOnlyList<JxlLayer>, JxlWriterOptions?, EgamiContext?)

Writes layers as one frame each, so that ReadLayers(string, ReaderOptions?, EgamiContext?) gives them back with their place, blend mode, duration and name, and Load gives them blended. Each layer blends onto the canvas made by the ones before it, the first onto a transparent black canvas. All layers take the first one's pixel format (gray or color, and its sample type) and, when any layer has alpha, alpha; others are converted. The file is lossless unless options sets Lossless to false or a Distance, and animated when any layer has a duration.

public static void WriteLayers(string path, int width, int height, IReadOnlyList<JxlLayer> layers, JxlWriterOptions? options = null, EgamiContext? context = null)

Parameters

path string

The file to write.

width int

The canvas width.

height int

The canvas height.

layers IReadOnlyList<JxlLayer>

The layers, bottom first.

options JxlWriterOptions

The options, or null for lossless at the default effort; FirstFrameOnly is ignored.

context EgamiContext

The context, or null for Default.

Examples

// Layers for an editor: each at its own place, blended onto the ones below, and named. ReadLayers gives them back.
using Raster<Rgba8> photo = Raster.Load<Rgba8>("duck.png");
Raster<Rgba8> badge = Raster.Create<Rgba8>(120, 60, new Rgba8(255, 200, 0, 160));
List<JxlLayer> layers =
[
    new(photo.As<Rgba8>(), name: "photo"),
    new(badge, x: -20, y: 30, blend: JxlLayerBlend.Blend, name: "badge"),
];
JxlImage.WriteLayers("layered.jxl", photo.Width, photo.Height, layers);
foreach (JxlLayer layer in layers)
{
    layer.Dispose();
}

// Load gives them blended; ReadLayers as they were written.
using Raster flat = Raster.Load("layered.jxl");
IReadOnlyList<JxlLayer> read = JxlImage.ReadLayers("layered.jxl");

Exceptions

ArgumentNullException

path or layers is null, or holds null.

ArgumentOutOfRangeException

width or height is not positive, or above 2³⁰.

ArgumentException

layers is empty, or a layer lasts longer than 2³² − 1 ms.