Initial project import

This commit is contained in:
drjones
2026-06-13 17:36:44 -07:00
commit ad2a18cc8d
18471 changed files with 4497570 additions and 0 deletions

View File

@@ -0,0 +1,84 @@
import { GainMapMetadata } from '../core/types';
import { type CompressedImage } from '../encode/types';
/**
* Encapsulates a Gainmap into a single JPEG file (aka: JPEG-R) with the base map
* as the sdr visualization and the gainMap encoded into a MPF (Multi-Picture Format) tag.
*
* @category Encoding
* @group Encoding
*
* @example
* import { compress, encode, findTextureMinMax } from '@monogrid/gainmap-js'
* import { encodeJPEGMetadata } from '@monogrid/gainmap-js/libultrahdr'
* import { EXRLoader } from 'three/examples/jsm/loaders/EXRLoader.js'
*
* // load an HDR file
* const loader = new EXRLoader()
* const image = await loader.loadAsync('image.exr')
*
* // find RAW RGB Max value of a texture
* const textureMax = findTextureMinMax(image)
*
* // Encode the gainmap
* const encodingResult = encode({
* image,
* maxContentBoost: Math.max.apply(this, textureMax)
* })
*
* // obtain the RAW RGBA SDR buffer and create an ImageData
* const sdrImageData = new ImageData(
* encodingResult.sdr.toArray(),
* encodingResult.sdr.width,
* encodingResult.sdr.height
* )
* // obtain the RAW RGBA Gain map buffer and create an ImageData
* const gainMapImageData = new ImageData(
* encodingResult.gainMap.toArray(),
* encodingResult.gainMap.width,
* encodingResult.gainMap.height
* )
*
* // parallel compress the RAW buffers into the specified mimeType
* const mimeType = 'image/jpeg'
* const quality = 0.9
*
* const [sdr, gainMap] = await Promise.all([
* compress({
* source: sdrImageData,
* mimeType,
* quality,
* flipY: true // output needs to be flipped
* }),
* compress({
* source: gainMapImageData,
* mimeType,
* quality,
* flipY: true // output needs to be flipped
* })
* ])
*
* // obtain the metadata which will be embedded into
* // and XMP tag inside the final JPEG file
* const metadata = encodingResult.getMetadata()
*
* // embed the compressed images + metadata into a single
* // JPEG file
* const jpeg = encodeJPEGMetadata({
* ...encodingResult,
* ...metadata,
* sdr,
* gainMap
* })
*
* // `jpeg` will be an `Uint8Array` which can be saved somewhere
*
*
* @param encodingResult - Encoding result containing SDR image, gain map image, and metadata
* @returns A Uint8Array representing a JPEG-R file
* @throws {Error} If `encodingResult.sdr.mimeType !== 'image/jpeg'`
* @throws {Error} If `encodingResult.gainMap.mimeType !== 'image/jpeg'`
*/
export declare const encodeJPEGMetadata: (encodingResult: GainMapMetadata & {
sdr: CompressedImage;
gainMap: CompressedImage;
}) => Uint8Array<ArrayBuffer>;

View File

@@ -0,0 +1,41 @@
/**
* JPEG assembler for creating JPEG-R (JPEG with gain map) files
* Based on libultrahdr jpegr.cpp implementation
*/
import { GainMapMetadataExtended } from '../core/types';
import { type CompressedImage } from '../encode/types';
/**
* Options for assembling a JPEG with gain map
*/
export interface AssembleJpegOptions {
/** Primary (SDR) JPEG image */
sdr: CompressedImage;
/** Gain map JPEG image */
gainMap: CompressedImage;
/** Gain map metadata */
metadata: GainMapMetadataExtended;
/** Optional EXIF data to embed */
exif?: Uint8Array<ArrayBuffer>;
/** Optional ICC color profile */
icc?: Uint8Array<ArrayBuffer>;
}
/**
* Assemble a JPEG-R file (JPEG with embedded gain map)
*
* The structure is:
* 1. Primary image:
* - SOI
* - APP1 (EXIF if present)
* - APP1 (XMP with gain map metadata)
* - APP2 (ICC profile if present)
* - APP2 (MPF data)
* - Rest of primary JPEG data
* 2. Secondary image (gain map):
* - SOI
* - APP1 (XMP with gain map parameters)
* - Rest of gain map JPEG data
*
* @param options - Assembly options
* @returns Complete JPEG-R file as Uint8Array
*/
export declare function assembleJpegWithGainMap(options: AssembleJpegOptions): Uint8Array<ArrayBuffer>;

