ImageCollection Class

A disposable collection of images that are not animation frames: the pages of a document (TIFF, BigTIFF) or the alternative representations of a drawing (ICO, CUR). Entries may differ in size, pixel format and metadata, and are never resized or converted implicitly.

public sealed class ImageCollection : IDisposable

Remarks

This type is deliberately separate from Image, whose frames are full-canvas displayed frames of one animation with a shared size and pixel format. Nothing converts one into the other implicitly: ImageCollectionEntry.Decode extracts an entry into a normal, independently owned Image, and ImageCollection.Add copies an image into the collection.

Loading is lazy and random access. Load reads only the directory structure of the container, so describing every entry costs a few kilobytes of reads whatever the size of the file; the pixels of an entry are read when that entry is decoded, each decode with its own limits and allocation scope. A collection therefore keeps its input open until it is disposed:

  • ImageCollection.Load keeps the file open for reading until the collection is disposed.
  • ImageCollection.Load needs a seekable stream, which it keeps open (it does not own it) and seeks freely: the stream position after any call is unspecified. A non-seekable stream is rejected; read it into memory yourself if you must.
  • ImageCollection.Load copies the data once, because the collection cannot retain a span.

Loaded entries can be decoded concurrently. ImageCollectionEntry.Decode may be called from several threads at once on the entries read from the input, the same entry or different ones: a file or in-memory collection reads at an offset, and a stream collection serializes its reads of the shared stream (the decoding itself still runs in parallel). The caller must not use a stream given to ImageCollection.Load while the collection is alive. Disposing the collection while an entry is decoding waits for the read in progress; the decode then completes or throws ObjectDisposedException. Editing the collection (ImageCollection.Add, Insert, Move, RemoveAt), Save and SaveAsync (until its task completes) are not thread-safe and must not overlap any other call.

Loading is synchronous. A random-access decoder issues many small reads whose offsets depend on the bytes just read, so an asynchronous variant would either await every tag or buffer the whole file. The asynchronous Image.LoadAsync and Image.IdentifyAsync entry points do buffer the whole input for these formats, which is why a large document should be read through this type.

Implements

Properties

NameDescription
ConfigurationGets the configuration used to load the collection and to decode its entries by default.
CountGets the number of entries.
EntriesGets the entries, in container order.
FormatGets the format the collection was loaded from, or ImageFormat.Unknown for a collection created in memory.
KindGets what the entries are: document pages or alternative representations.

Configuration

ImageCollection.cs

Gets the configuration used to load the collection and to decode its entries by default.

public ImageConfiguration Configuration { get; }

Property value

ImageConfiguration

Gets the number of entries.

public int Count { get; }

Property value

int

Gets the entries, in container order.

public IReadOnlyList<ImageCollectionEntry> Entries { get; }

Property value

IReadOnlyList<ImageCollectionEntry>

Remarks

Entries are borrowed from the collection: they are valid until it is disposed or they are removed.

Gets the format the collection was loaded from, or ImageFormat.Unknown for a collection created in memory.

public ImageFormat Format { get; }

Property value

ImageFormat

Gets what the entries are: document pages or alternative representations.

public ImageCollectionKind Kind { get; }

Property value

ImageCollectionKind

Indexers

NameDescription
this[int]Gets the entry at an index.

Gets the entry at an index.

public ImageCollectionEntry this[int index] { get; }

Parameters

index int
The zero-based index.

Property value

ImageCollectionEntry

Exceptions

ArgumentOutOfRangeException
The index is outside the collection.

Methods

NameDescription
Add(Image, Point?)Appends a copy of an image as the last entry.
Create(ImageCollectionKind, ImageConfiguration?)Creates an empty collection to be filled with images and saved.
Dispose()Releases the input of a loaded collection and the images of the entries that own one. Images returned by ImageCollectionEntry.Decode are owned by their caller and are not affected.
Insert(int, Image, Point?)Inserts a copy of an image at an index.
Load(Stream, ImageConfiguration?)Opens a multi-entry image from a seekable stream, starting at its current position.
Load(ReadOnlySpan<byte>, ImageConfiguration?)Opens a multi-entry image from in-memory encoded data.
Load(string, ImageConfiguration?)Opens a multi-entry image file and describes its entries without decoding any of them.
Move(int, int)Moves an entry to another index, shifting the entries in between.
RemoveAt(int)Removes an entry. An entry that owns a copied image releases it.
Save(Stream, ImageEncoder)Encodes the collection to a stream, starting at its current position. The stream is left open.
Save(string, ImageEncoder?)Encodes the collection to a file, published atomically.
SaveAsync(Stream, ImageEncoder, CancellationToken)Asynchronously encodes the collection to a stream, starting at its current position. The stream is left open.
SaveAsync(string, ImageEncoder?, CancellationToken)Asynchronously encodes the collection to a file, with the same atomic-publication guarantees as ImageCollection.Save.
SelectBySize(Size)Selects the representation that best matches a requested size: the smallest entry at least as large as size in both directions, or, when none is large enough, the largest entry. Ties are broken by the highest stored bit depth, then by container order.

