4848import com .itextpdf .text .Meta ;
4949import com .itextpdf .text .Rectangle ;
5050import com .itextpdf .text .io .RandomAccessSourceFactory ;
51- import com .itextpdf .text .pdf .*;
51+ import com .itextpdf .text .pdf .PRIndirectReference ;
52+ import com .itextpdf .text .pdf .PRStream ;
53+ import com .itextpdf .text .pdf .PRTokeniser ;
54+ import com .itextpdf .text .pdf .PdfAnnotation ;
55+ import com .itextpdf .text .pdf .PdfArray ;
56+ import com .itextpdf .text .pdf .PdfBoolean ;
57+ import com .itextpdf .text .pdf .PdfContentByte ;
58+ import com .itextpdf .text .pdf .PdfContentParser ;
59+ import com .itextpdf .text .pdf .PdfDictionary ;
60+ import com .itextpdf .text .pdf .PdfIndirectReference ;
61+ import com .itextpdf .text .pdf .PdfLiteral ;
62+ import com .itextpdf .text .pdf .PdfName ;
63+ import com .itextpdf .text .pdf .PdfNumber ;
64+ import com .itextpdf .text .pdf .PdfObject ;
65+ import com .itextpdf .text .pdf .PdfReader ;
66+ import com .itextpdf .text .pdf .PdfStamper ;
67+ import com .itextpdf .text .pdf .PdfString ;
68+ import com .itextpdf .text .pdf .RandomAccessFileOrArray ;
69+ import com .itextpdf .text .pdf .RefKey ;
5270import com .itextpdf .text .pdf .parser .ContentByteUtils ;
5371import com .itextpdf .text .pdf .parser .ImageRenderInfo ;
5472import com .itextpdf .text .pdf .parser .InlineImageInfo ;
89107import java .util .Map ;
90108import java .util .Set ;
91109import java .util .Stack ;
92- import java .util .StringTokenizer ;
93110import java .util .TreeSet ;
94-
111+ import java . util . regex . Pattern ;
95112import javax .xml .XMLConstants ;
96113import javax .xml .parsers .DocumentBuilder ;
97114import javax .xml .parsers .DocumentBuilderFactory ;
102119import javax .xml .transform .TransformerFactory ;
103120import javax .xml .transform .dom .DOMSource ;
104121import javax .xml .transform .stream .StreamResult ;
105-
106122import org .w3c .dom .Document ;
107123import org .w3c .dom .Element ;
108124import org .w3c .dom .Node ;
@@ -392,9 +408,17 @@ public void writeReportToXml(OutputStream stream) throws ParserConfigurationExce
392408
393409 private String gsExec ;
394410 private String compareExec ;
395- private final String gsParams = " -dNOPAUSE -dBATCH -sDEVICE=png16m -r150 -sOutputFile=<outputfile> <inputfile>" ;
411+ private static final String renderedImageExtension = "png" ;
412+ private static final String pageNumberPattern = "%03d" ;
413+ private static final Pattern pageListRegexp = Pattern .compile ("^(\\ d+,)*\\ d+$" );
414+ private static final String tempFilePrefix = "itext_gs_io_temp" ;
415+
416+
417+ private final String gsParams = " -dNOPAUSE -dBATCH -dSAFER -sDEVICE=" +
418+ renderedImageExtension + "16m -r150 -sOutputFile=<outputfile> <inputfile>" ;
396419 private final String compareParams = " \" <image1>\" \" <image2>\" \" <difference>\" " ;
397420
421+
398422 static private final String cannotOpenTargetDirectory = "Cannot open target directory for <filename>." ;
399423 static private final String gsFailed = "GhostScript failed for <filename>." ;
400424 static private final String unexpectedNumberOfPages = "Unexpected number of pages for <filename>." ;
@@ -462,7 +486,6 @@ private String compare(String outPath, String differenceImagePrefix, Map<Integer
462486 file .delete ();
463487 }
464488 }
465-
466489 File diffFile = new File (outPath + differenceImagePrefix );
467490 if (diffFile .exists ()) {
468491 diffFile .delete ();
@@ -499,38 +522,23 @@ private String compare(String outPath, String differenceImagePrefix, Map<Integer
499522 init (outPath + ignoredAreasPrefix + outPdfName , outPath + ignoredAreasPrefix + cmpPdfName );
500523 }
501524
525+ String cmpPdfTempCopy = null ;
526+ String replacementImagesDirectory = null ;
527+ String outPdfTempCopy = null ;
502528 if (targetDir .exists ()) {
503- String gsParams = this .gsParams .replace ("<outputfile>" , outPath + cmpImage ).replace ("<inputfile>" , cmpPdf );
504- Process p = runProcess (gsExec , gsParams );
505- BufferedReader bri = new BufferedReader (new InputStreamReader (p .getInputStream ()));
506- BufferedReader bre = new BufferedReader (new InputStreamReader (p .getErrorStream ()));
529+ replacementImagesDirectory = CompareToolUtil .createTempDirectory (tempFilePrefix );
530+ cmpPdfTempCopy = CompareToolUtil .createTempCopy (cmpPdf , tempFilePrefix , null );
531+ outPdfTempCopy = CompareToolUtil .createTempCopy (outPdf , tempFilePrefix , null );
532+ int exitValue = runGhostscriptAndGetExitCode (cmpPdfTempCopy , CompareToolUtil .buildPath (replacementImagesDirectory ,
533+ new String []{"cmp_" + tempFilePrefix + pageNumberPattern + "." + renderedImageExtension }));
507534 String line ;
508- while ((line = bri .readLine ()) != null ) {
509- System .out .println (line );
510- }
511- bri .close ();
512- while ((line = bre .readLine ()) != null ) {
513- System .out .println (line );
514- }
515- bre .close ();
516- if (p .waitFor () == 0 ) {
517- gsParams = this .gsParams .replace ("<outputfile>" , outPath + outImage ).replace ("<inputfile>" , outPdf );
518- p = runProcess (gsExec , gsParams );
519- bri = new BufferedReader (new InputStreamReader (p .getInputStream ()));
520- bre = new BufferedReader (new InputStreamReader (p .getErrorStream ()));
521- while ((line = bri .readLine ()) != null ) {
522- System .out .println (line );
523- }
524- bri .close ();
525- while ((line = bre .readLine ()) != null ) {
526- System .out .println (line );
527- }
528- bre .close ();
529- int exitValue = p .waitFor ();
530-
535+ if (exitValue == 0 ) {
536+ exitValue = runGhostscriptAndGetExitCode (outPdfTempCopy , CompareToolUtil .buildPath (replacementImagesDirectory ,
537+ new String []{tempFilePrefix + pageNumberPattern + "." + renderedImageExtension }));
531538 if (exitValue == 0 ) {
532- imageFiles = targetDir .listFiles (new PngFileFilter ());
533- cmpImageFiles = targetDir .listFiles (new CmpPngFileFilter ());
539+ File tempTargetDir = new File (replacementImagesDirectory );
540+ imageFiles = tempTargetDir .listFiles (new PngFileFilter ());
541+ cmpImageFiles = tempTargetDir .listFiles (new CmpPngFileFilter ());
534542 boolean bUnexpectedNumberOfPages = false ;
535543 if (imageFiles .length != cmpImageFiles .length ) {
536544 bUnexpectedNumberOfPages = true ;
@@ -543,6 +551,10 @@ private String compare(String outPath, String differenceImagePrefix, Map<Integer
543551 Arrays .sort (cmpImageFiles , new ImageNameComparator ());
544552 String differentPagesFail = null ;
545553 for (int i = 0 ; i < cnt ; i ++) {
554+ CompareToolUtil .copy (imageFiles [i ].getAbsolutePath (), CompareToolUtil .buildPath (targetDir .getAbsolutePath (),
555+ new String []{outPdfName + "-" + (i + 1 ) + "." + renderedImageExtension }));
556+ CompareToolUtil .copy (cmpImageFiles [i ].getAbsolutePath (), CompareToolUtil .buildPath (targetDir .getAbsolutePath (),
557+ new String []{"cmp_" + outPdfName + "-" + (i + 1 ) + "." + renderedImageExtension }));
546558 if (equalPages != null && equalPages .contains (i ))
547559 continue ;
548560 System .out .print ("Comparing page " + Integer .toString (i + 1 ) + " (" + imageFiles [i ].getAbsolutePath () + ")..." );
@@ -552,15 +564,20 @@ private String compare(String outPath, String differenceImagePrefix, Map<Integer
552564 is1 .close ();
553565 is2 .close ();
554566 if (!cmpResult ) {
555- if (compareExec != null && new File (compareExec ).exists ()) {
556- String compareParams = this .compareParams .replace ("<image1>" , imageFiles [i ].getAbsolutePath ()).replace ("<image2>" , cmpImageFiles [i ].getAbsolutePath ()).replace ("<difference>" , outPath + differenceImagePrefix + Integer .toString (i + 1 ) + ".png" );
557- p = runProcess (compareExec , compareParams );
558- bre = new BufferedReader (new InputStreamReader (p .getErrorStream ()));
567+ if (compareExec != null ) {
568+ String compareParams = this .compareParams .replace ("<image1>" , imageFiles [i ].getAbsolutePath ()).replace ("<image2>" ,
569+ cmpImageFiles [i ].getAbsolutePath ()).replace ("<difference>" ,
570+ CompareToolUtil .buildPath (replacementImagesDirectory , new String []{ "diff" +
571+ (i + 1 ) + "." + renderedImageExtension }));
572+
573+ Process p = CompareToolUtil .runProcess (compareExec , compareParams );
574+ BufferedReader bre = new BufferedReader (new InputStreamReader (p .getErrorStream ()));
559575 while ((line = bre .readLine ()) != null ) {
560576 System .out .println (line );
561577 }
562578 bre .close ();
563579 int cmpExitValue = p .waitFor ();
580+
564581 if (cmpExitValue == 0 ) {
565582 if (differentPagesFail == null ) {
566583 differentPagesFail = differentPages .replace ("<filename>" , outPdf ).replace ("<pagenumber>" , Integer .toString (i + 1 ));
@@ -581,8 +598,17 @@ private String compare(String outPath, String differenceImagePrefix, Map<Integer
581598 } else {
582599 System .out .println ("done." );
583600 }
601+ CompareToolUtil .removeFiles (new String [] {imageFiles [i ].getAbsolutePath (), cmpImageFiles [i ].getAbsolutePath ()});
602+ }
603+ File [] diffFiles = tempTargetDir .listFiles ();
604+ for (int i = 0 ; i < diffFiles .length ; i ++) {
605+ System .out .println (targetDir .getAbsolutePath ());
606+ CompareToolUtil .copy (diffFiles [i ].getAbsolutePath (), CompareToolUtil .buildPath (targetDir .getAbsolutePath (),
607+ new String []{differenceImagePrefix + "-" + (i + 1 ) + "." + renderedImageExtension }));
608+ diffFiles [i ].delete ();
584609 }
585- if (differentPagesFail != null ) {
610+ tempTargetDir .delete ();
611+ if (differentPagesFail != null ) {
586612 return differentPagesFail ;
587613 } else {
588614 if (bUnexpectedNumberOfPages )
@@ -597,20 +623,27 @@ private String compare(String outPath, String differenceImagePrefix, Map<Integer
597623 } else {
598624 return cannotOpenTargetDirectory .replace ("<filename>" , outPdf );
599625 }
600-
601626 return null ;
602627 }
603628
604- private Process runProcess (String execPath , String params ) throws IOException , InterruptedException {
605- StringTokenizer st = new StringTokenizer (params );
606- String [] cmdArray = new String [st .countTokens () + 1 ];
607- cmdArray [0 ] = execPath ;
608- for (int i = 1 ; st .hasMoreTokens (); ++i )
609- cmdArray [i ] = st .nextToken ();
610-
611- Process p = Runtime .getRuntime ().exec (cmdArray );
612-
613- return p ;
629+ private int runGhostscriptAndGetExitCode (String replacementPdf , String replacementImagesDirectory )
630+ throws IOException , InterruptedException {
631+ String gsParams = this .gsParams .replace ("<outputfile>" , replacementImagesDirectory ).
632+ replace ("<inputfile>" , replacementPdf );
633+ Process p = CompareToolUtil .runProcess (gsExec , gsParams );
634+ BufferedReader bri = new BufferedReader (new InputStreamReader (p .getInputStream ()));
635+ BufferedReader bre = new BufferedReader (new InputStreamReader (p .getErrorStream ()));
636+ String line ;
637+ while ((line = bri .readLine ()) != null ) {
638+ System .out .println (line );
639+ }
640+ bri .close ();
641+ while ((line = bre .readLine ()) != null ) {
642+ System .out .println (line );
643+ }
644+ bre .close ();
645+ int exitValue = p .waitFor ();
646+ return exitValue ;
614647 }
615648
616649 public String compare (String outPdf , String cmpPdf , String outPath , String differenceImagePrefix , Map <Integer , List <Rectangle >> ignoredAreas ) throws IOException , InterruptedException , DocumentException {
@@ -1367,9 +1400,12 @@ private void init(String outPdf, String cmpPdf) {
13671400 this .cmpPdf = cmpPdf ;
13681401 outPdfName = new File (outPdf ).getName ();
13691402 cmpPdfName = new File (cmpPdf ).getName ();
1370- outImage = outPdfName + "-%03d.png" ;
1371- if (cmpPdfName .startsWith ("cmp_" )) cmpImage = cmpPdfName + "-%03d.png" ;
1372- else cmpImage = "cmp_" + cmpPdfName + "-%03d.png" ;
1403+ outImage = outPdfName + pageNumberPattern + "." + renderedImageExtension ;
1404+ if (cmpPdfName .startsWith ("cmp_" )) {
1405+ cmpImage = cmpPdfName + pageNumberPattern + "." + renderedImageExtension ;
1406+ } else {
1407+ cmpImage = "cmp_" + cmpPdfName + pageNumberPattern + "." + renderedImageExtension ;
1408+ }
13731409 }
13741410
13751411 private boolean compareStreams (InputStream is1 , InputStream is2 ) throws IOException {
@@ -1396,7 +1432,7 @@ public boolean accept(File pathname) {
13961432 String ap = pathname .getAbsolutePath ();
13971433 boolean b1 = ap .endsWith (".png" );
13981434 boolean b2 = ap .contains ("cmp_" );
1399- return b1 && !b2 && ap . contains ( outPdfName ) ;
1435+ return b1 && !b2 ;
14001436 }
14011437 }
14021438
@@ -1405,7 +1441,7 @@ public boolean accept(File pathname) {
14051441 String ap = pathname .getAbsolutePath ();
14061442 boolean b1 = ap .endsWith (".png" );
14071443 boolean b2 = ap .contains ("cmp_" );
1408- return b1 && b2 && ap . contains ( cmpPdfName ) ;
1444+ return b1 && b2 ;
14091445 }
14101446 }
14111447
@@ -1500,6 +1536,4 @@ public InputSource resolveEntity(String publicId, String systemId) throws SAXExc
15001536 return new InputSource (new StringReader ("" ));
15011537 }
15021538 }
1503-
1504-
15051539}
0 commit comments