A PDF Library for Delphi aceita imagens AVIF, HEIF e JPEG XL como entrada por meio de AddModernImageFromFile e de suas variantes de stream e string, preservando o alfa, o perfil ICC incorporado e os canais de 16 bits no caminho até o objeto de imagem do PDF. A detecção de formato acontece em uma leitura limitada de número mágico, e a decodificação passa por um backend substituível, então nada externo é invocado para um arquivo que na verdade não é um desses formatos
Esses formatos chegaram aos fluxos de trabalho de documentos por meio de celulares. O iOS produz HEIC por padrão há anos, dispositivos Android produzem AVIF, e um técnico de campo fotografando uma peça danificada envia uma imagem que um gerador de relatórios em PDF construído em 2015 simplesmente não consegue abrir. O caminho de fallback genérico, decodificando por meio de um bitmap de plataforma, produz de forma confiável cor de 8 bits e perde o alfa e o perfil de cor no caminho
O que o caminho de imagem moderna preserva que uma conversão para bitmap perde?
Três coisas, e cada uma tem um fluxo de trabalho que depende dela. O alfa sobrevive, o que importa para logotipos e recortes de produto compostos sobre o conteúdo da página. O perfil ICC sobrevive, o que importa para qualquer coisa que será impressa ou combinada por cor. E os canais de 16 bits sobrevivem, o que importa para imagens médicas e científicas onde a quantização de 8 bits destrói exatamente as gradações para as quais a imagem foi capturada
Passar uma imagem por um bitmap de plataforma perde as três coisas em uma única etapa, e faz isso silenciosamente: o PDF resultante parece aproximadamente correto, e ninguém percebe até que uma gráfica pergunte por que o vermelho corporativo está errado. O valor de opção 8 nas chamadas de imagem moderna é a flag que mantém alfa, ICC e canais de 16 bits juntos, e é o padrão para essas chamadas
Adicionando uma imagem a uma página
A chamada retorna um identificador de imagem, que é então selecionado e desenhado, ou desenhado e liberado em uma única etapa:
uses
PDFlibrary, PDFlibModernImage;
var
Lib: TPDFlib;
ImageID: Integer;
begin
Lib := TPDFlib.Create;
try
Lib.NewDocument;
Lib.SetPageSize('A4');
Lib.NewPage;
// Options = 8 mantém alfa, ICC e canais de 16 bits
ImageID := Lib.AddModernImageFromFile('site-photo.heic', 8);
if ImageID > 0 then
Lib.DrawImageAndRelease(ImageID, 40, 40, 515, 340)
else
Lib.DrawText(40, 40, 'image could not be decoded');
Lib.SaveToFile('inspection-report.pdf');
finally
Lib.Free;
end;
end;
A detecção precede a decodificação e é deliberadamente restrita. A biblioteca lê um cabeçalho limitado, reconhece as marcas do formato de arquivo de mídia base ISO que identificam AVIF e HEIF, e reconhece tanto as assinaturas brutas quanto as de contêiner do JPEG XL, e então restaura a posição do stream do chamador. Uma entrada desconhecida ou disfarçada nunca chega ao codec externo, o que impede que um executável renomeado seja entregue a um decodificador como se fosse uma imagem
Onde a decodificação realmente acontece?
Formatos de imagem modernos são codecs grandes e complexos, e colocar um deles dentro de uma biblioteca de PDF seria uma escolha de design estranha. O backend padrão carrega dinamicamente, em processo, um módulo MagickWand implantável e o procura em uma ordem documentada: um arquivo ou diretório explícito que você define, variáveis de ambiente, o diretório do executável e o caminho de busca do sistema
Aplicações que já entregam um decodificador, ou que não podem carregar nenhum módulo externo, registram seu próprio callback em vez disso. O contrato é pequeno: leia o stream de entrada, grave um PNG no stream de saída, respeite a orientação solicitada:
function MyDecoder(InStream, OutPNG: TStream;
ImageFormat: TPDFlibModernImageFormat;
ApplyOrientation: Boolean): Boolean;
begin
// Decodifique InStream com seu próprio codec e grave os bytes PNG em OutPNG
Result := DecodeWithBundledCodec(InStream, OutPNG,
ImageFormat, ApplyOrientation);
end;
begin
RegisterModernImageDecoderBackend(MyDecoder);
// ... adiciona imagens ...
ClearModernImageDecoderBackend; // volta ao backend padrão
end;
A implantação ganha uma conveniência e uma restrição deliberada. Se o diretório do codec contiver um subdiretório modules\coders, a biblioteca preenche as variáveis de ambiente de codec que esse layout exige, mas apenas quando a aplicação hospedeira ainda não as definiu. Uma aplicação com sua própria estratégia de implantação de runtime mantém a dela
Por que passar por PNG no meio do caminho?
Fazer a ponte por um PNG em memória, em vez de um buffer de pixels bruto, parece uma etapa extra e na verdade é a mais barata correta. O PNG expressa tudo o que precisa sobreviver, alfa, tipo de cor, profundidade de bits e um perfil ICC incorporado, e a biblioteca já tem um caminho maduro e bem testado de PNG até um objeto de imagem de PDF com os filtros e o espaço de cor corretos. Reutilizá-lo significa que os formatos modernos herdam anos de trabalho de correção, em vez de ganhar uma implementação paralela
A ponte é inteiramente em memória, então nenhum arquivo temporário é criado e nenhuma limpeza é necessária em caso de falha. Um detalhe exigiu tratamento explícito: algumas conversões descartam o perfil ICC ao mudar de formato. O backend, portanto, captura o perfil de origem antes da troca de formato, comprime-o com Flate, constrói um chunk iCCP válido com um CRC recalculado, e remove qualquer chunk sRGB que entraria em conflito com ele. Em testes, um AVIF decodificado manteve RGBA de 16 bits com alfa de 16 bits, e o perfil extraído do PDF resultante correspondeu ao perfil de origem byte a byte em 60.960 bytes
Notas práticas antes de ativar isso em produção
Verifique a disponibilidade na inicialização, não na primeira fotografia. ModernImageCodecAvailable informa se um backend pode ser usado, e SetModernImageCodecLibrary aponta para um arquivo ou diretório explícito quando sua implantação coloca o codec em algum lugar não padrão:
Lib.SetModernImageCodecLibrary('C:\MyApp\codecs');
if Lib.ModernImageCodecAvailable = 0 then
Log('modern image input unavailable - HEIC and AVIF will be refused');
Observe o tamanho de arquivo do resultado. Uma imagem RGBA de 16 bits com um perfil incorporado é um objeto de imagem de PDF grande, e um relatório com quarenta delas será grande. Quando o documento se destina a visualização em tela em vez de impressão, reduzir a resolução (downsampling) antes de incorporar é a escolha certa, e as alavancas gerais de tamanho são abordadas em otimização de tamanho de arquivo PDF
Por fim, decida a política de cor deliberadamente. Manter o perfil de origem é correto para arquivamento e trabalho de impressão; converter para um espaço de todo o documento é correto quando um conjunto misto de fotografias precisa parecer consistente, e a rota de conversão é descrita em recolorindo um documento para outro espaço de cor. Se você precisa confirmar o que realmente entrou no arquivo, o caminho de inspeção em extração de texto, imagem e fonte relata os objetos de imagem que um documento carrega
Entrada de imagem moderna, gerenciamento de cor e otimização de imagem fazem parte da mesma biblioteca para Delphi, C++Builder e Free Pascal; a lista completa de recursos está na página da PDF Library for Delphi