PDF/R, normalizado como ISO 23504-1, es el perfil PDF para documentos escaneados: cada página porta exactamente una imagen de banda y nada más. PDFium Component lo valida desde Delphi, Lazarus y C++Builder a través de ValidatePdfRCompliance, que lee un flujo y devuelve el nivel de conformidad más un conjunto de problemas concretos
El perfil existe porque los escáneres y los sistemas de captura de documentos necesitaban un objetivo más estrecho que PDF/A. Un PDF archivable puede contener cualquier cosa que la parte permita; un PDF raster es deliberadamente desnudo, de modo que cualquier lector conforme lo muestra de forma idéntica y cualquier escritor conforme puede producirlo a partir de un escaneo sin un motor de autoría
¿Qué prohíbe PDF/R que PDF/A permite?
Texto, en la práctica. Una página raster porta la imagen escaneada y nada más, así que un recurso de fuente en una página es una infracción —reportada como pvriFontForbidden bajo ISO 23504-1 §6.5.2—. Eso sorprende a quien añade una capa de texto OCR invisible para busquabilidad, que es algo normal y útil en un flujo PDF/A y simplemente no es PDF/R
La relación página-imagen es igual de estricta. El §6.5.1 hace que cada página sea exactamente una imagen de banda, así que pvriPageImageMismatch se dispara cuando el recuento de imágenes no coincide con el de páginas —una página sin imagen y una página con dos son ambas no conformes—. Y pvriBadMediaBox informa de una página cuyo MediaBox no tiene la forma [0 0 w h] (§6.5.3), porque un escaneo no tiene ningún motivo para asentarse en un origen desplazado
uses FPdfPdfr;
var
Src: TFileStream;
Res: TPdfRValidationResult;
begin
Src := TFileStream.Create('scan-batch-0142.pdf', fmOpenRead or fmShareDenyWrite);
try
Res := ValidatePdfRCompliance(Src);
if Res.IsCompliant then
Memo1.Lines.Add('PDF/R-1 conformant')
else
begin
if pvriFontForbidden in Res.Issues then
Memo1.Lines.Add('A page names a font resource; a raster page carries no text');
if pvriPageImageMismatch in Res.Issues then
Memo1.Lines.Add('Image count does not match page count');
if pvriForbiddenImageFilter in Res.Issues then
Memo1.Lines.Add('A strip image uses an encoding outside the white list');
end;
finally
Src.Free;
end;
end;
Qué codificaciones de imagen se permiten
Cuatro, y la lista blanca es corta por un motivo. El §6.6 admite /CCITTFaxDecode, /DCTDecode, /JPXDecode y /FlateDecode —fax bivalente, JPEG, JPEG 2000 y deflate sin pérdida, que entre todos cubren cualquier salida de escáner que importe—. Todo lo demás se informa como pvriForbiddenImageFilter, incluidos /LZWDecode, /RunLengthDecode, /ASCII85Decode, /ASCIIHexDecode, /JBIG2Decode y /Crypt
Dos de esos rechazos conviene entenderlos en lugar de memorizarlos. /JBIG2Decode comprime los escaneos bivalentes extremadamente bien y es perfectamente legal en PDF/A, pero su reconstrucción por diccionario de símbolos puede sustituir glifos visualmente parecidos —un modo de fallo documentado para dígitos escaneados— y un perfil cuyo propósito íntegro es la reproducción raster fiel no puede admitir ese riesgo. Los filtros ASCII se excluyen por el motivo opuesto: inflan el archivo sin añadir nada que un perfil raster necesite
Reglas de estructura que se disparan antes de leer ninguna página
PDF/R también constriñe el contenedor. pvriObjStmPresent informa de un flujo /Type /ObjStm, que el perfil prohíbe en redondo —los flujos de objeto complican el análisis simple y secuencial que un lector raster debe poder realizar—. pvriBadHeader informa de una cabecera fuera de %PDF-1.4 a 1.7 y %PDF-2.0, y pvriEncryptVersionMismatch informa de un archivo cifrado cuya cabecera no es %PDF-2.0, según §6.2.3
El catálogo y el diccionario Info están en lista blanca, no simplemente comprobados. pvriProhibitedCatalogEntry y pvriProhibitedInfoEntry se disparan con entradas fuera del conjunto permitido, y pvriInfoXmpMismatch se dispara cuando una entrada Info discrepa de su equivalente XMP. Un flujo /Metadata ausente en el catálogo, un /ID ausente en el trailer y un marcador de pie %PDF-raster-1.0 ausente tienen cada uno su propio problema
Por qué el registro de opciones de guardado omite Title y Author
TPdfRSaveOptions porta Creator, Producer, CreationDate, ModDate, DocumentId e InstanceId, y deliberadamente no tiene campo para Title, Author, Subject ni Keywords. Esas cuatro son las entradas que §6.4.3 prohíbe, así que un registro que las expusiera estaría invitando a los llamadores a escribir un archivo no conforme a través de una API conforme
Dos opciones booleanas controlan la limpieza al convertir un PDF existente. StripInfoOptionalEntries vale True por defecto y retira Title, Author, Subject, Keywords y Trapped del diccionario Info de origen. StripCatalogOptionalEntries también vale True por defecto y retira Names, Outlines, StructTreeRoot, OutputIntents, Lang y el resto, dejando únicamente la lista blanca del §6.3. Pon cualquiera a False y conservas las entradas —y pierdes la conformidad, que ocasionalmente es justamente lo que un llamador quiere para un archivo interno—
var
Opts: TPdfRSaveOptions;
Src, Dest: TFileStream;
begin
Opts := TPdfRSaveOptions.Default;
Opts.Creator := 'Capture Station 4';
Opts.Producer := 'PDFium Component';
Src := TFileStream.Create('scan-in.pdf', fmOpenRead or fmShareDenyWrite);
try
Dest := TFileStream.Create('scan-pdfr.pdf', fmCreate);
try
InjectPdfRMarkers(Src, Dest, Opts); // markers + metadata, not page content
finally
Dest.Free;
end;
finally
Src.Free;
end;
end;
Ten en cuenta lo que la inyección de marcadores no hace: añade metadatos e identificación, y no puede suministrar contenido de página. Una página de origen que no porte imagen de banda seguirá fallando pvriPageImageMismatch después de la inyección, porque la imagen ausente nunca fue un problema de metadatos
Dónde encaja PDF/R en un flujo de captura
Úsalo donde el entregable es el propio escaneo y la fidelidad es el contrato íntegro —imagen probatoria, captura de cheques y remesas, archivos de planos de ingeniería procedentes de un escáner de gran formato—. Usa PDF/A en cuanto el documento necesite texto buscable, etiquetado, adjuntos incrustados o cualquier otra cosa que el perfil raster elimine
Un arreglo habitual y viable es producir ambos: un PDF/R original que nunca cambia, y un derivado PDF/A con una capa OCR para recuperación. Los validadores son independientes, así que el mismo trabajo por lotes puede comprobar cada artefacto contra el perfil que de verdad reclama. Para el lado archivable de esa pareja, consulta las notas sobre la conformidad archivable PDF/A y la validación de preflight PDF/A, y para la salida orientada a impresión el recorrido por la validación de documentos PDF/X listos para imprimir
PDFium Component lleva el motor PDFium a Delphi, C++Builder y Lazarus con una API VCL y validadores de conformidad para PDF/A, PDF/X, PDF/E, PDF/UA y PDF/R; la página del producto PDFium Component lista las normas admitidas y las versiones de IDE