View File

@@ -0,0 +1,47 @@
/**
* JPEG marker constants
* Based on JPEG specification and libultrahdr implementation
*/
/**
* JPEG marker prefix - all markers start with this byte
*/
export declare const MARKER_PREFIX = 255;
/**
* JPEG markers
*/
export declare const MARKERS: {
/** Start of Image */
readonly SOI: 216;
/** End of Image */
readonly EOI: 217;
/** Application segment 0 */
readonly APP0: 224;
/** Application segment 1 (EXIF/XMP) */
readonly APP1: 225;
/** Application segment 2 (ICC/MPF) */
readonly APP2: 226;
/** Start of Scan */
readonly SOS: 218;
/** Define Quantization Table */
readonly DQT: 219;
/** Define Huffman Table */
readonly DHT: 196;
/** Start of Frame (baseline DCT) */
readonly SOF0: 192;
};
/**
* XMP namespace identifier for APP1 marker
*/
export declare const XMP_NAMESPACE = "http://ns.adobe.com/xap/1.0/\0";
/**
* EXIF identifier for APP1 marker
*/
export declare const EXIF_IDENTIFIER = "Exif\0\0";
/**
* MPF signature for APP2 marker
*/
export declare const MPF_SIGNATURE = "MPF\0";
/**
* ICC profile identifier for APP2 marker
*/
export declare const ICC_IDENTIFIER = "ICC_PROFILE\0";

View File

@@ -0,0 +1,20 @@
/**
* Multi-Picture Format (MPF) generator
* Based on CIPA DC-007 specification and libultrahdr multipictureformat.cpp
*
* MPF is used to embed multiple images in a single JPEG file
*/
/**
* Calculate the total size of the MPF structure
*/
export declare function calculateMpfSize(): number;
/**
* Generate MPF (Multi-Picture Format) data structure
*
* @param primaryImageSize - Size of the primary image in bytes
* @param primaryImageOffset - Offset of the primary image (typically 0 for FII - First Individual Image)
* @param secondaryImageSize - Size of the secondary (gain map) image in bytes
* @param secondaryImageOffset - Offset of the secondary image from the MP Endian field
* @returns Uint8Array containing the MPF data
*/
export declare function generateMpf(primaryImageSize: number, primaryImageOffset: number, secondaryImageSize: number, secondaryImageOffset: number): Uint8Array<ArrayBuffer>;

View File

@@ -0,0 +1,33 @@
/**
* XMP metadata generator for gain map images
* Based on libultrahdr jpegrutils.cpp implementation
*/
import { type GainMapMetadataExtended } from '../core/types';
/**
* Generate XMP metadata for the primary image
*
* This XMP contains:
* - Container directory with references to primary and gain map images
* - Gain map version
* - Item metadata for both images
*
* @param secondaryImageLength - Length of the secondary (gain map) JPEG in bytes
* @param metadata - Gain map metadata
* @returns XMP packet as string
*/
export declare function generateXmpForPrimaryImage(secondaryImageLength: number, metadata: GainMapMetadataExtended): string;
/**
* Generate XMP metadata for the secondary (gain map) image
*
* This XMP contains all the gain map parameters:
* - Version
* - Gain map min/max
* - Gamma
* - Offset SDR/HDR
* - HDR capacity min/max
* - Base rendition flag
*
* @param metadata - Gain map metadata
* @returns XMP packet as string
*/
export declare function generateXmpForSecondaryImage(metadata: GainMapMetadataExtended): string;