Goo.Images 0.10.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package Goo.Images --version 0.10.0
                    
NuGet\Install-Package Goo.Images -Version 0.10.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Goo.Images" Version="0.10.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Goo.Images" Version="0.10.0" />
                    
Directory.Packages.props
<PackageReference Include="Goo.Images" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Goo.Images --version 0.10.0
                    
#r "nuget: Goo.Images, 0.10.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Goo.Images@0.10.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Goo.Images&version=0.10.0
                    
Install as a Cake Addin
#tool nuget:?package=Goo.Images&version=0.10.0
                    
Install as a Cake Tool

Local raster images

Prepare local PNG, JPEG, or GIF assets with ImageSourceCache before building the UI. The loader reads and decodes on a worker, then returns an immutable ImageSource:

using let images = ImageSourceCache()
using let logo = await images.LoadAsync(Path.Combine(AppContext.BaseDirectory, "Assets/logo.png"))
// Store logo in application state and use it from Cell.Build:
Image{Source: logo, Width: 64, Height: 64, Fit: ImageFit.Contain}

Copy packaged image assets to the output/publish directory using the application's ordinary content items. The loader accepts local filesystem paths, including extracted packaged assets. It does not fetch URLs. Await loading outside Cell.Build, painting, and input callbacks. For a later load, assign the result to application state on the window's owner thread and rebuild the affected Cell.

PNG grayscale, RGB, indexed, grayscale-alpha, and RGBA are supported, including their standard bit depths and Adam7 interlacing. Output is premultiplied RGBA8. JPEG supports 8-bit grayscale, RGB/YCbCr, and CMYK/YCCK baseline or progressive images (at most 64 scans); JPEG alpha is opaque. GIF87a/GIF89a loads the first image onto the logical screen, including palette transparency and interlacing. Animated GIFs are accepted as static first-frame images, at most 1024 frames; later frames are structurally checked but are neither decoded nor scheduled. The loader uses the first PNG image and ignores animation and color-profile metadata. PNG eXIf and JPEG EXIF orientation are applied, including mirrored orientations. Width, height and thumbnail bounds refer to the displayed image. Malformed or duplicate EXIF metadata is ignored. Those images stay unrotated. Color management is not performed. Pixels are treated as sRGB by rendering. Other formats throw NotSupportedException; a consumer decoder can still create ImageSource directly. Image.Path is legacy metadata: mounting a nonempty path without Source throws a message directing the caller to LoadAsync.

By default each file is limited to 16 MiB encoded, 8192 pixels per dimension, and 64 MiB decoded RGBA. An ImageDecodeLimits argument changes the limits, and a file that exceeds one throws ImageLimitException. The loader validates PNG chunk bounds/checksums and the exact decompressed scanline size before invoking the decoder, including for compressed data that expands beyond the header's dimensions. JPEG frame dimensions, segment bounds, scan count, and an end marker are checked before decoding. GIF screen/frame bounds, complete data blocks, and the first frame's exact LZW expansion are checked before decoding. It serializes decoding within each cache to bound simultaneous working buffers. Temporary decoder buffers are native memory that is additional to the decoded cache budget. The decode frees them before it returns. Only the returned pixels stay in managed memory.

The cache defaults to 64 MiB decoded and 128 unique canonical paths. Constructor arguments can change those cache limits. A full cache faults new loads with InvalidOperationException; existing entries remain available. Paths are snapshots: changing a file does not refresh a cached source. Create a new cache when assets change. Path aliases involving symlinks are not deduplicated.

Concurrent requests for a completed path share pixels and renderer identity. Each successful call returns an independently disposable owner, so callers can release results separately. Disposing the cache releases its owners and cancels queued/in-flight loads; returned sources and already-mounted leases stay valid. Keep the cache at application scope and dispose returned sources when no longer needed. The final owner/lease releases the pixels.

LoadAsync(path, cancellationToken) cancels only that caller. Cancellation is checked while waiting, reading, validating, and before publication. A native window is never needed for decoding. The decoder itself is synchronous; cancellation during that bounded step is observed when it returns. Missing files, access errors, malformed input, unsupported formats, capacity exhaustion, and cancellation are observable through the returned task. Failed or cancelled loads are not cached and may be retried.

The decoder is the pinned stb_image source in the goo-harfbuzz-gpu native library. No extra native library ships. The packaged loading smoke covers PNG, baseline/progressive/CMYK JPEG, transparent GIF, and the first frame of an animated GIF under NativeAOT; the Linux Vulkan smoke also checks rendered pixels and teardown.

HiDPI asset families

import Goo.Images

using let variants = ImageVariants([]ImageVariant{
    ImageVariant("Assets/logo.png", 1),
    ImageVariant("Assets/logo@2x.png", 2),
    ImageVariant("Assets/logo@3x.png", 3),
})
let result = await variants.LoadAsync(metrics, token)
if result.Status == ImageAssetStatus.Success {
    Image{Source: result.Source, PixelsPerUnit: result.PixelsPerUnit}
}
  • Reference the optional Goo.Images package.
  • Pass the latest Window.MetricsChanged snapshot. It includes UiScale.
  • Selection uses the smallest density at least as large as the window scale, else the largest.
  • Each variant must have the same logical size. A 128-pixel 2x source measures 64 logical units.
  • Publish Source and PixelsPerUnit together on the UI thread. Ignore late results from older requests.
  • Each result owns its Source. Dispose it when application state no longer needs it.
  • The family caches decoded pixels. Disposing the family does not invalidate returned sources or mounted leases.
Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • Goo (>= 0.10.0)

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.15.0 104 10/24/2026
0.13.0 97 10/24/2026
0.12.1 96 10/24/2026
0.12.0 96 10/23/2026
0.11.0 93 10/23/2026
0.10.0 95 10/23/2026
0.9.0 101 10/23/2026