Skip to main content
Skip table of contents

Determine if a color channel is used

📌 Overview

This article explains the best practice for color reporting - using a custom transform.

(question) Issue Description

A customer asked: “How can we determine if a process color channel is used on a page. We want to know if a document has no pixel of cyan or magenta although these color channels always exist. We could count the separations contents, but this might be unreliable in low resolutions and I wonder if there is a simpler way.“

💡 Solution

To solve this, a custom transform can be used to scan the content to discover which color spaces are in use.

  1. Create a custom transform implementation: Override the transformColor() method and append each color to a new list property. See m_colorList in the sample code.

  2. Apply the transform to every page: Create an instance of the transform and apply it to a page with ICustomTransform::transform()

  3. Get the list of colors and process accordingly: Retrieve the list of colors using a “get method”. See CEDLVector<IDOMColorPtr> getColorList() const { return m_colorList; } in the sample code below. From here you can get the color space and color space type using IDOMColor::getColorSpace() and IDOMColorSpace::GetColorSpaceType() respectively.

⌨️ Sample Code

This C+ example shows how it’s done. See snippets below or find the full example at ColorReporting.cpp.

Custom Transform

CPP
class CColorTransformImplementation : public ICustomTransform::IImplementation
{
public:
    CColorTransformImplementation()
    {
    }

    virtual IDOMBrushPtr transformShadingPatternBrush(IImplementation* genericImplementation, const IDOMShadingPatternBrushPtr& brush, const CTransformState& state)
    {
        return genericImplementation->transformShadingPatternBrush(NULL, brush, state);
    }

    virtual IDOMColorPtr transformColor(IImplementation* genericImplementation, const IDOMColorPtr& color, const CTransformState& state)
    {
        m_colorList.append(color);
        return genericImplementation->transformColor(NULL, color, state);
    }

    CEDLVector<IDOMColorPtr> getColorList() const
    {
        return m_colorList;
    }

private:
    CEDLVector<IDOMColorPtr> m_colorList;

};

Get list of colors

CPP
IDocumentPtr document = assembly->getDocument();
uint32 pageCount = document->getNumPages();

// Create a transform to gather color info
CColorTransformImplementation implementation;
ITransformPtr getColors = ICustomTransform::create(jawsMako, &implementation, abort, true, true, true, true, true, true);
std::map<String, IDOMColorPtr> inkMap;

// Apply the transform to every page
for (uint32 pageNum = 0; pageNum < pageCount; pageNum++)
{
    IPagePtr page = document->getPage(pageNum);
    IDOMFixedPagePtr fixedPage = page->edit();

    // Get inks
    inkMap.clear();
    IRendererTransform::CInkInfoVect inks = IRendererTransform::findInks(jawsMako, fixedPage);
    for (auto ink : inks)
    {
        inkMap.insert({ U8StringToString(ink.inkName), ink.inkColor });
    }

    // get colors
    bool result = false;
    getColors->transform(fixedPage, result);
}

CEDLVector<IDOMColorPtr> colors = implementation.getColorList();
std::wcout << L"Color count: " << colors.size() << std::endl;

Process results

CPP
// Process colors
int index = 0;
for (IDOMColorPtr color : colors)
{
    auto colorSpace = color->getColorSpace();
    auto colorSpaceEnum = colorSpace->getColorSpaceType();
    String colorSpaceType = colorSpaceMap.at(colorSpaceEnum);

    uint8 numComponents = colorSpace->getNumComponents();
    wprintf_s(L"%3d ", ++index);
    std::wcout << colorSpaceType << L" (";
    for (uint32 c = 0; c < numComponents; c++)
    {
        wprintf_s(L"%4.2f", color->getComponentValue(c));
        if (c < numComponents - 1)
            std::wcout << ",";
    }
    std::wcout << L") ";
    if (colorSpaceEnum == IDOMColorSpace::eDeviceN)
    {
        IDOMColorSpaceDeviceNPtr deviceN = edlobj2IDOMColorSpaceDeviceN(colorSpace);
        numComponents = deviceN->getNumComponents();

        for (uint8 componentIdx = 0; componentIdx < numComponents; componentIdx++)
        {
            auto altColorSpace = deviceN->getAlternateColorSpace();
            auto altColorSpaceEnum = altColorSpace->getColorSpaceType();
            IDOMDeviceNColorantPtr colorant = deviceN->getColorant(componentIdx);
            String colorantName = U8StringToString(U8String(colorant->getName()));

            // Only process if a not a special
            if (colorantName != L"All" && colorantName != L"None")
            {
                IDOMColorPtr colorantColor = inkMap.at(colorantName);
                std::wcout << L"('" << colorantName << L"'\t";

                String altColorSpaceType = colorSpaceMap.at(altColorSpaceEnum);

                // Components of the alternate color space
                uint8 altNumComponents = altColorSpace->getNumComponents();
                std::wcout << altColorSpaceType << L" (";
                for (uint32 altComponentIdx = 0; altComponentIdx < altNumComponents; altComponentIdx++)
                {
                    wprintf_s(L"%4.2f", colorantColor->getComponentValue(altComponentIdx));
                    if (altComponentIdx < (altNumComponents - 1))
                        std::wcout << ",";
                }
                std::wcout << L") ";
            }
        }
        std::wcout << std::endl;
    }
    std::wcout << std::endl;
}

☑️ Conclusion

By implementing a custom transform, you can effectively determine the usage of color channels within a document. This method provides a reliable way to identify color spaces and their components, ensuring accurate color reporting even in complex documents. Utilizing the provided sample code and resources, you can integrate this solution into your workflow to enhance color management capabilities.

📚 Additional Resources

If you need additional help, see our API documentation for detailed information on class/method usage, or raise a support ticket via our customer portal.

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.