Gdy PDFXCompliance jest ustawione na 'X-1a', HotPDF waliduje kolor treści na samym końcu pracy: EndDoc woła THotPDF.EnsurePDFX1aContentColorSpaces, które odrzuca dowolną treść DeviceRGB, CalRGB albo ICCBased RGB gdziekolwiek na dowolnej stronie i rzuca wyjątek nazywający winny zasób. Plik nigdy nie zostaje zapisany jako dokument PDF/X-1a, który drukarnia odbije
Ta ostatnia część jest sednem. Plik PDF/X-1a z jednym zabłąkanym logo RGB wygląda na ekranie perfekcyjnie, przechodzi pobieżny przegląd i pada na preflight w drukarni dwa dni przed slotem prasy. Wyłapanie tego w buildzie Delphi, z komunikatem mówiącym, która strona i który obraz, jest o wiele tańsze niż dowiedzenie się od wściekłego operatora prepress
Dlaczego PDF/X-1a odrzuca treść RGB?
PDF/X-1a odrzuca RGB, bo format obiecuje, że każdy kolor jest już ostateczny dla jednego konkretnego warunku druku CMYK. ISO 15930-1:2001 §6.2.3 ogranicza kolor treści do DeviceCMYK, DeviceGray i farb spot, czyli przestrzeni Separation i DeviceN, których alternatywy są CMYK albo Gray. OutputIntent GTS_PDFX osadzony w pliku nazywa ten warunek druku, na przykład FOGRA39 coated offset, i odbierający workflow ma prawo wysłać liczby wprost na płyty bez żadnej konwersji barw
RGB łamie ten kontrakt. Wartość RGB opisuje kolor względem wyświetlacza albo przestrzeni roboczej, nie receptę farby, więc ktoś downstream musiałby zdecydować, jak ją wyseparować, a X-1a istnieje właśnie po to, by odebrać tę decyzję odbiorcy. ISO 32000-1 §8.6 grupuje przestrzenie barw PDF w rodziny device, oparte na CIE i specjalne, i członkowie RGB pojawiają się w więcej niż jednej rodzinie: DeviceRGB to przestrzeń device, CalRGB i ICCBased o trzech komponentach są oparte na CIE, a przestrzeń Indexed albo Separation może schować bazę lub alternatywę RGB pod spodem. Kontroler patrzący wyłącznie na operator rg przeoczy większość z nich. Późniejsza edycja PDF/X-1a:2003 (ISO 15930-4) trzyma tę samą regułę barwną; zauważ, że wartość 'X-1a' HotPDF-a zapisuje identyfikację PDF/X-1a:2001 do pakietu XMP
Jeśli twoja treść naprawdę jest RGB i taka ma zostać, X-1a to zły cel. HotPDF ogranicza tę kontrolę wyłącznie do 'X-1a', więc 'X-3' i 'X-4', które pozwalają barwę opartą na ICC i kalibrowaną, pozostają nietknięte
Co faktycznie sprawdza EnsurePDFX1aContentColorSpaces
EnsurePDFX1aContentColorSpaces łączy flagę z czasu rysowania z rekurencyjnym przejściem po zasobach każdej strony i działa ostatnie w bramce PDF/X. EndDoc najpierw wymusza ogólne wymagania PDF/X: Title musi być ustawione, Trapped musi być 'True', 'False' albo 'Unknown', OutputIntent GTS_PDFX musi istnieć (EnsurePDFXOutputIntent), a każda strona potrzebuje TrimBox albo ArtBox (EnsurePDFXPageBoxes). Dopiero po ich zaliczeniu rusza kontrola koloru
Pierwsza ścieżka to flaga dla całego dokumentu. Setter kolorów RGB HotPDF-a, osadzanie bitmap i wpisy kolorów adnotacji rejestrują użycie DeviceRGB w czasie rysowania, co obejmuje inline operatory rg i RG, które nigdy nie pojawiają się w słowniku zasobów. Druga ścieżka przechodzi przez /Resources każdej strony i zagląda w:
- Nazwane przestrzenie barw w
/ColorSpace, łącznie ze skrótem obrazów inlineRGBjako synonimem DeviceRGB /ColorSpacekażdego Image XObject- Form XObjects i wzory tiling, przez rekurencję w ich własne zagnieżdżone
/Resources - Shading Patterns i wpisy w słowniku
/Shadingstrony, przez/ColorSpaceshadingu - Bazy przestrzeni Indexed, alternatywy Separation i DeviceN oraz bazy wzorów, śledzone w dół do zagnieżdżenia 8
Odrzucane są trzy rzeczy: DeviceRGB, CalRGB oraz przestrzenie ICCBased, których strumień profilu deklaruje N = 3. Słowniki zasobów współdzielone między Form XObjects i wzorami są odwiedzane raz, więc wzajemnie się referujący zestaw form nie zapętla przejścia. Metoda jest publiczna na THotPDF, ale w normalnym użyciu nigdy sam jej nie wołasz, bo robi to za ciebie EndDoc
Rysowanie strony X-1a w Delphi przechodzącej kontrolę
Zgodny dokument X-1a HotPDF potrzebuje OutputIntent CMYK, TrimBox na każdej stronie i koloru ustawianego wyłącznie przez API CMYK, Gray i spot. Szkielet poniżej używa profilu FOGRA39; AddPDFXOutputIntent bierze identyfikator warunku wyjściowego, string info, strumień profilu ICC, liczbę jego komponentów i przestrzeń alternatywną
var
Pdf: THotPDF;
Profile: TFileStream;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.FileName := 'brochure-x1a.pdf';
Pdf.Title := 'Spring brochure, press edition';
Pdf.Trapped := 'False';
Pdf.PDFXCompliance := 'X-1a';
Pdf.BeginDoc;
Profile := TFileStream.Create('CoatedFOGRA39.icc', fmOpenRead or fmShareDenyWrite);
try
Pdf.AddPDFXOutputIntent('FOGRA39 (ISO 12647-2:2004)',
'Coated FOGRA39 offset', Profile, 4, 'DeviceCMYK');
finally
Profile.Free;
end;
Pdf.CurrentPage.SetTrimBox(0, 0, 612, 792); // wymagany na każdej stronie
Pdf.CurrentPage.SetCMYKFillColor(0, 0.5, 0.8, 0.1);
Pdf.CurrentPage.Rectangle(72, 600, 468, 120);
Pdf.CurrentPage.Fill;
Pdf.CurrentPage.SetGrayFillColor(0.2); // tekst DeviceGray
Pdf.CurrentPage.SetFont('Arial', [], 14);
Pdf.CurrentPage.TextOut(72, 560, 0, 'Spring catalog, press edition');
Pdf.EndDoc; // tu działa kontrola koloru
finally
Pdf.Free;
end;
end;
Każde wywołanie oparte na TColor to pułapka w tym kontekście. SetRGBFillColor, SetRGBStrokeColor i SetRGBColor wszystkie biorą kolor GDI i emitują DeviceRGB, więc helper napisany lata temu dla raportów pod ekran zatru zadanie drukowane w chwili, gdy zostanie ponownie użyty. Używaj SetCMYKFillColor, SetCMYKStrokeColor albo SetCMYKColor z komponentami w zakresie od 0 do 1, albo odpowiedników Gray
Farby spot i gradienty CMYK
Farby spot są dozwolone w X-1a, dopóki ich alternatywa jest CMYK albo Gray. RegisterSeparation buduje przestrzeń Separation i zwraca jej nazwę zasobu, a RegisterAxialGradient dobiera przestrzeń barwną shadingu z liczby komponentów, którą podasz, przy czym cztery komponenty znaczy DeviceCMYK
var
SpotCS, Ramp: AnsiString;
begin
// Farba spot z przybliżonym składem CMYK jako alternate
SpotCS := Pdf.RegisterSeparation('Corporate Red', 'DeviceCMYK',
[0, 1, 0.8, 0.05]);
Pdf.CurrentPage.SetFillColorSpace(SpotCS);
Pdf.CurrentPage.SetFillColor([1.0]); // tint 100%
Pdf.CurrentPage.Rectangle(72, 420, 200, 80);
Pdf.CurrentPage.Fill;
// 4 komponenty na stop: shading to DeviceCMYK, nie DeviceRGB
Ramp := Pdf.RegisterAxialGradient(72, 300, 540, 300,
[0, 0, 0, 0], [1, 0.6, 0, 0.2]);
Pdf.CurrentPage.SetFillPattern(Ramp);
Pdf.CurrentPage.Rectangle(72, 260, 468, 80);
Pdf.CurrentPage.Fill;
end;
Podaj temu samemu wywołaniu gradientu trzy komponenty, a dostaniesz shading DeviceRGB, który przejście po zasobach odrzuci pod nazwą wzoru shadingu. To samo dotyczy Separacji zarejestrowanej z 'DeviceRGB' jako alternatywą: nazwa farby spot wygląda niewinnie, ale przejście idzie za alternatywą i znajduje RGB pod spodem. Jak takie farby spot są komponowane, gdy przeglądarka albo RIP spada na alternatywę, opisuje artykuł renderowaniu Separation i DeviceN farb spot w Delphi
Obrazy rastrowe potrzebują tej samej dyscypliny. HotPDF przybija bitmapy skompresowane Flate do DeviceRGB, podczas gdy JPEG osadzony z icJpeg trzyma własną liczbę komponentów, więc czterokanałowy CMYK JPEG albo skala szarości jest w porządku, a zwykły RGB JPEG nie. Konwertuj grafikę do profilu prasowego w swoim pipeline obrazowania, zanim dotrze do PDF-a
Dlaczego /DefaultRGB nie ratuje pliku PDF/X-1a?
/DefaultRGB nie pomaga w X-1a, bo reguła dotyczy tego, co dostaje prasa, nie tego, czy RGB jest skarakteryzowane. Dla PDF/A HotPDF pozwala, by RegisterDefaultColorSpace('DefaultRGB', ...) wchłonęło użycie DeviceRGB: gdy domyślna przestrzeń barw mapuje DeviceRGB na profil ICC, treść jest niezależna od urządzenia i kontrola spójności PDF/A ją przyjmuje. Deweloperzy, którzy przeszli przez ten workflow, mają tendencję do próbowania tego samego lekarstwa tutaj
EnsurePDFX1aContentColorSpaces celowo ignoruje to mapowanie. Skarakteryzowana wartość RGB nadal jest RGB, a OutputIntent X-1a to warunek druku CMYK, więc ktoś i tak musiałby ją skonwertować. Jeśli masz zapamiętać jedną różnicę między tymi dwoma profilami archiwalnym i drukowym, niech będzie ta: PDF/A pyta, czy kolor jest jednoznaczny, PDF/X-1a pyta, czy jest już farbą
Kolejność rysowania i setup strony, który się nie liczy
Ponieważ kontrola działa przy EndDoc na już zapisanej treści, kolejność, w jakiej sobie konfigurujesz, nie ma znaczenia. RGB narysowane przed przypisaniem PDFXCompliance albo przed rejestracją OutputIntent nadal zostanie wyłapane. To ma znaczenie dla kodu budującego strony we współdzielonych procedurach i decydującego o profilu wyjściowym późno, czasem na podstawie ustawienia użytkownika wybranego, gdy pół dokumentu już istnieje
Pdf.BeginDoc;
// ... OutputIntent i TrimBox jak wyżej ...
Pdf.CurrentPage.SetRGBFillColor(clRed); // stary helper, emituje DeviceRGB
Pdf.CurrentPage.Rectangle(72, 72, 200, 100);
Pdf.CurrentPage.Fill;
Pdf.PDFXCompliance := 'X-1a'; // zadecydowane po rysowaniu
Pdf.EndDoc; // nadal rzuca: DeviceRGB zapisany
Flaga z czasu rysowania ma jedną pułapkę wartą znajomości, jeśli budujesz podobną kontrolę sam. Każda nowa strona jest inicjalizowana czarnym stanem graficznym przez SetRGBColor(0), co emituje parę 0 0 0 rg i 0 0 0 RG, i gdyby ten boilerplate setupu strony mógł ustawić flagę DeviceRGB, każdy dokument wyglądałby na zatruty RGB — zarówno dla tej kontroli, jak i dla kontroli spójności barw PDF/A. HotPDF zapisuje i przywraca flagę wokół tej inicjalizacji, więc liczy się tylko kolor, który faktycznie narysujesz
Jak znaleźć treść RGB, gdy EndDoc rzuca?
Czytaj lokalizację z początku komunikatu wyjątku, bo mówi ci, która z dwóch ścieżek znalazła problem. Komunikat ma formę PDFXCompliance 'X-1a': <where> uses <what>, po której idzie referencja ISO 15930-1 i rada, by skonwertować do CMYK albo Gray albo przejść na X-3 lub X-4. Walidator rzuca zwykły Exception przy pierwszym naruszeniu, więc dopasowuj na tekst, nie na klasę wyjątku
document content uses DeviceRGB (rg/RG operators, RGB images or annotation colours recorded during drawing)znaczy, że zapaliła się flaga z czasu rysowania. Nie ma numeru strony, bo flaga jest ogólnodokumentowa i sprawdzana przed przejściem. Przeszukaj kod rysowania za wywołaniamiSetRGB*, bitmapami Flate, JPEG-ami RGB i kolorami adnotacjiTColorpage 3 image XObject /Im2 uses DeviceRGB contentalbopage 1 shading Pattern /P1 uses DeviceRGB contentprzychodzi z przejścia po zasobach i wskazuje dokładny klucz zasobuuses an ICCBased RGB colour space (N=3)po lokalizacjiColorSpace /...to typowy wynik rejestracji profilu sRGB przezRegisterICCProfilei wybrania go przezSetFillColorSpace, ścieżki, której flaga z czasu rysowania nie widzi- Zagnieżdżone lokalizacje się łańcuchują, na przykład
page 2 Form XObject /Fm1 ColorSpace /CS1, więc możesz iść ścieżką od strony w dół do zasobu niosącego przestrzeń RGB
try
Pdf.EndDoc;
except
on E: Exception do
begin
if Pos('X-1a', E.Message) > 0 then
LogPrepressFailure(Pdf.FileName, E.Message); // twój własny logger
raise;
end;
end;
Ponieważ raportowane jest tylko pierwsze naruszenie, naprawianie zadania z kilkoma źródłami RGB jest iteracyjne: napraw, przebuduj, przeczytaj następny komunikat. Dla zadań wsadowych opłaca się logować pełny komunikat per plik i trzymać krótką listę znanych sprawców, jak bitmapa logo albo helper wykresów, który nadal bierze TColor
Gdzie bramka RGB pasuje do twojego preflightu
EnsurePDFX1aContentColorSpaces to celowana bramka RGB działająca wewnątrz twojego builda i stanowi parę z pełnym preflightem PDF/X-1a, zamiast go zastępować. Pokrywa rodziny RGB — przez przejście po zasobach od /Resources każdej strony i przez flagę z czasu rysowania, którą prowadzą settery kolorów HotPDF-a dla inline operatorów rg i RG; zagnieżdżone przestrzenie barw są śledzone do głębokości 8 jako zabezpieczenie przed zepsutymi cyklami, a pierwsze naruszenie jest raportowane per EndDoc. Inne rodziny barw jak Lab albo CalGray to materiał dla pełnego preflightu, więc przegon skończony plik przez zewnętrzny walidator jako część builda, by dostać pełny werdykt zgodności. Szerszy obraz wyników zgodności jest w przewodniku po wyjściu PDF/A, PDF/X i PDF/UA z HotPDF, a podpięcie walidatora do pipeline'u nienadzorowanego opisuje automatyzacja kontroli preflight PDF w Delphi
HotPDF to natywny komponent VCL PDF dla Delphi i C++Builder z wyjściem PDF/X, PDF/A i PDF/UA, API kolorów CMYK i spot oraz wsparciem ICC OutputIntent. Szczegóły, licencjonowanie i pobranie próbne są na stronie produktu HotPDF Delphi PDF component