madam.raw module

Raw camera image processor using rawpy (LibRaw).

The optional raw dependency group must be installed:

uv sync --extra raw
class madam.raw.RawImageProcessor(config: Mapping[str, Any] | None = None)[source]

Bases: Processor

Represents a processor that handles raw camera image formats (DNG, CR2, NEF, ARW, and any other format supported by LibRaw).

Reading and decoding require the rawpy package, which is a Python binding for LibRaw. Pillow is used to encode the decoded image into the requested output format.

Install the optional raw extra to get both dependencies:

pip install madam[raw]

Added in version 0.24.

__init__(config: Mapping[str, Any] | None = None) None[source]

Initializes a new RawImageProcessor.

Parameters:

config – Mapping with settings.

can_read(file: IO) bool[source]

Returns whether the specified MIME type is supported by this processor.

Parameters:

file (IO) – file-like object to be tested

Returns:

whether the data format of the specified file is supported or not

Return type:

bool

decode(asset: Asset, mime_type: str = 'image/png') Asset[source]

Demosaics a raw camera image and returns the result as a standard raster image asset.

Demosaicing is performed with LibRaw using automatic white balance. The result is encoded into the format specified by mime_type.

Parameters:
  • asset (Asset) – Raw image asset to demosaic

  • mime_type (str) – MIME type of the output image ('image/png', 'image/jpeg', or 'image/tiff')

Returns:

Decoded raster image asset

Return type:

Asset

Raises:

OperatorError – if mime_type is not supported

execute_run(steps: list[Callable], asset_or_context: Asset | ProcessingContext) Asset | ProcessingContext

Execute a grouped run of consecutive operators from this processor.

The default implementation applies each step sequentially, equivalent to the old per-step behaviour. Subclasses may override this to defer encoding: accumulate each operator’s effect into a ProcessingContext and return it; Pipeline will call ProcessingContext.materialize() at the next processor boundary or at the end of the pipeline.

Parameters:
  • steps – Ordered list of tagged operator callables in this run.

  • asset_or_context – Input asset (or live context from a preceding run of the same processor).

Returns:

Processed Asset or a live ProcessingContext.

Added in version 1.0.

read(file: IO) Asset[source]

Reads a raw camera image file and returns an Asset.

The essence contains the original raw bytes unchanged. The width and height metadata attributes reflect the full sensor dimensions before demosaicing.

Parameters:

file (IO) – Readable binary file-like object containing raw image data

Returns:

Asset with mime_type='image/x-raw', width, and height

Return type:

Asset

property supported_mime_types: frozenset

MIME types this processor can handle (used to build the Madam index).

Added in version 0.24.

class madam.raw.RawMetadataProcessor(config: Mapping[str, Any] | None = None)[source]

Bases: MetadataProcessor

Reads EXIF metadata from raw camera image files (DNG, CR2, NEF, etc.) using piexif.

Raw files embed EXIF data in their TIFF structure. This processor extracts camera make/model, shooting parameters (ISO, exposure, f-number, focal length), and capture timestamp, storing them under the 'exif' format key — the same schema used by ExifMetadataProcessor for JPEG/WebP.

Because piexif does not support inserting EXIF into TIFF/DNG files, combine() raises UnsupportedFormatError. strip() returns the file unchanged (EXIF is integral to the raw TIFF structure).

Added in version 1.0.

__init__(config: Mapping[str, Any] | None = None) None[source]

Initializes a new MetadataProcessor.

combine(file: IO, metadata: Mapping) IO[source]

Not supported — piexif cannot insert EXIF into TIFF/DNG files.

Raises:

UnsupportedFormatError – always.

property formats: frozenset

The metadata formats which are supported.

Returns:

supported metadata formats

Return type:

set[str]

read(file: IO) Mapping[str, Mapping][source]

Extract EXIF metadata from a raw camera image file.

Returns:

{'exif': {key: value, ...}} or {} if no EXIF data is found.

Raises:

UnsupportedFormatError – if file is not a TIFF-based raw image.

strip(file: IO) IO[source]

Return the file unchanged.

EXIF data is integral to the raw TIFF structure; removing it would corrupt the file for most raw processors.