Skip to content

Bisect: f464b41 CIccPcsXform::ConnectFirst() & CIccPcsXform::ConnectLast() #1748

Description

@xian20020

Body:
Hi, I found a possible issue in IccProfLib.

Summary

When creating an RGB -> CMYK transform with black point compensation enabled, CIccCmm::Begin() may fail with:

Incorrect Apply object

The returned status is:

icCmmStatIncorrectApply

After reading the CMM connection code, I suspect that the first/last PCS connection paths may leave some CIccPcsXform metadata unset.

Environment

  • iccDEV / IccProfLib version: 2.3.2.2
  • Platform: Windows
  • Compiler: MinGW 13.1
  • Build environment: Qt 6.11 / MinGW 64-bit
  • Transform: RGB profile -> CMYK profile
  • Rendering intent: Perceptual
  • Black point compensation: enabled

Observed behavior

CIccCmm::Begin() fails during transform initialization.

The error string is:

Incorrect Apply object

Expected behavior

The CMM transform chain should initialize successfully when the profiles and conversion parameters are valid.

Investigation

CIccPcsXform::Connect() initializes the source/destination color-space metadata and sample counts:

m_srcSpace
m_dstSpace
m_nSrcSamples
m_nDstSamples

However, CIccPcsXform::ConnectFirst() and CIccPcsXform::ConnectLast() appear to build PCS edge transforms without setting these fields.

That means they may remain at the constructor defaults:

m_srcSpace = icSigUnknownData;
m_dstSpace = icSigUnknownData;
m_nSrcSamples = 0;
m_nDstSamples = 0;

With black point compensation enabled, CIccApplyBPCHint may build an auxiliary PCS/device/PCS path while calculating the destination black point. If that path includes these PCS edge transforms with unknown color spaces or zero sample counts, the nested apply object can become invalid, and initialization may fail with icCmmStatIncorrectApply.

Suggested fix

Initialize the metadata in CIccPcsXform::ConnectFirst():

m_srcSpace = srcSpace;
if (IsSpaceSpectralPCS(m_srcSpace))
  m_srcSpace = icGetColorSpaceType(m_srcSpace);
m_nSrcSamples = (icUInt16Number)icGetSpaceSamples(m_srcSpace);

m_dstSpace = pToXform->GetSrcSpace();
if (IsSpaceSpectralPCS(m_dstSpace))
  m_dstSpace = icGetColorSpaceType(m_dstSpace);
m_nDstSamples = pToXform->GetNumSrcSamples();

And initialize the metadata in CIccPcsXform::ConnectLast():

m_srcSpace = srcSpace;
if (IsSpaceSpectralPCS(m_srcSpace))
  m_srcSpace = icGetColorSpaceType(m_srcSpace);
m_nSrcSamples = pFromXform->GetNumDstSamples();

m_dstSpace = dstSpace;
if (IsSpaceSpectralPCS(m_dstSpace))
  m_dstSpace = icGetColorSpaceType(m_dstSpace);
m_nDstSamples = (icUInt16Number)icGetSpaceSamples(m_dstSpace);

Question

Should ConnectFirst() and ConnectLast() initialize their source/destination color-space metadata and sample counts in the same way as Connect()?

If so, would a patch like the one above be acceptable?

Metadata

Metadata

Labels

BisectMaintainer indicates BisectTriagedMaintainer indicates triaged status and ready for developer handoffVerified ReportMaintainer indicates a Verified Report

Type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions