Enhancement: CICP interpretation and conversion · Issue #4619 · lovell/sharp · GitHub
Skip to content

Enhancement: CICP interpretation and conversion #4619

Open

Description

@mertalev

Feature request

What are you trying to achieve?

The basic goals are to leverage libvips's new CICP support to:

  • Interpret input images (both raw and encoded) with CICP metadata
  • Save images with either the input's CICP or caller-provided CICP metadata
  • Inspect the CICP metadata of input and output images

The biggest motivation is for HDR in being able to process and output HDR AVIF images, convert native HDR images to Ultra HDR JPEG, and so on.

When you searched for similar feature requests, what did you find that might be related?

#4508 was a PoC for this integration with a slightly different API.

What would you expect the API to look like?

Ideally, the API is intuitive and consistent with sharp's other APIs.

Constructor

  • ignoreCicp (default false) to not apply the input's CICP metadata
  • raw: { cicp: { colourPrimaries, transferCharacteristics, matrixCoefficients, fullRangeFlag } } to interpret raw bitmaps

Methods

  • keepCicp() makes it encode with the input's CICP. No-op if the input does not have CICP.
  • withCicp({ colourPrimaries: 'bt2020', transferCharacteristics: 'pq' }) makes it encode with other CICP values, supporting the same strings as libvips
    • libvips only implements identity matrix coefficients and full range output
    • Last caller wins between it and keepCicp, matching keepGainMap / withGainMap

Metadata

  • CicpMetadata: { colourPrimaries, transferCharacteristics, matrixCoefficients, fullRangeFlag }
  • Metadata includes cicp?: CicpMetadata, reflecting the original input's CICP metadata
  • OutputInfo likewise includes cicp?: CicpMetadata, reflecting the CICP values it was encoded with

Behavior

  • keepCicp / withCicp takes priority over toColorspace and withIccProfile when the output format supports CICP. If the format does not support CICP, then OutputInfo returns no cicp
    • The intent is to make it easy to express "output to HDR AVIF or Display P3 WebP" to ensure the best color fidelity for the output format
  • CICP is interpreted transparently like ICC by calling CICP2scRGB internally, with ignoreCicp in the constructor to opt out. The scRGB bitmap is transformed to the pipeline colorspace before moving on if pipelineColorspace is explicitly set
    • Notably, if the CICP is sRGB or unspecified, it should not convert to scRGB since it would just slow things down for no benefit
  • The input image is encoded as normal by default even if it has CICP, matching how sharp defaults to sRGB even if the input has ICC
    • Not sure about this since it does mean that an HDR input gets clipped by default, but that's still better than the status quo
  • Error if ignoreCicp is used in combination with cicp in the constructor

What alternatives have you considered?

There's a sliding scale of how lenient/strict it should be, throwing if withCicp and withIccProfile are both set, if withCicp is set when the output format doesn't support CICP, and so on. Being strict makes the behavior unambiguous, but less ergonomic for some use-cases (the caller might have to call .metadata() and branch).

Another axis is how manual/automatic it should be. Requiring you to opt in to interpreting CICP would be one end of that while automatically preserving the original's CICP in the output unless overridden would be the other end. Since sharp describes outputting sRGB by default, I figured the path of least surprise was to interpret CICP but target sRGB by default.

#4608 and #4612 both describe changes to default color management. If there are planned changes in that area, they should probably be reflected in the CICP behavior as well for consistency. For example, if keepIccProfile is default, then keepCicp should probably be too.

Please provide sample image(s) that help explain this feature

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions