View Javadoc

1   package com.atlassian.selenium.visualcomparison.utils;
2   
3   import org.apache.velocity.VelocityContext;
4   
5   import javax.imageio.ImageIO;
6   import java.awt.*;
7   import java.util.List;
8   import java.awt.image.BufferedImage;
9   import java.io.File;
10  import java.io.FileOutputStream;
11  import java.io.IOException;
12  import java.io.OutputStreamWriter;
13  import java.util.ArrayList;
14  
15  public class ScreenshotDiff
16  {
17      private Screenshot oldScreenshot;
18      private Screenshot newScreenshot;
19      private String id;
20      private ScreenResolution resolution;
21      private BufferedImage diffImage;
22      private ArrayList<BoundingBox> boxes;
23      private List<BoundingBox> ignoreAreas;
24  
25      public ScreenshotDiff(Screenshot oldScreenshot, Screenshot newScreenshot,
26              String id, ScreenResolution resolution,
27              BufferedImage diffImage, ArrayList<BoundingBox> boxes, List<BoundingBox> ignoreAreas)
28      {
29          this.oldScreenshot = oldScreenshot;
30          this.newScreenshot = newScreenshot;
31          this.id = id;
32          this.resolution = resolution;
33          this.diffImage = diffImage;
34          this.boxes = boxes;
35          this.ignoreAreas = ignoreAreas;
36      }
37      
38      public List<BoundingBox> getDiffAreas()
39      {
40      	return this.boxes;
41      }
42  
43      public static class ReportDiffInfo
44      {
45          private String oldImageFile;
46          private String newImageFile;
47          private String diffImageFile;
48  
49          public ReportDiffInfo(String oldImageFile, String newImageFile, String diffImageFile)
50          {
51              this.oldImageFile = oldImageFile;
52              this.newImageFile = newImageFile;
53              this.diffImageFile = diffImageFile;
54          }
55  
56          public String getOldImageFile()
57          {
58              return oldImageFile;
59          }
60  
61          public String getNewImageFile()
62          {
63              return newImageFile;
64          }
65  
66          public String getDiffImageFile()
67          {
68              return diffImageFile;
69          }
70      }
71  
72      public boolean hasDifferences()
73      {
74          return boxes.size() > 0;
75      }
76  
77      public void writeDiffReport(String outputDir, String imageSubDir) throws Exception
78      {
79          if (!hasDifferences())
80          {
81              return;
82          }
83  
84          String imageOutputDir = outputDir + "/";
85          if (imageSubDir != null && !imageSubDir.equals(""))
86          {
87              imageOutputDir = imageOutputDir + imageSubDir + "/";
88          }
89          
90          ArrayList<ReportDiffInfo> reportDiffs = new ArrayList<ReportDiffInfo>();
91          int i = 0;
92          for (BoundingBox box : boxes)
93          {
94              Graphics2D graphics = diffImage.createGraphics();
95  
96              String oldImageFile = "boxold" + i + "-" + id + "." + resolution + ".png";
97              String newImageFile = "boxnew" + i + "-" + id + "." + resolution + ".png";
98              String diffImageFile = "boxdiff" + i + "-" + id + "." + resolution + ".png";
99              i++;
100 
101             writeSubImage(oldScreenshot.getImage(), box, imageOutputDir + oldImageFile);
102             writeSubImage(newScreenshot.getImage(), box, imageOutputDir + newImageFile);
103             writeSubImage(diffImage, box, imageOutputDir + diffImageFile);
104 
105             // Once we've written the sub-images, draw a black box around each of the bounding boxes on the diff.
106             graphics.setColor(Color.BLACK);
107             BasicStroke stroke = new BasicStroke(2.0f,
108                     BasicStroke.CAP_SQUARE,
109                     BasicStroke.JOIN_MITER,
110                     10.0f, new float[] { 10.0f }, 0.0f);
111             graphics.setStroke(stroke);
112             graphics.drawRect(box.getMarginLeft(), box.getMarginTop(), box.getMarginWidth(diffImage.getWidth() - 1), box.getMarginHeight(diffImage.getHeight() - 1));
113 
114             reportDiffs.add(new ReportDiffInfo(imageSubDir + "/" + oldImageFile, imageSubDir + "/" + newImageFile,
115                     imageSubDir + "/" + diffImageFile));
116         }
117         if (ignoreAreas != null)
118         {
119             for (BoundingBox ignoreArea : ignoreAreas)
120             {
121                 Graphics2D graphics = diffImage.createGraphics();
122                 // Draw an orange box around each of the ignored areas on the diff.
123                 graphics.setColor(Color.ORANGE);
124                 BasicStroke stroke = new BasicStroke(2.0f,
125                         BasicStroke.CAP_SQUARE,
126                         BasicStroke.JOIN_MITER,
127                         10.0f, new float[] { 10.0f }, 0.0f);
128                 graphics.setStroke(stroke);
129                 graphics.drawRect(ignoreArea.getLeft(), ignoreArea.getTop(), ignoreArea.getWidth(), ignoreArea.getHeight());
130             }
131         }
132         // Write the full diff image to the output directory.
133         String diffImageFile = "diff-" + id + "." + resolution + ".png";
134         ImageIO.write(diffImage, "png", new File(imageOutputDir + diffImageFile));
135         diffImage.flush();
136 
137         // Copy the full baseline image to the output directory.
138         String oldImageFile = "old-" + oldScreenshot.getFileName();
139         ImageIO.write(oldScreenshot.getImage(), "png", new File(imageOutputDir + oldImageFile));
140 
141         // Copy the new image to the output directory.
142         ImageIO.write(newScreenshot.getImage(), "png", new File(imageOutputDir + newScreenshot.getFileName()));
143 
144         VelocityContext context = ReportRenderer.createContext();
145         context.put("id", id);
146         context.put("resolution", resolution);
147         context.put("diffs", reportDiffs);
148         context.put("oldImageFile", imageSubDir + "/" + oldImageFile);
149         context.put("newImageFile", imageSubDir + "/" + newScreenshot.getFileName());
150         context.put("diffImageFile", imageSubDir + "/" + diffImageFile);
151         String report = ReportRenderer.render(context, "visual-regression-report-single.vm");
152 
153         OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(new File(outputDir + "/report-" + id + "-" + resolution + ".html")));
154         writer.append(report);
155         writer.close();
156     }
157 
158     private void writeSubImage(BufferedImage image, BoundingBox box, String outputPath) throws IOException
159     {
160         BufferedImage boxImage = image.getSubimage(box.getMarginLeft(), box.getMarginTop(), box.getMarginWidth(image.getWidth() - 1), box.getMarginHeight(image.getHeight() - 1));
161         ImageIO.write(boxImage, "png", new File(outputPath));
162     }
163 }