ConvertPdfDocumentColours obtains the active PDF revision, transforms original component operands and image samples through an IPdfColourTransform, then appends a consistent revision to a separate output stream
Supported input includes text and vector fill/stroke operators in DeviceGray, DeviceRGB, DeviceCMYK and ICCBased spaces, inherited page resources, named default colour-space aliases, nested Form XObjects, and raw or general-filter images with 8-bit or 16-bit components
Content arrays use a common operand parser and graphics-state stack, with a space separating streams; throughout conversion, q/Q, default colour spaces and component counts refer to their original source spaces
CMYK operands are taken directly from PDF content and image streams, never from rendered RGB getters; unprofiled DeviceCMYK input needs DeviceCMYKProfile
Source ICCBased profiles are resolved in their original resource scope; /Range [0 1 ...] must be absent or default, and image /Decode arrays are applied before conversion and omitted from the converted image
16-bit image samples retain PDF big-endian ordering; exact byte geometry and destination expansion are validated before allocating samples, with no invented stride or padding
PreserveAllSpotColours is true by default; otherwise, list decoded PDF colourant names in PreservedSpotColours, as Separation or DeviceN is retained only if every named colourant is selected
Retained spot-colour operators, tint functions and resources are left intact; other spots need a dedicated conversion backend and are reported as unsupported
Image stencil masks and referenced mask data are retained; colour-key masks, explicit masks and soft-mask matte components need policies of their own
Unsupported cases comprise DCT/JPX images without a decoder for original components, 1/2/4-bit images and row padding, nondefault ICC ranges, Indexed/Cal/Lab/Pattern spaces, inline images, shading functions, Type3 glyph programs, annotation dictionary colours, form default-appearance instructions, XFA colour content, transparency groups, non-normal blending, overprint, graphics transfer functions and rendering intents
A Form with its own resources must select its colour space before bare sc/scn operands; shared forms or images inherited in differing source contexts are unsupported, and cached failures are passed to every calling scope
By default, FailOnUnsupported is true and failure leaves the destination unchanged; false permits separate supported updates, marks Complete false and prevents a partial conversion from installing a new OutputIntent
Partial output may still contain the source's existing OutputIntent; OutputIntentWritten tells you specifically whether this operation installed a new destination declaration
For complete output, the supplied destination ICC profile is embedded and an OutputIntent is written with the requested identifier; this does not certify PDF/X, PDF/A or any other conformance level
Use different source and destination streams; the source position is restored, preparation errors preserve the destination, and cancellation retains EPdfOperationCancelled
Publishing uses the destination's stream API to replace its contents; truncation or write exceptions may leave partial output, so publish files atomically by writing a temporary file and renaming it after success
For encrypted or already signed input, prepare an unencrypted, unsigned source separately; incremental colour conversion cannot maintain signature validity
Alongside the active-object reader's budgets, defaults permit 64 MiB per decoded content/image stream, 512 MiB of output staging, 10,000 issue reports and depth 64
Before adding each update, the output budget conservatively accounts for source bytes, staged replacement objects and reserved xref/trailer overhead; full trailer length is included before serialisation, and the limited output stream refuses excess writes before extending its logical size
The allowance covers logical output staging, not total process memory or allocator capacity rounding; the final serialised size is checked once more before publication
Delphi and FPC Win32/Win64 tests verify real RGB, CMYK and ICCBased image conversion, text/vector conversion, nested forms, retained Separation and DeviceN, OutputIntent, compressed object streams, and PDF saving, reopening and rendering
ProviderOptions := TPdfLittleCmsOptions.Default; Provider := CreatePdfLittleCmsColourTransform(LibraryPath, ProviderOptions); Options := TPdfDocumentColourOptions.Default; Options.DeviceCMYKProfile := SourceCmykProfile; TargetProfile := CreatePdfLittleCmsGrayProfile(LibraryPath); if not ConvertPdfDocumentColours(Source, Destination, pcsDeviceGray, TargetProfile, Provider, Options, Report, CancellationToken) then raise Exception.Create(Report.ErrorText);
type
TPdfSpotColourNames = array of AnsiString;
TPdfDocumentColourOptions = record
ReadOptions: TPdfActiveObjectReadOptions;
MaxDecodedStreamBytes: Integer;
MaxOutputBytes: Int64;
MaxIssues: Integer;
MaxDepth: Integer;
FailOnUnsupported: Boolean;
PreserveAllSpotColours: Boolean;
PreservedSpotColours: TPdfSpotColourNames;
DeviceGrayProfile, DeviceRGBProfile, DeviceCMYKProfile: TBytes;
OutputIntentIdentifier: string;
class function Default: TPdfDocumentColourOptions; static;
end;
TPdfDocumentColourIssue = record
ObjectNumber: Integer;
Reason: string;
end;
TPdfDocumentColourIssues = array of TPdfDocumentColourIssue;
TPdfDocumentColourReport = record
Succeeded: Boolean;
Complete: Boolean;
ContentStreamsConverted, FormsConverted, ImagesConverted: Integer;
ColourOperatorsConverted, PreservedSpotSelections, PreservedMasks: Integer;
UnsupportedCount: Integer;
OutputIntentWritten: Boolean;
Issues: TPdfDocumentColourIssues;
ErrorText: string;
end;
function ConvertPdfDocumentColours(Source, Destination: TStream;
TargetSpace: TPdfColourSpace; const TargetProfile: TBytes;
Transform: IPdfColourTransform; const Options: TPdfDocumentColourOptions;
out Report: TPdfDocumentColourReport;
CancellationToken: IPdfCancellationToken = nil): Boolean;