diff --git a/README.md b/README.md index b36908b5..74ddc788 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ The default CLI conversion uses metadata white balance and selects the spectral - [Installation, data setup, and v1 CLI migration](src/docs/getting_started.rst) - [Docker installation and conversion](src/docs/getting_started.rst#docker) - [CLI usage guide](src/docs/user_guide.rst) -- [C++ API guide](src/docs/api/cpp/index.rst) and [Python API guide](src/docs/api/python/index.rst) +- [API overview](src/docs/api/overview.rst), [C++ API guide](src/docs/api/cpp/index.rst), and [Python API guide](src/docs/api/python/index.rst) - [Spectral datasets and schema](https://github.com/AcademySoftwareFoundation/rawtoaces-data) - [Public headers](src/cpp/include/rawtoaces), [source](src), and [tests](tests) - [Changes](docs/CHANGES.md) and [known issues](https://github.com/AcademySoftwareFoundation/rawtoaces/issues) diff --git a/src/docs/_static/css/tables.css b/src/docs/_static/css/tables.css new file mode 100644 index 00000000..20db5794 --- /dev/null +++ b/src/docs/_static/css/tables.css @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* Copyright Contributors to the rawtoaces project. */ + +/* + * sphinx_rtd_theme keeps every table cell on one line, so a long cell sets + * the table width and the page scrolls sideways. Let cells wrap between + * words. Inline literals stay on one line. + */ + +.rst-content table.docutils thead, +.rst-content .wy-table-responsive table.docutils th, +.rst-content .wy-table-responsive table.docutils td { + white-space: normal; +} + +.rst-content .wy-table-responsive table.docutils th span.pre, +.rst-content .wy-table-responsive table.docutils td span.pre { + white-space: nowrap; +} diff --git a/src/docs/api/cpp/image_converter.rst b/src/docs/api/cpp/image_converter.rst index 835dd123..e104b545 100644 --- a/src/docs/api/cpp/image_converter.rst +++ b/src/docs/api/cpp/image_converter.rst @@ -62,3 +62,18 @@ Pixel values are multiplied by ``settings.headroom * settings.scale``. ``headroom`` is a linear factor (default ``6.0``). Doubling headroom is equivalent to adding one exposure stop. An adjustment of ``s`` stops corresponds to multiplying the factor by ``std::pow(2.0, s)``. + +OpenImageIO buffers +------------------- + +``ImageConverter`` can also run the same pipeline on OpenImageIO buffers. +``configure`` reads metadata and prepares decoding hints. ``load_image`` fills +an ``OIIO::ImageBuf``. ``process_buffer`` applies lens correction, the colour +matrix, scale, and crop; those steps are also available individually. +``save_image`` writes the ACES container. + +These C++ methods are part of ``rawtoaces_util``. The matching Python methods +require OpenImageIO 3.2 or later; see :ref:`overview-oiio-notice`. Signatures +are in the +:doc:`C++ Reference `. The :doc:`API overview <../overview>` +says when the buffer layer is the right choice. diff --git a/src/docs/api/cpp/index.rst b/src/docs/api/cpp/index.rst index 361e0aa0..6b9e05e5 100644 --- a/src/docs/api/cpp/index.rst +++ b/src/docs/api/cpp/index.rst @@ -8,8 +8,11 @@ C++ API This section contains the API documentation for the rawtoaces C++ libraries, automatically generated from the source code using Doxygen and Breathe. -Go directly to :doc:`C++ Reference ` for class and function -signatures. +Start with the :doc:`API overview <../overview>` to choose file conversion, an +OpenImageIO buffer pipeline, or a metadata or spectral solve. Go directly to +:doc:`C++ Reference ` for class and function signatures. The +matching Python buffer methods require OpenImageIO 3.2 or later +(:ref:`overview-oiio-notice`). .. toctree:: :maxdepth: 3 diff --git a/src/docs/api/overview.rst b/src/docs/api/overview.rst new file mode 100644 index 00000000..6d32a1a2 --- /dev/null +++ b/src/docs/api/overview.rst @@ -0,0 +1,221 @@ +.. + Copyright Contributors to the rawtoaces Project. + SPDX-License-Identifier: CC-BY-4.0 + +.. _api-overview: + +API Overview +============ + +Use the :doc:`user guide <../user_guide>` to convert files from the command +line. This page chooses a programming API: convert a whole RAW file, run the +OpenImageIO buffer steps yourself, or solve a transform from metadata or +spectral data. + +The table names the entry point. The sections below say what you pass in, what +comes back, which data the call needs, how failure is reported, and where the +worked example and signatures live. C++ and Python cover the same tasks where +both languages have the API. Helpers that exist only in C++ are listed at the +end. + +.. list-table:: + :header-rows: 1 + :widths: 32 34 34 + + * - Task + - Main API + - Where it is available + * - Convert a RAW file to an ACES EXR + - ``ImageConverter`` and ``Settings``, through ``process_image`` + - C++ and every Python build + * - Run the pipeline on OpenImageIO buffers + - ``configure``, ``load_image``, ``process_buffer``, ``save_image``, and the ``apply_*`` steps + - C++. Python when the extension is built with OpenImageIO 3.2 or later + * - Solve from extracted camera metadata + - ``Metadata`` and ``MetadataSolver`` + - C++ and Python + * - Solve from measured spectral data + - ``SpectralData`` and ``SpectralSolver`` + - C++ and Python + * - Generate an illuminant spectrum directly, or adapt D65 XYZ + - ``calculate_daylight_SPD``, ``calculate_blackbody_SPD``, and ``XYZD65Solver`` + - C++. Python can load the built-in named illuminants through ``SpectralSolver.find_illuminant`` + +.. _overview-oiio-notice: + +OpenImageIO 3.2 +--------------- + +Calling the buffer methods from Python requires an extension built against +OpenImageIO 3.2 or later, with ``ImageBuf``, ``ParamValueList``, and +``ImageSpec`` registered for nanobind. Importing that extension also imports +the ``OpenImageIO`` Python module. An earlier OpenImageIO build still provides +``process_image`` and ``configure(input_filename)``, and omits the buffer +methods. After a successful import, +``hasattr(rawtoaces.ImageConverter, "load_image")`` reports whether they are +present. The :ref:`capability table ` lists each +method. + +The C++ methods are members of :cpp:class:`rta::util::ImageConverter` in +``rawtoaces_util``, which links OpenImageIO. + +Convert a RAW file +------------------ + +Pass a filesystem path to :cpp:func:`rta::util::ImageConverter::process_image` +or :py:meth:`rawtoaces.ImageConverter.process_image`. Set +``ImageConverter::Settings`` first when the defaults are not the conversion you +want. ``process_image`` configures the transform from the file, decodes it, +applies lens correction (off unless requested), the colour matrix, exposure +scaling, and crop, then writes an ACES EXR. + +The output name is ``_aces.exr``. It is written beside the input, or +under ``output_dir`` when that is set. ``create_dirs`` defaults to false, so +the output directory must already exist unless you enable it. ``overwrite`` +defaults to false. Pixel values are multiplied by ``headroom * scale``; +``headroom`` is a linear factor and defaults to ``6.0``. The API crop default +is hard: only the crop region is written. The command-line crop default is +described in the :doc:`user guide <../user_guide>`. + +White balance defaults to metadata from the file. DNG is the format that +carries the calibration this method uses. A named illuminant, or the spectral matrix method, needs camera +sensitivity data. ``Auto`` selects the spectral matrix when that data is +available and otherwise uses metadata. An Adobe matrix comes from LibRaw +through OpenImageIO. A custom matrix is a complete camera RGB to ACES AP0 +matrix and is applied as given. ``database_directories`` selects the spectral +data directory; when it is empty the search uses ``RAWTOACES_DATA_PATH``, then +the legacy ``AMPAS_DATA_PATH``, then the platform default. Setup is in +:doc:`Getting Started <../getting_started>`. Lens correction is opt-in and uses +the Lensfun database; see :doc:`Lens Correction <../lens_correction>`. + +A failed call returns false. Read ``status`` and ``last_error_message``. +``status`` distinguishes a missing input, an existing output, a missing +spectral database, and a failure in configuration, reading, lens correction, +the matrix, scale, crop, or writing. + +Worked examples: +:doc:`C++ ImageConverter ` and +:doc:`Python ImageConverter `. +Signatures: +:doc:`C++ Reference ` and +:doc:`Python Reference `. +:cpp:func:`rta::util::collect_image_files` and +:py:func:`rawtoaces.collect_image_files` group file and directory arguments +into batches. :cpp:func:`rta::util::ImageConverter::make_output_path`, +``init_parser``, and ``parse_parameters`` are C++ only; Python sets +``settings`` directly. + +.. code-block:: python + + import rawtoaces + + converter = rawtoaces.ImageConverter() + if not converter.process_image("/path/to/input.dng"): + raise RuntimeError(converter.last_error_message) + +OpenImageIO buffers +------------------- + +Use this layer when the surrounding application already owns the image or +needs to run load, colour, scale, crop, and save separately. + +In C++, and in the Python overload that accepts options, pass the current +``settings`` plus either a RAW path or an ``OIIO::ImageSpec`` / +``OpenImageIO.ImageSpec`` into ``configure``. The file overload fills an +OpenImageIO parameter list with decoding hints. The ``ImageSpec`` overload uses +metadata you already have. Then pass that parameter +list to ``load_image`` to fill an ``ImageBuf``. ``process_buffer`` runs lens +correction, the matrix, scale, and crop. The same four steps are +``apply_lens_correction``, ``apply_matrix``, ``apply_scale``, and ``apply_crop``. +``save_image`` writes an ACES container; the default stored sample type is +half-float. ``get_WB_multipliers`` and ``get_transform_matrix`` are valid after +a successful ``configure``. + +Python file conversion can call ``configure(input_filename)`` in every build. +The overloads that take ``ParamValueList`` or ``ImageSpec``, and +``load_image``, ``save_image``, ``process_buffer``, and the ``apply_*`` +methods, require OpenImageIO 3.2 or later as described in +:ref:`overview-oiio-notice`. + +Each step returns false and sets ``status`` and ``last_error_message`` when it +fails. Call ``configure`` again after changing settings that affect the +transform. + +The C++ signatures are on :cpp:class:`rta::util::ImageConverter` in the +:doc:`C++ Reference `. The Python signatures are on +:py:class:`rawtoaces.ImageConverter` in the +:doc:`Python Reference `. + +Solve from camera metadata +-------------------------- + +Use :cpp:class:`rta::core::MetadataSolver` or +:py:class:`rawtoaces.MetadataSolver` when you already have DNG calibration +metadata and want the transform without decoding a file. + +Pass a :cpp:struct:`rta::core::Metadata` / :py:class:`rawtoaces.Metadata` +value: ``neutral_RGB``, ``baseline_exposure``, and two calibration sets. Each +calibration set carries an illuminant tag and an XYZ-to-camera-RGB matrix. +``calculate_transform`` returns a boolean and, on success, writes a 3×3 matrix +to ``transform_matrix``. That matrix includes chromatic adaptation and takes +camera RGB to ACES. The solver copies the metadata it is given; it does not +read a spectral database. + +A false return leaves the explanation in ``last_error_message``. Python raises +``ValueError`` when a required vector has the wrong length. + +The worked Python example is the metadata workflow in +:doc:`Core `. C++ signatures are in the +:doc:`C++ Reference `. + +Solve from spectral data +------------------------ + +Use :cpp:class:`rta::core::SpectralSolver` or +:py:class:`rawtoaces.SpectralSolver` when the transform should come from +measured spectra. + +Pass search directories to the constructor, or assign ``camera``, +``illuminant``, ``observer``, and ``training_data`` yourself. ``find_camera`` +and ``find_illuminant`` load those two from the search path. Built-in +illuminant names such as ``d55`` and ``3200k`` are generated; any other name +must exist in the data directory. Before ``calculate_transform``, the camera +needs three channels, the illuminant one, the observer three, and the training +set must be non-empty. Calculate white balance with ``calculate_WB``, or with +the three-multiplier form of ``find_illuminant``. The name form only loads the +illuminant. + +On success, ``get_WB_multipliers`` holds the RGB multipliers and +``transform_matrix`` holds the 3×3 transform. A missing camera, illuminant, +observer, or training set makes ``calculate_transform`` return false and sets +``last_error_message``. Leaving white balance unset keeps the multipliers at +``[1.0, 1.0, 1.0]`` and is not reported as an error. Python raises +``ValueError`` for an invalid argument shape. + +The dataset layout and schema are documented with the +`rawtoaces-data repository `_. +The worked Python example is the spectral workflow in +:doc:`Core `. C++ types are introduced in +:doc:`rawtoaces Core ` and +:doc:`Spectral Data `, with signatures in the +:doc:`C++ Reference `. + +C++-only helpers +---------------- + +These C++ entry points have no matching Python function. Python reaches the +built-in illuminants through ``SpectralSolver.find_illuminant`` instead of the +two spectrum generators. + +- :cpp:func:`rta::core::calculate_daylight_SPD` fills a + :cpp:struct:`rta::core::Spectrum` for daylight from 4000 K to 25000 K, or + from the short form 40–250 (55 selects D55). +- :cpp:func:`rta::core::calculate_blackbody_SPD` fills a spectrum for + 1500–3999 K. +- :cpp:class:`rta::core::XYZD65Solver` writes the fixed D65 chromatic-adaptation + and XYZ-to-ACES matrix. ``calculate_transform`` succeeds whenever it is + called. +- ``SpectralSolver::collect_aliases`` reads camera make and model aliases from + the spectral database. + +Signatures are in the :doc:`C++ Reference `. diff --git a/src/docs/api/python/image_converter.rst b/src/docs/api/python/image_converter.rst index 0ed38600..4fc2f82d 100644 --- a/src/docs/api/python/image_converter.rst +++ b/src/docs/api/python/image_converter.rst @@ -62,9 +62,9 @@ corresponds to multiplying the factor by ``2 ** s``. OpenImageIO interoperability ---------------------------- -The extension's compile-time OpenImageIO version determines whether the -lower-level image APIs are present. The reference deliberately describes a -superset; a method shown there may be absent from your installed build. +Whether these methods exist at runtime depends on the extension you import. +A method shown here may be absent from a build that predates OpenImageIO 3.2. +See :ref:`overview-oiio-notice`. .. list-table:: Python capabilities :header-rows: 1 diff --git a/src/docs/api/python/index.rst b/src/docs/api/python/index.rst index 7b9db7c9..68c6fba1 100644 --- a/src/docs/api/python/index.rst +++ b/src/docs/api/python/index.rst @@ -6,9 +6,10 @@ Python API ========== The Python bindings provide file conversion and metadata/spectral transform -solving. Start with the :doc:`image conversion guide ` or the -:doc:`core workflows `, then use the -:doc:`Python Reference ` for signatures and settings. +solving. Start with the :doc:`API overview <../overview>` to choose a layer, +then use the :doc:`image conversion guide ` or the +:doc:`core workflows `. The +:doc:`Python Reference ` lists signatures and settings. The main classes are: diff --git a/src/docs/conf.py b/src/docs/conf.py index 2bd5186b..f25a67ba 100644 --- a/src/docs/conf.py +++ b/src/docs/conf.py @@ -73,6 +73,7 @@ html_theme = 'sphinx_rtd_theme' html_static_path = ['_static'] +html_css_files = ['css/tables.css'] html_theme_options = { 'logo_only': False, diff --git a/src/docs/getting_started.rst b/src/docs/getting_started.rst index 79372329..492bbca9 100644 --- a/src/docs/getting_started.rst +++ b/src/docs/getting_started.rst @@ -136,7 +136,7 @@ Use the platform's virtual-environment activation command on Windows. ``RTA_PYTH PYTHONPATH="$PWD/install-python/lib" python -c \ "import rawtoaces; print(rawtoaces.ImageConverter)" -For builds against OpenImageIO 3.2 or later, ``rawtoaces`` also imports the ``OpenImageIO`` Python extension and checks its nanobind type registrations. Install a compatible OpenImageIO Python extension for the selected interpreter, with its native dependencies available to the runtime loader. Merely installing nanobind or satisfying the OpenImageIO version number is not sufficient. See :doc:`api/python/index` for method availability and setup details. +For builds against OpenImageIO 3.2 or later, ``rawtoaces`` also imports the ``OpenImageIO`` Python extension and checks its nanobind type registrations. Install a compatible OpenImageIO Python extension for the selected interpreter, with its native dependencies available to the runtime loader. Merely installing nanobind or satisfying the OpenImageIO version number is not sufficient. See :doc:`api/overview` for when to use the buffer methods and :doc:`api/python/index` for setup details. Docker ^^^^^^ diff --git a/src/docs/index.rst b/src/docs/index.rst index dbcdf724..e9694ecf 100644 --- a/src/docs/index.rst +++ b/src/docs/index.rst @@ -12,6 +12,9 @@ integration into other applications. Programming references ---------------------- +:doc:`api/overview` chooses a file conversion, an OpenImageIO buffer pipeline, +or a metadata or spectral solve. The language references list signatures: + - :doc:`api/cpp/api_reference`: C++ classes, settings, and functions. - :doc:`api/python/api_reference`: Python classes and methods. @@ -22,6 +25,7 @@ Programming references getting_started user_guide lens_correction + api/overview api/cpp/index api/python/index contributing