Add(Image, Point?)

ImageCollection.cs

Appends a copy of an image as the last entry.

public ImageCollectionEntry Add(Image image, Point? hotspot = null)

Parameters

image Image
The image. It is copied; the caller keeps its own image and disposes it.
hotspot Point?
The hotspot of a cursor representation, or null to use the hotspot of the frame of image (FrameMetadata.Hotspot), if it has one.

Returns

ImageCollectionEntry The new entry.

Exceptions

ArgumentException
image is animated or has a poster frame: a page or a representation is a still image.
ArgumentOutOfRangeException
hotspot is outside the image.
ObjectDisposedException
The collection or the image is disposed.

Create(ImageCollectionKind, ImageConfiguration?)

ImageCollection.cs

Creates an empty collection to be filled with images and saved.

public static ImageCollection Create(ImageCollectionKind kind, ImageConfiguration? configuration = null)

Parameters

kind ImageCollectionKind
What the entries will be: ImageCollectionKind.Pages for a document, ImageCollectionKind.Representations for an icon or a cursor.
configuration ImageConfiguration?
The configuration, or null for ImageConfiguration.Default.

Returns

ImageCollection An empty collection owned by the caller.

Exceptions

ArgumentOutOfRangeException
kind is not ImageCollectionKind.Pages or ImageCollectionKind.Representations.

Releases the input of a loaded collection and the images of the entries that own one. Images returned by ImageCollectionEntry.Decode are owned by their caller and are not affected.

public void Dispose()

Insert(int, Image, Point?)

ImageCollection.cs

Inserts a copy of an image at an index.

public ImageCollectionEntry Insert(int index, Image image, Point? hotspot = null)

Parameters

index int
The zero-based index, from 0 to ImageCollection.Count.
image Image
The image. It is copied.
hotspot Point?
The hotspot of a cursor representation, or null to use the hotspot of the frame of image (FrameMetadata.Hotspot), if it has one.

Returns

ImageCollectionEntry The new entry.

Exceptions

ArgumentOutOfRangeException
The index is outside the collection, or the hotspot is outside the image.
ArgumentException
image is animated or has a poster frame.

Load overloads

Load(Stream, ImageConfiguration?)

ImageCollection.cs

Opens a multi-entry image from a seekable stream, starting at its current position.

public static ImageCollection Load(Stream stream, ImageConfiguration? configuration = null)
Parameters
stream Stream
The readable, seekable stream. It is left open and is seeked freely: its position after any call is unspecified.
configuration ImageConfiguration?
The configuration, or null for ImageConfiguration.Default.
Returns

ImageCollection The collection, owned by the caller.

Exceptions
ArgumentException
stream is not readable, or is not seekable.
UnknownImageFormatException
The format is not recognized.
UnsupportedImageFeatureException
The format is recognized but stores a single image.
InvalidImageContentException
The structure of the data is malformed or truncated.

Load(ReadOnlySpan<byte>, ImageConfiguration?)

ImageCollection.cs

Opens a multi-entry image from in-memory encoded data.

public static ImageCollection Load(ReadOnlySpan<byte> data, ImageConfiguration? configuration = null)
Parameters
data ReadOnlySpan<byte>
The encoded data. It is copied once: the collection outlives the call and cannot retain a span.
configuration ImageConfiguration?
The configuration, or null for ImageConfiguration.Default.
Returns

ImageCollection The collection, owned by the caller.

Exceptions
UnknownImageFormatException
The format is not recognized.
UnsupportedImageFeatureException
The format is recognized but stores a single image.
InvalidImageContentException
The structure of the data is malformed or truncated.
ImageResourceLimitException
The data is longer than ImageResourceLimits.MaxEncodedBytes.

Load(string, ImageConfiguration?)

ImageCollection.cs

Opens a multi-entry image file and describes its entries without decoding any of them.

public static ImageCollection Load(string path, ImageConfiguration? configuration = null)
Parameters
path string
The path of the file. It stays open for reading until the collection is disposed.
configuration ImageConfiguration?
The configuration, or null for ImageConfiguration.Default.
Returns

ImageCollection The collection, owned by the caller.

Exceptions
ArgumentException
path is empty.
UnknownImageFormatException
The format is not recognized.
UnsupportedImageFeatureException
The format is recognized but stores a single image, or the file uses an unsupported feature.
InvalidImageContentException
The structure of the file is malformed or truncated.
ImageResourceLimitException
A configured limit is exceeded.
IOException
An I/O error occurred.

Move(int, int)

ImageCollection.cs

Moves an entry to another index, shifting the entries in between.

