A PDF Library for Delphi cria os dois tipos de máscara suave de PDF a partir do Delphi. SetImageSoftMaskEx anexa uma imagem de máscara a uma imagem alvo e pode gravar a entrada /Matte que a arte pré-multiplicada exige. NewSoftMaskGraphicsState constrói uma máscara alfa ou de luminosidade a partir de conteúdo capturado e retorna um graphics state que você aplica ao desenho subsequente. E quando um consumidor não consegue lidar com transparência de forma alguma, FlattenTransparency renderiza o resultado visual e substitui cada página por ele
Máscaras suaves são como o PDF expressa um degradê, uma vinheta, uma foto mesclada em um fundo, e todo outro efeito em que a opacidade varia através de uma região. Transparência constante é um único número no graphics state; uma máscara suave é uma função inteira de posição, e até você conseguir criar uma, uma categoria inteira de design não pode ser reproduzida
Os dois tipos de máscara, e o que cada um lê
Uma máscara alfa tira seus valores do canal alfa do conteúdo de mascaramento. Uma máscara de luminosidade os tira do brilho do conteúdo de mascaramento, de modo que uma área branca é totalmente opaca e uma área preta totalmente transparente. Luminosidade é a que os designers usam, porque pintar um degradê em tons de cinza é uma forma natural de descrever um esmaecimento
Máscaras suaves de formulário são construídas a partir de conteúdo capturado, e vários detalhes são fixos, e não opcionais. O conteúdo capturado se torna um grupo de transparência isolado em DeviceRGB, de modo que a máscara é avaliada em um espaço de cor conhecido. A cor de fundo, portanto, precisa ter três componentes, correspondendo a esse grupo. A função de transferência aceita /Identity ou um objeto de função válido, permitindo que você remodele a curva da máscara sem repintar a arte
uses
PDFlibrary;
var
Lib: TPDFlib;
MaskCapture, MaskGS, PhotoID: Integer;
begin
Lib := TPDFlib.Create;
try
Lib.LoadFromFile('brochure.pdf', '');
// A página 4 tem um degradê em tons de cinza pintado para uso como máscara
MaskCapture := Lib.CapturePage(4);
MaskGS := Lib.NewSoftMaskGraphicsState(MaskCapture,
PDF_SOFT_MASK_LUMINOSITY, '0 0 0', '/Identity');
Lib.SelectPage(1);
Lib.SetGraphicsState(MaskGS);
PhotoID := Lib.AddImageFromFile('hero.jpg', 0);
Lib.SelectImage(PhotoID);
Lib.DrawImage(40, 700, 515, 260); // esmaece sob a máscara
// Os parâmetros de ExtGState persistem: encerre o escopo explicitamente
Lib.SetGraphicsState(Lib.NewSoftMaskGraphicsState(0,
PDF_SOFT_MASK_NONE, '', ''));
Lib.SaveToFile('brochure-masked.pdf');
finally
Lib.Free;
end;
end;
Essa última etapa não é decoração. Os parâmetros de graphics state persistem até serem alterados, e aplicar um graphics state comum depois não limpa uma máscara suave ativa. Sem um /SMask /None explícito, tudo o que é desenhado depois da arte mascarada herda a máscara, o que é um dos bugs mais desconcertantes de diagnosticar visualmente
Máscaras de imagem e a entrada Matte
Para mascaramento em nível de imagem, a imagem de máscara é normalizada primeiro para DeviceGray, de modo que uma máscara fornecida em qualquer espaço de cor se comporta de forma previsível. A entrada opcional /Matte, de um a quatro componentes dependendo do espaço de cor da imagem, informa a um consumidor que os dados da imagem estão pré-multiplicados contra aquela cor, o que evita o halo escuro que aparece quando arte pré-multiplicada é composta como se fosse alfa direto
Duas barreiras importam aqui. PDF/A-1 e PDF/X-1 proíbem transparência, e a chamada se recusa antes de modificar qualquer objeto, em vez de produzir um arquivo que falha na validação depois. E uma máscara suave bem-sucedida exige PDF 1.4, que a biblioteca define automaticamente — transparência não existia antes dessa versão, e um cabeçalho 1.3 em um arquivo contendo máscaras suaves é simplesmente falso
Estados repetidos são reutilizados: a mesma forma capturada, tipo de máscara, cor de fundo e assinatura de função de transferência geram o mesmo objeto de graphics state, em vez de um novo por chamada. Em um documento que mascara cem imagens de forma idêntica, isso são noventa e nove objetos que nunca chegam a ser gravados
Por que achatar, e o que o achatamento realmente faz
Transparência ainda é a fonte mais comum de "parece certo na tela e errado na impressão". RIPs mais antigos, alguns sistemas de submissão regulatória e o PDF/X-1a todos exigem um arquivo sem transparência ativa alguma
O achatamento aqui é deliberadamente literal: cada página no intervalo solicitado é renderizada em um DPI escolhido sobre um fundo opaco, e o conteúdo e os recursos da página são substituídos por essa única imagem. Como o renderizador produz o resultado composto final, isso cobre tudo de uma vez — grupos de transparência, modos de mesclagem, máscaras suaves, padrões e formulários aninhados — sem nenhuma lógica de aproximação por construção que possa dar errado. A memória de raster de pico permanece limitada a uma página
// Achata as páginas 1-8 a 300 DPI em branco, depois salva como PDF 1.3
Lib.FlattenTransparency('1-8', 300, $FFFFFF, 0);
Lib.SaveToFile('press-ready.pdf');
O custo é igualmente literal: a saída é uma imagem, então o texto não é mais selecionável ou pesquisável, e as bordas vetoriais são reamostradas no DPI escolhido. O achatamento é uma etapa de entrega, não uma etapa de edição. Mantenha o original transparente e achate uma cópia
Páginas rotacionadas, unidades de usuário e as caixas de página
Uma página rotacionada precisa de cuidado que uma implementação ingênua pula. Depois da renderização, a largura e a altura visuais são gravadas de volta no MediaBox, a unidade de usuário é incorporada ao DPI efetivo e ao novo tamanho de página, e a entrada /Rotate, a unidade de usuário e as caixas de página auxiliares são removidas
Pular isso produz um arquivo em que a imagem achatada está correta, mas um visualizador a rotaciona de novo, ou a escala por uma unidade de usuário que não se aplica mais. Remover as caixas em vez de recalculá-las é a decisão certa, porque uma TrimBox descrevendo a geometria pré-achatamento é pior do que nenhuma TrimBox
Anotações e campos de formulário são renderizados na imagem estática por padrão, e os objetos interativos são removidos, o que é o que um material pronto para impressão quer. Se você mantiver os objetos interativos em vez disso, a passagem de anotações do renderizador é desativada para que nada seja desenhado duas vezes
A verificação de versão que escaneia tudo
Salvar como PDF 1.3 exige que nenhuma transparência reste em lugar nenhum, e a verificação pré-salvamento examina todo objeto indireto, não apenas os alcançáveis a partir das páginas. Isso é mais rigoroso do que parece à primeira vista e está correto: uma máscara suave órfã deixada por uma edição anterior ainda está no arquivo, e um consumidor que percorre objetos em vez de páginas vai encontrá-la
Para tornar o rebaixamento de versão viável, uma passagem de mark-and-sweep roda por padrão assim que toda página alvo foi substituída com sucesso, liberando os objetos inalcançáveis. A consequência a planejar é que identificadores de imagem, página capturada e graphics state obtidos antes dessa varredura podem não ser mais válidos depois. Readquira os identificadores de recurso de que você precisa antes de continuar a editar, ou desative a varredura e aceite que a versão não pode então ser rebaixada
Duas companheiras completam o quadro. Arte vetorial que usa shadings e degradês em vez de máscaras é abordada em gráficos vetoriais, shaders e degradês, e é frequentemente a rota melhor quando o efeito pode ser expresso como um shading. E se o motivo pelo qual você está achatando é uma exigência de cor, e não de transparência, o caminho de conversão em recolorindo um documento para outro espaço de cor preserva o texto ativo onde o achatamento não preservaria
A criação de máscaras suaves, o achatamento e o motor de renderização por trás deles vêm em uma única biblioteca para Delphi, C++Builder e Free Pascal; a lista completa de recursos está na página da PDF Library for Delphi