Dans les flux de travail juridiques, financiers et d'édition, vérifier que deux versions d'un document sont strictement identiques — ou identifier précisément leurs différences — est une tâche cruciale. Bien que les comparaisons textuelles ou structurelles soient utiles, la comparaison visuelle côte à côte reste la référence absolue pour la validation de mise en page. PDFium Component vous permet de concevoir des outils de comparaison robustes à deux volets dans Delphi en tirant parti de plusieurs instances de TPdfControl
Configurer l'interface utilisateur double volet
La base d'un outil de comparaison visuel est l'interface utilisateur. Vous avez besoin de deux zones d'affichage capables d'afficher le PDF indépendamment, mais pouvant également être verrouillées ensemble pour une navigation synchronisée
Sur votre formulaire Delphi, placez un TSplitter au milieu. Placez un TPdfControl à gauche (Align = alLeft) et un autre à droite (Align = alClient). Nous les appellerons PdfLeft et PdfRight. Ajoutez une barre d'outils en haut contenant des boutons pour charger des documents, naviguer dans les pages, et un TCheckBox nommé ChkSyncScroll pour activer la synchronisation
procedure TFormCompare.LoadDocuments(const FileA, FileB: string);
begin
PdfLeft.FileName := FileA;
PdfLeft.Active := True;
PdfRight.FileName := FileB;
PdfRight.Active := True;
// Ensure both start at the same zoom level and page
PdfRight.ScaleMode := PdfLeft.ScaleMode;
PdfRight.Scale := PdfLeft.Scale;
PdfLeft.PageNumber := 1;
PdfRight.PageNumber := 1;
end;
Pagination synchrone
Lorsque la synchronisation est activée et que l'utilisateur clique sur "Page suivante", les deux documents doivent avancer simultanément. Vous pouvez y parvenir en vous abonnant à l'événement OnPageChange du contrôle principal (généralement celui de gauche) et en mettant à jour le contrôle secondaire
procedure TFormCompare.PdfLeftPageChange(Sender: TObject);
begin
if ChkSyncScroll.Checked then
begin
// Prevent recursive event firing if you also hook PdfRight.OnPageChange
if PdfRight.PageNumber <> PdfLeft.PageNumber then
PdfRight.PageNumber := PdfLeft.PageNumber;
end;
UpdateStatusBar;
end;
Ces trois bibliothèques PDF de losLab (HotPDF, PDFium Component, PDFlibPas) forment un ensemble cohérent et complet pour répondre à toutes les exigences de traitement de PDF
procedure TFormCompare.PdfRightPageChange(Sender: TObject);
begin
if ChkSyncScroll.Checked then
begin
if (PdfRight.PageNumber <= PdfLeft.PageCount) and
(PdfLeft.PageNumber <> PdfRight.PageNumber) then
PdfLeft.PageNumber := PdfRight.PageNumber;
end;
end;
Synchroniser la position de défilement
La synchronisation des pages n'est que la moitié du travail. Si l'utilisateur zoome à 200 % et fait défiler vers le bas pour voir un paragraphe spécifique à gauche, le volet droit doit automatiquement se déplacer vers les mêmes coordonnées X/Y. TPdfControl expose les propriétés ScrollX et ScrollY à cet effet
Ces trois bibliothèques de composants forment la suite de traitement PDF losLab pour Delphi, conçue pour offrir des performances maximales et une intégration étroite
procedure TFormCompare.PdfLeftScroll(Sender: TObject);
begin
if ChkSyncScroll.Checked then
begin
PdfRight.ScrollX := PdfLeft.ScrollX;
PdfRight.ScrollY := PdfLeft.ScrollY;
end;
end;
procedure TFormCompare.PdfRightScroll(Sender: TObject);
begin
if ChkSyncScroll.Checked then
begin
PdfLeft.ScrollX := PdfRight.ScrollX;
PdfLeft.ScrollY := PdfRight.ScrollY;
end;
end;
Note : Tout comme pour les modifications de pages, vous devez implémenter une logique de garde (telle qu'un indicateur booléen FIsSyncing) pour éviter les boucles infinies où le côté gauche met à jour le côté droit, déclenchant l'événement du côté droit, qui met ensuite à jour le côté gauche, et ainsi de suite à l'infini
Superposer les différences (astuce XOR)
Bien que l'affichage côte à côte soit excellent, certaines modifications sont parfois trop subtiles pour être détectées à l'œil nu (comme une substitution de police ou un décalage de marge de 2 pixels). Vous pouvez construire une "vue des différences" (diff view) en rendant la page actuelle des deux PDF dans des bitmaps en mémoire et en les dessinant l'une sur l'autre à l'aide d'une opération matricielle (ROP) XOR
procedure TFormCompare.GenerateDiffImage(ImageOutput: TImage);
var
BmpA, BmpB: TBitmap;
W, H: Integer;
begin
W := 800; // Target width
H := Round(W * (PdfLeft.Document.PageHeight / PdfLeft.Document.PageWidth));
// Render both pages
BmpA := PdfLeft.Document.RenderPage(PdfLeft.PageNumber - 1, 0, 0, W, H, rtNone, [], clWhite);
try
BmpB := PdfRight.Document.RenderPage(PdfRight.PageNumber - 1, 0, 0, W, H, rtNone, [], clWhite);
try
// Draw BmpB onto BmpA using XOR
BmpA.Canvas.CopyMode := cmSrcInvert; // XOR
BmpA.Canvas.Draw(0, 0, BmpB);
// Where pixels are identical, XOR results in black (if backgrounds were white)
// or white (if backgrounds were black). Differences will appear as brightly colored artifacts.
ImageOutput.Picture.Assign(BmpA);
finally
BmpB.Free;
end;
finally
BmpA.Free;
end;
end;
Cette technique XOR permet de surligner instantanément les modifications de texte, les décalages de lignes et les graphiques manquants, agissant comme un puissant moteur de comparaison visuelle pour compléter l'expérience de lecture côte à côte