public void Move(int sourceIndex, int destinationIndex)

Parameters

sourceIndex int
The index of the entry to move.
destinationIndex int
The index it must have afterward.

Exceptions

ArgumentOutOfRangeException
An index is outside the collection.

RemoveAt(int)

ImageCollection.cs

Removes an entry. An entry that owns a copied image releases it.

public void RemoveAt(int index)

Parameters

index int
The zero-based index.

Exceptions

ArgumentOutOfRangeException
The index is outside the collection.

Save overloads

Save(Stream, ImageEncoder)

ImageCollection.cs

Encodes the collection to a stream, starting at its current position. The stream is left open.

public void Save(Stream stream, ImageEncoder encoder)
Parameters
stream Stream
The writable destination. TIFF output also requires a seekable stream (the directory offsets are patched once the pages are written).
encoder ImageEncoder
The encoder.
Exceptions
ArgumentException
stream is not writable, is not seekable when the output requires it, or the encoder does not produce a multi-entry format.
InvalidOperationException
The collection is empty.
UnsupportedImageFeatureException
An entry cannot be encoded without a loss the encoder settings do not allow.

Save(string, ImageEncoder?)

ImageCollection.cs

Encodes the collection to a file, published atomically.

public void Save(string path, ImageEncoder? encoder = null)
Parameters
path string
The destination path.
encoder ImageEncoder?
The encoder, or null to select it from the extension (.tif, .tiff, .ico, .cur).
Exceptions
ArgumentException
path is empty, or the extension does not select a multi-entry encoder.
InvalidOperationException
The collection is empty.
UnsupportedImageFeatureException
An entry cannot be encoded without a loss the encoder settings do not allow.
IOException
An I/O error occurred.

SaveAsync overloads

SaveAsync(Stream, ImageEncoder, CancellationToken)

ImageCollection.cs

Asynchronously encodes the collection to a stream, starting at its current position. The stream is left open.

public Task SaveAsync(Stream stream, ImageEncoder encoder, CancellationToken cancellationToken = default)
Parameters
stream Stream
The writable destination. TIFF output also requires a seekable stream (the directory offsets are patched once the pages are written).
encoder ImageEncoder
The encoder.
cancellationToken CancellationToken
The token to monitor for cancellation requests.
Returns

Task A task that completes when the collection has been written and the stream flushed.

Exceptions
ArgumentException
stream is not writable, is not seekable when the output requires it, or the encoder does not produce a multi-entry format.
InvalidOperationException
The collection is empty.
UnsupportedImageFeatureException
An entry cannot be encoded without a loss the encoder settings do not allow.
OperationCanceledException
The operation was canceled.
Remarks

The arguments, the encoder and the collection are validated before the method returns. The stream is written with Stream.WriteAsync; the entries are encoded synchronously between the writes, one entry at a time. On failure or cancellation, the bytes already written stay in the stream: its content is then not a valid file. The save must not overlap any other call on the collection until the task completes.

SaveAsync(string, ImageEncoder?, CancellationToken)

ImageCollection.cs

Asynchronously encodes the collection to a file, with the same atomic-publication guarantees as ImageCollection.Save.

public Task SaveAsync(string path, ImageEncoder? encoder = null, CancellationToken cancellationToken = default)
Parameters
path string
The destination path.
encoder ImageEncoder?
The encoder, or null to select it from the extension (.tif, .tiff, .ico, .cur).
cancellationToken CancellationToken
The token to monitor for cancellation requests. On cancellation, no file is published.
Returns

Task A task that completes when the file has been published.

Exceptions
ArgumentException
path is empty, or the extension does not select a multi-entry encoder.
InvalidOperationException
The collection is empty.
UnsupportedImageFeatureException
An entry cannot be encoded without a loss the encoder settings do not allow.
IOException
An I/O error occurred.
OperationCanceledException
The operation was canceled.
Remarks

The arguments, the encoder and the collection are validated before the method returns, as by ImageCollection.Save. The file is written with asynchronous I/O; the entries are encoded, and the entries backed by the encoded input are read and decoded, synchronously between the writes, one entry at a time. The token is checked before the file is created, before each entry, between the strips of a TIFF page and by every write. A failure or a cancellation deletes the temporary file and leaves an existing destination unchanged.

Like ImageCollection.Save, the save must not overlap any other call on the collection until the task completes.

SelectBySize(Size)

ImageCollection.cs

Selects the representation that best matches a requested size: the smallest entry at least as large as size in both directions, or, when none is large enough, the largest entry. Ties are broken by the highest stored bit depth, then by container order.

public ImageCollectionEntry SelectBySize(Size size)

Parameters

size Size
The requested size, in pixels.

Returns

ImageCollectionEntry The selected entry. Nothing is decoded or resized.

Exceptions

ArgumentOutOfRangeException
A dimension is not positive.
InvalidOperationException
The collection is empty.