ultrahdr_core/lib.rs
1//! Core gain map math for Ultra HDR.
2//!
3//! This crate provides the pure computational components for Ultra HDR:
4//! - Pixel math for applying/computing gain maps
5//! - Tone mapping (HDR → SDR)
6//! - Color space conversions and transfer functions
7//!
8//! JPEG-container metadata (MPF, XMP, ISO 21496-1 APP2 envelope) previously
9//! lived here in `ultrahdr_core::metadata`; it has moved to
10//! `zenjpeg::container` (JPEG-specific parsing) and `zencodec::gainmap`
11//! (codec-agnostic payload). See issue #8.
12//!
13//! This crate has **no JPEG codec dependency**. For full Ultra HDR encode/decode,
14//! use the `ultrahdr` crate which provides codec integration.
15//!
16//! # no_std Support
17//!
18//! This crate is `no_std` compatible with alloc. Disable default features:
19//! ```toml
20//! ultrahdr-core = { version = "0.1", default-features = false }
21//! ```
22//!
23//! # Cooperative Cancellation
24//!
25//! Long-running operations accept an `impl Stop` parameter from the `enough` crate
26//! for cooperative cancellation. Use `Unstoppable` when cancellation is not needed.
27//!
28//! # Example — compute a gain map from an HDR/SDR pair
29//!
30//! ```
31//! use ultrahdr_core::{
32//! ColorPrimaries, TransferFunction, PixelFormat, new_pixel_buffer, Unstoppable,
33//! gainmap::{apply_gainmap, compute_gainmap, GainMapConfig, HdrOutputFormat},
34//! };
35//!
36//! // Minimal 8x8 matching HDR + SDR surfaces. In practice these come from
37//! // your image decoder — this example just shows the call shape.
38//! let hdr = new_pixel_buffer(
39//! 8, 8, PixelFormat::Rgba8, ColorPrimaries::Bt709, TransferFunction::Srgb,
40//! )?;
41//! let sdr = new_pixel_buffer(
42//! 8, 8, PixelFormat::Rgba8, ColorPrimaries::Bt709, TransferFunction::Srgb,
43//! )?;
44//!
45//! // Derive gain map + metadata.
46//! let config = GainMapConfig::default();
47//! let (gainmap, metadata) = compute_gainmap(&hdr, &sdr, &config, Unstoppable)?;
48//!
49//! // For XMP / ISO 21496-1 APP2 serialization, use `zenjpeg::container::xmp`
50//! // and `zencodec::gainmap`.
51//!
52//! // Reconstruct HDR at 4× boost.
53//! let _hdr_out = apply_gainmap(
54//! &sdr, &gainmap, &metadata,
55//! 4.0, HdrOutputFormat::LinearFloat, Unstoppable,
56//! )?;
57//! # Ok::<(), ultrahdr_core::Error>(())
58//! ```
59
60#![cfg_attr(not(feature = "std"), no_std)]
61#![forbid(unsafe_code)]
62#![warn(missing_docs)]
63#![warn(clippy::all)]
64
65extern crate alloc;
66
67pub mod color;
68pub mod gainmap;
69mod types;
70
71// Re-export core types (local)
72pub use types::{
73 ColorPrimaries, Error, GainMap, GainMapEncodingFormat, PixelBuffer, PixelFormat, PixelSlice,
74 PixelSliceMut, Result, TransferFunction, clone_pixel_buffer, descriptor_for, luminance,
75 new_pixel_buffer, pixel_buffer_from_vec, require_supported_format, validate_gainmap_metadata,
76 validate_ultrahdr_dimensions, validate_ultrahdr_image, validate_ultrahdr_slice,
77};
78
79// Re-export from zencodec (canonical gain map metadata types)
80pub use types::{Fraction, GainMapChannel, GainMapMetadata, Iso21496Format, UnsignedFraction};
81pub use zencodec::GainMapParams;
82pub use zencodec::gainmap::{parse_iso21496_fmt, serialize_iso21496_fmt};
83
84// Re-export enough for convenience
85pub use enough::{Stop, StopReason, Unstoppable};
86
87// Re-export gain map types
88pub use gainmap::{apply::HdrOutputFormat, compute::GainMapConfig, compute::compute_gain_row};
89
90// Splitter API lives in zentone — re-export at crate root for back-compat
91// with `ultrahdr_core::LumaToneMap` etc. Gated behind the `tonemap` feature
92// (default-on) so decoder-only consumers can build without pulling in zentone.
93#[cfg(feature = "tonemap")]
94pub use zentone::{
95 Bt2408Yrgb, ExtendedReinhardLuma, HableFilmic, LumaFn, LumaGainMapSplitter, LumaToneMap,
96 SplitConfig, SplitStats,
97};
98
99/// Safety limits for parsing and allocation.
100pub mod limits {
101 /// Maximum XMP string length to parse (16 MB).
102 pub const MAX_XMP_LENGTH: usize = 16 * 1024 * 1024;
103
104 /// Maximum image dimension (width or height).
105 pub const MAX_IMAGE_DIMENSION: u32 = 65535;
106
107 /// Maximum total pixels (width * height).
108 pub const MAX_TOTAL_PIXELS: u64 = 500_000_000; // 500 megapixels
109
110 /// Maximum gain map metadata array length.
111 pub const MAX_METADATA_ARRAY_LENGTH: usize = 1024;
112}