Removing embedded profiles from a PDF

📌 Overview

This article explains how to remove embedded ICC-based color profiles from a PDF using the Mako SDK. This is often necessary when profiles cause unexpected rendering results, such as outputting CMYK instead of pure Black (K).

question mark Issue Description

A customer reported that while they could remove embedded profiles from images, they were struggling to do the same for PDF files. Specifically, a PDF with an embedded profile was rendering in CMYK, whereas the version without the profile correctly output only K.

💡 Solution

The solution involves using a custom transform that targets both images and color spaces. By extending a custom transform to iterate through the PDF page content, you can identify and remove ICCBased color space profiles.

🪜 Steps

  1. Implement a Custom Transform: Create a class inheriting from ICustomTransform::IImplementation.

  2. Target Color Spaces: Within the transform, identify ICCBased color spaces.

  3. Apply to Document: Iterate through the pages of the document and apply the transform to the page content.

⌨️ Sample Code

The following approach demonstrates how to use a custom transform to strip profiles. Full code can be found at RemoveEmbeddedProfiles.cs.

C#
class RemoveEmbeddedProfilesTransform(IEDLClassFactory factory)
        : ICustomTransform.IImplementation
{
    public override IDOMImage transformImage(
        ICustomTransform.IImplementation genericImplementation,
        IDOMImage image,
        CTransformState state) =>
        SubstituteImageColorSpace(factory, image) ??
        genericImplementation.transformImage(null, image, state);

    public override IDOMColorSpace transformColorSpace(
        ICustomTransform.IImplementation genericImplementation,
        IDOMColorSpace colorSpace,
        CTransformState state) =>
        GetReplacementDeviceColorSpace(factory, colorSpace) ??
        genericImplementation.transformColorSpace(null, colorSpace, state);
}
C#
private static IDOMImage? SubstituteImageColorSpace(
        IEDLClassFactory factory,
        IDOMImage image)
{
    using var replacementColorSpace = GetReplacementDeviceColorSpace(factory, image);
    if (replacementColorSpace == null) return null;

    var substitutedImage = image.getImageWithSubstitutedColorSpace(factory, replacementColorSpace);
    if (substitutedImage == null || IDOMImage.isEqual(image, substitutedImage)) return null;
    return substitutedImage;
}

private static IDOMColorSpace? GetReplacementDeviceColorSpace(IEDLClassFactory factory, IDOMImage image)
{
    using var frame = image.getImageFrame(factory);
    using var sourceColorSpace = frame.getColorSpace();
    return GetReplacementDeviceColorSpace(factory, sourceColorSpace);
}

private static IDOMColorSpace? GetReplacementDeviceColorSpace(
    IEDLClassFactory factory,
    IDOMColorSpace? sourceColorSpace)
{
    if (sourceColorSpace == null ||
        sourceColorSpace.getColorSpaceType() != IDOMColorSpace.eColorSpaceType.eICCBased) return null;

    using var iccBasedColorSpace = IDOMColorSpaceICCBased.fromRCObject(sourceColorSpace);
    if (iccBasedColorSpace == null) return null;

    var processChannels = IColorManager.get(factory).getNumComponentsForICCBasedSpace(iccBasedColorSpace);
    return processChannels switch
    {
        1 => IDOMColorSpaceDeviceGray.create(factory),
        3 => IDOMColorSpaceDeviceRGB.create(factory),
        4 => IDOMColorSpaceDeviceCMYK.create(factory),
        _ => null
    };
}

☑️ Conclusion

By targeting color spaces within a custom transform, you can effectively remove embedded ICC profiles from PDF content, ensuring consistent rendering behavior across different files.

📚 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.