/*
* Software Name : ATK
*
* Copyright (C) 2007 - 2012 France Télécom
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ------------------------------------------------------------------
* File Name : Model.java
*
* Created : 04/06/2009
* Author(s) : France Telecom
*/
package com.orange.atk.compModel;
import java.awt.Color;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Observable;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.imageio.ImageIO;
import javax.media.jai.iterator.RandomIter;
import javax.media.jai.iterator.RandomIterFactory;
import javax.swing.JOptionPane;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.orange.atk.platform.Platform;
import com.sun.org.apache.xml.internal.serialize.OutputFormat;
import com.sun.org.apache.xml.internal.serialize.XMLSerializer;
/**
* class for the Model in MVC architecture for images comparison
*
* @author bvqj2105
*/
public class Model extends Observable {
public static final String AUTOMATIC_PASS ="Passed";
public static final String MANUALLY_PASS ="Manually Passed";
public static final String FAIL ="Failed";
private String refDirectory="src/images/ref";
private String testDirectory="src/images/test";
private Document resultDoc;
private Element resultRootElement;
private Document useddoc;
private static final String xmlReportName = "ComparisonScreenShotReport.xml";
private static final String maskXmlFileName = "masks.xml";
private static final String refXmlFileName = "refDescription.xml";
private static final String pdfReportName = "ComparisonScreenShotReport.pdf";
private HashMap<String, ImageFileMask> refImage;
private HashMap<Integer, Mask> refMask;
private int maskHeight;
private int maskWidth;
private int imageHeight;
private int imageWidth;
private HashMap<String,String> refScDesc;
private ArrayList<ComparaisonCouple> couples;
private ProgressListener progressListener;
/** Creates a new instance of Model3
* @throws IOException */
public Model(String refDir, String testDir, ProgressListener progressListener) throws IllegalArgumentException {
refDirectory=refDir;
testDirectory=testDir;
this.progressListener = progressListener;
couples = new ArrayList<ComparaisonCouple>();
refImage = new HashMap<String, ImageFileMask>();
refMask = new HashMap<Integer, Mask>();
refScDesc = new HashMap<String, String>();
// initialize the model DOM and the ListModels
initModel();
//create the XML report file in the test directory
printToFile(resultDoc, getTestDirectory()+Platform.FILE_SEPARATOR+xmlReportName);
}
public Model(String refDir, String testDir) throws IllegalArgumentException {
this(refDir, testDir, null);
}
public void setProgressListener(ProgressListener listener) {
progressListener = listener;
}
/**
* @param name
* @return the Element from the model DOM corresponding with the image whose name is in parameter
* @return null if not exists
*/
public Element getElementFromDOM(String name){
NodeList nl = resultRootElement.getElementsByTagName("Test");
int i = 0;
while ( i < nl.getLength() && !nl.item(i).getAttributes().getNamedItem("name").getNodeValue().equals(name)) {
// //Logger.getLogger(this.getClass() ).debug(nl.item(i).getAttributes().getNamedItem("name").getNodeValue());
i++;
}
if (nl.item(i)!=null)
return (Element) nl.item(i).getParentNode();// The <img> Element corresponding.
else return null;
}
/**
* @return the number of failed couples
*/
public int getNbFail() {
int nbFail=0;
for (ComparaisonCouple cp : couples)
if(cp.getPass().equals(FAIL))
nbFail++;
return nbFail;
}
/**
* @return the number of images couples
*/
public int getNbImages() {
return couples.size();
}
/**
* @return the path to reference directory
*/
public String getRefDirectory(){
//Logger.getLogger(this.getClass() ).debug("Model.getRefDiredtory");
return refDirectory;
}
/**
* re-initiate the model with this new parameter
* @param rep - the path to reference directory
*/
public void setDirectories(String ref, String test) throws IllegalArgumentException {
//Logger.getLogger(this.getClass() ).debug("Model.setRefDirectory");
refDirectory =ref;
testDirectory=test;
initModel();
setChanged();
notifyObservers();
}
/**
* @return the path to reference directory
*/
public String getTestDirectory(){
return testDirectory;
}
public String getPdfReportName() {
return pdfReportName;
}
public int getMaskHeight() {
return maskHeight;
}
public int getMaskWidth() {
return maskWidth;
}
public ImageFileMask getRefImage(String id) {
return refImage.get(id);
}
public Set<String> getListRefImage() {
return refImage.keySet();
}
public Mask getRefMask(Integer id) {
return refMask.get(id);
}
public void addRefMask(Mask mask) {
refMask.put(mask.getId(), mask);
}
public void setRefScDescription(String id, String description) {
if (refScDesc.get(id) == null || !refScDesc.get(id).equals(description)) {
refScDesc.put(id, description);
this.saveRefDescriptions();
}
}
public String getRefScDescription(String id) {
String desc = refScDesc.get(id);
if (desc == null) return "";
else return desc;
}
public void removeRefMask(Mask mask) {
refMask.remove(mask);
}
public Set<Integer> getListKeysetMask() {
return refMask.keySet();
}
public Mask[] getListMask() {
Mask[] listMask = new Mask[getListKeysetMask().size()];
int i = 0;
for(int Id : getListKeysetMask()){
listMask[i] = getRefMask(Id);
i++;
}
return listMask;
}
public int getImageHeight() {
return imageHeight;
}
/**
* recompute differences between the two images from the i-th couple
* @param cp ComparaisonCouple
* @return 0 if there is no differences, >0 else
* @throws IOException
*/
public double recompute(ComparaisonCouple cp) throws IOException {
//Logger.getLogger(this.getClass() ).debug("Model.recalcul");
return calcDistance(ImageIO.read(cp.getImgRef().getImage()),
ImageIO.read(cp.getImgTest()),
cp.getMaskSum(),cp.getDif());
}
/**initialize the model :</br>
* - listModels</br>
* - DOM File</br>
* - arrays masked and different set the currentIndex to 0
*/
private void initModel() throws IllegalArgumentException {
//Logger.getLogger(this.getClass() ).debug("Model.initModel");
File [] ref= getImageFilesFromDirectory(refDirectory);
File [] test= getImageFilesFromDirectory(testDirectory);
//First we need to compare to be sure all the image have the same size
//We compare all the images to the first one, and report error if an image is different
for(int i = 1; i < ref.length; i++){
if(!fileSameSize(ref[0], ref[i])){
String message="2 files have different sizes, " +
"you must change the folders to compare.\n"+
ref[0].getName()+" and\n"+ref[i].getName()+" have different size.";
JOptionPane.showMessageDialog(null,message);
Logger.getLogger(this.getClass()).error(message);
throw new IllegalArgumentException(message);
}
}
for(int i = 0; i < test.length; i++){
if(!fileSameSize(ref[0], test[i])){
String message="2 files have different sizes, " +
"you must change the folders to compare.\n"+
ref[0].getName()+" and\n"+test[i].getName()+" have different size.";
JOptionPane.showMessageDialog(null,message);
Logger.getLogger(this.getClass()).error(message);
throw new IllegalArgumentException(message);
}
}
//We had all the reference image in the table
for(File refFile : ref)
refImage.put(refFile.getName(), new ImageFileMask(refFile,this));
initRefDescriptions(refDirectory);
initMaskOfReferencesImage(refDirectory,ref);
//saveMaskAssociations();
try {
resultDoc=DocumentBuilderFactory.newInstance()
.newDocumentBuilder().newDocument();
resultRootElement=resultDoc.createElement("Report");
if(ref.length==0){
Logger.getLogger(this.getClass() ).warn("Warning : one of the directory is empty.");
throw new IllegalArgumentException("one of directory is empty");
}
int [] testToRef=new int[test.length];
String testName;
progressListener.setProgressValue(0);
for (int i=0;i<test.length; i++){
testName = test[i].getName().split("-")[0];
int j = 0;
boolean refFound = false;
while(j<ref.length && !refFound){
String refName = ref[j].getName();
String refNamePrefix = refName;
// refere-000.png -->refere
Pattern pat = Pattern.compile("([^-]*)-?[0-9]*\\.(png|jpg|jpeg|gif)");
Matcher mtc = pat.matcher(refName);
if(mtc.matches())
refNamePrefix = mtc.group(1);
if (refNamePrefix.equals(testName)){
//found the couple
testToRef[i]=j;
refFound=true;
//add an element in Doc report
Element e = resultDoc.createElement("img");
Element eRef=resultDoc.createElement("Ref");
eRef.setAttribute("name", ref[j].getName());
eRef.setTextContent(ref[j].getAbsolutePath());
e.appendChild(eRef);
Element eTest=resultDoc.createElement("Test");
eTest.setAttribute("name", test[i].getName());
eTest.setTextContent(test[i].getAbsolutePath());
e.appendChild(eTest);
Element ePass=resultDoc.createElement("Pass");
String pass ="";
Boolean2D different = new Boolean2D(maskWidth,maskHeight);
try {
if (calcDistance(
ImageIO.read(ref[j]),
ImageIO.read(test[i]) ,
refImage.get(refName).getMaskSum() ,
different)!=0){
pass=FAIL;
}
else{
pass=AUTOMATIC_PASS;
}
}catch (IOException exception) {
exception.printStackTrace();
}
ePass.setTextContent(pass);
e.appendChild(ePass);
Element eComm=resultDoc.createElement("Comment");
eComm.setTextContent(""+test[i].getName());
e.appendChild(eComm);
Element eMask=resultDoc.createElement("Mask");
eMask.setTextContent(""+refImage.get(refName).getMaskSum().getId()+" - "+refImage.get(refName).getMaskSum().getLabel());
e.appendChild(eMask);
resultRootElement.appendChild(e);
couples.add(new ComparaisonCouple(refName, test[i], different ,pass, this));
}
j++;
}
if (!refFound){
Logger.getLogger(this.getClass() ).warn("Warning : No Reference image was found for this image <"+testName+" : "+test[i].getAbsolutePath()+">." +
"This image will not be considered in the comparator. The association is made with names.");
}
if (progressListener !=null) {
int pourcent = (int)(((double)100 / (double)test.length) * (double)(i+1));
progressListener.setProgressValue(pourcent);
}
}
resultDoc.appendChild(resultRootElement);
} catch (ParserConfigurationException e1) {
e1.printStackTrace();
}
}
/**
* Compare the size of two images from a file
* @param File1 pointing to an image
* @param File2 pointing to an image
* @return <b>True</b> if the two images have the same size.
*/
Boolean fileSameSize(File File1,File File2){
RenderedImage Image1 = null;
RenderedImage Image2 = null;
try {
Image1 = ImageIO.read(File1);
Image2 = ImageIO.read(File2);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
return imageSameSize(Image1, Image2);
}
/**
* Compare the size of two images
* @param Image1
* @param Image2
* @return <b>True</b> if the two images have the same size.
*/
Boolean imageSameSize(RenderedImage Image1,RenderedImage Image2){
return (Image1.getHeight()==Image2.getHeight() &&
Image1.getWidth()==Image2.getWidth());
}
/**
* read XML
* @param refDirectory
*/
private void initRefDescriptions(String refDirectory) {
try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
File reffile = new File(refDirectory+Platform.FILE_SEPARATOR+refXmlFileName);
if (reffile.exists() ){
Document refdoc= builder.parse(reffile);
//find masks
NodeList scNode = refdoc.getElementsByTagName("Screenshot");
for (int i=0; i<scNode.getLength(); i++) {
Node n = scNode.item(i);
NodeList l = n.getChildNodes();
String name = null;
String desc = null;
for (int j =0; j < l.getLength(); j++) {
Node r= l.item(j);
if (r.getNodeName().equals("Name")) name = r.getTextContent();
else if (r.getNodeName().equals("Description")) desc = r.getTextContent();
}
if (name!=null && desc!=null) refScDesc.put(name,desc);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* read XML
* @param refDirectory
*/
private void initMaskOfReferencesImage(String refDirectory, File[] image) {
// Initialize the DOM with masks references in association with each couple of images
try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
File maskfile = new File(refDirectory+Platform.FILE_SEPARATOR+maskXmlFileName);
File[] ref = getImageFilesFromDirectory(refDirectory);
refMask = new HashMap<Integer, Mask>();
RenderedImage imageRef = null;
imageRef = ImageIO.read(ref[0]);
//We calculate the size of mask corresponding to the image
imageWidth = imageRef.getWidth();
double maskRefWidth = (double)imageWidth/(double)(2*Mask.getCELL_HALF_SIZE());
if (maskRefWidth - (int)maskRefWidth > 0)
maskRefWidth++;
imageHeight = imageRef.getHeight();
double maskRefHeight = (double)imageHeight/(double)(2*Mask.getCELL_HALF_SIZE());
if (maskRefHeight - (int)maskRefHeight > 0)
maskRefHeight++;
if (maskfile.exists() ){
Document maskdoc= builder.parse(maskfile);
//Get the size of the mask
NodeList maskSize = maskdoc.getElementsByTagName("UsedMask");
maskHeight = (int) Integer.parseInt(maskSize.item(0).getAttributes().getNamedItem("height").getNodeValue());
maskWidth = (int) Integer.parseInt(maskSize.item(0).getAttributes().getNamedItem("width").getNodeValue());
//Check if they have the correct size for the masks
if(((int)maskRefWidth!=maskWidth)||((int)maskRefHeight!=maskHeight)){
Logger.getLogger(this.getClass() ).debug("The size of the mask is incorrect: x="+
maskWidth+" - y="+maskHeight+" The image is:"+maskRefWidth+" - y="+maskRefHeight);
maskWidth = (int)maskRefWidth;
maskHeight = (int)maskRefHeight;
return;
}
//find masks
NodeList masksNode = maskdoc.getElementsByTagName("Mask");
for (int i=0; i<masksNode.getLength(); i++) {
Node n = masksNode.item(i);
int id = (int) Integer.parseInt(n.getAttributes().getNamedItem("id").getNodeValue());
String label= n.getAttributes().getNamedItem("label").getNodeValue();
NodeList listCell = n.getChildNodes();
Mask mask = new Mask(label, id, maskWidth, maskHeight);
for (int j =0; j < listCell.getLength(); j++) {
Node c= listCell.item(j);
if(c.hasAttributes()){
int x=(int) Integer.parseInt(c.getAttributes().getNamedItem("x").getNodeValue());
int y=(int) Integer.parseInt(c.getAttributes().getNamedItem("y").getNodeValue());
if((x>maskWidth)||(x<0)||(y>maskHeight)||(y<0))
Logger.getLogger(this.getClass() ).debug("Cell (x="+x+" - y="+y+" in mask "+label+" out of range");
else
mask.setCell(x, y, true);
}
}
refMask.put(id,mask);
}
//associate image reference and mask
NodeList imgs = maskdoc.getElementsByTagName("img");
for (int i = 0; i < imgs.getLength(); i++) {
String imgId = imgs.item(i).getAttributes().getNamedItem("id").getNodeValue();
String maskValues = imgs.item(i).getAttributes().getNamedItem("mask").getNodeValue();
if(!maskValues.equals("")){
String [] maskId = maskValues.split(",+");
for(String Id : maskId){
refImage.get(imgId).addMask(Integer.valueOf(Id));
}
}
}
}else{
maskWidth = (int)maskRefWidth;
maskHeight = (int)maskRefHeight;
return;
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* This method get all image files in the same directory as the reference.
* Just for kicks include also the reference image.
*/
private File[] getImageFilesFromDirectory(String dirPath)
{
File dir = new File(dirPath);
// List all the image files in that directory.
File[] files = dir.listFiles(new ImageFileFilter());
for (int i=1; i<files.length; i++) {
String filename = files[i].getName();
String timestamp = getImageTimestamp(filename);
if (timestamp != null) {
int j=i-1;
while (j>=0 && timestamp.compareTo(getImageTimestamp(files[j].getName()))<0) j--;
if (j<i-1) {
File fileToSort = files[i];
for (int k=i; k>j+1; k--) {
files[k] = files[k-1];
}
files[j+1] = fileToSort;
}
}
}
return files;
}
private String getImageTimestamp(String imageName) {
int begin = imageName.lastIndexOf("-");
int end = imageName.lastIndexOf(".");
if (begin!= -1 && end != -1) return imageName.substring(begin, end);
return null;
}
/*
* This method calculates and returns signature vectors for the input image.
*/
private Color[][] calcSignature(RenderedImage i)
{
// Get memory for the signature.
Color[][] sig = new Color[i.getWidth()/(2*Mask.getCELL_HALF_SIZE())+1][i.getHeight()/(2*Mask.getCELL_HALF_SIZE())+1];
// For each of the 25 signature values average the pixels around it.
// Note that the coordinate of the central pixel is in proportions.
//float[] prop = new float[]
// {1f / 10f, 3f / 10f, 5f / 10f, 7f / 10f, 9f / 10f};
for (int x = 0; x< i.getWidth()/(2*Mask.getCELL_HALF_SIZE())+1; x++)
for (int y = 0; y < i.getHeight()/(2*Mask.getCELL_HALF_SIZE())+1; y++)
sig[x][y] = averageAround(i, (x*2+1)*Mask.getCELL_HALF_SIZE(), (y*2+1)*Mask.getCELL_HALF_SIZE());
return sig;
}
/**
* This method averages the pixel values around a central point and return the
* average as an instance of Color. The point coordinates are proportional to
* the image.
*/
private Color averageAround(RenderedImage img, double px, double py)
{
// Get an iterator for the image.
RandomIter iterator = RandomIterFactory.create(img, null);
// Get memory for a pixel and for the accumulator.
double[] pixel = new double[4];
double[] accum = new double[3];
// The size of the sampling area.
// Sample the pixels.
for (double x = px - Mask.getCELL_HALF_SIZE(); x < Math.min(px + Mask.getCELL_HALF_SIZE(),img.getWidth()); x++)
{
for (double y = py - Mask.getCELL_HALF_SIZE(); y < Math.min(py + Mask.getCELL_HALF_SIZE(),img.getHeight()); y++)
{
iterator.getPixel((int) x, (int) y, pixel);
accum[0] += pixel[0];
accum[1] += pixel[1];
accum[2] += pixel[2];
}
}
// Average the accumulated values.
accum[0] /= Mask.getCELL_HALF_SIZE() * Mask.getCELL_HALF_SIZE() * 4;
accum[1] /= Mask.getCELL_HALF_SIZE() * Mask.getCELL_HALF_SIZE() * 4;
accum[2] /= Mask.getCELL_HALF_SIZE() * Mask.getCELL_HALF_SIZE() * 4;
return new Color((int) accum[0], (int) accum[1], (int) accum[2]);
}
/*
* This method calculates the distance between the signatures of an image and
* the reference one. The signatures for the image passed as the parameter are
* calculated inside the method.
*/
private double calcDistance(RenderedImage refImage, RenderedImage testImage, Mask mask, Boolean2D different)
{
//Logger.getLogger(this.getClass() ).debug("calcDistance"+i);
if (imageSameSize(refImage, testImage)){
// Calculate the signature for that image.
Color[][] sigRef = calcSignature(refImage);
Color[][] sigTest = calcSignature(testImage);
// There are several ways to calculate distances between two vectors,
// we will calculate the sum of the distances between the RGB values of
// pixels in the same positions.
double dist = 0;
for (int x = 0; x < maskWidth; x++)
for (int y = 0; y < maskHeight; y++)
{
int r1 = sigRef[x][y].getRed();
int g1 = sigRef[x][y].getGreen();
int b1 = sigRef[x][y].getBlue();
int r2 = sigTest[x][y].getRed();
int g2 = sigTest[x][y].getGreen();
int b2 = sigTest[x][y].getBlue();
double tempDist = Math.sqrt((r1 - r2)*(r1 - r2) +
(g1 - g2)*(g1 - g2) + (b1 - b2)*(b1 - b2));
//We compare with 5 since the images are using some lossy compression like jpeg or png
//We want to estimate as equal images with very small differences
if (tempDist>10){
different.set(x, y, true);
}else{
tempDist = 0;
}
if (! mask.getCell(x, y)){
dist += tempDist;
}
}
return dist;
}
return Double.MAX_VALUE;
}
public void saveMaskAssociations() {
Logger.getLogger(this.getClass() ).debug("saveMaskAssociation");
//update useddoc
try {
useddoc=DocumentBuilderFactory.newInstance()
.newDocumentBuilder().newDocument();
Element usedRootElement = useddoc.createElement("UsedMask");
usedRootElement.setAttribute("height",""+maskHeight);
usedRootElement.setAttribute("width",""+maskWidth);
ArrayList<Integer> printedMask = new ArrayList<Integer>();
//First we had all the images
for(String image : refImage.keySet()){
addNewImg(usedRootElement, refImage.get(image));
}
//Then we had all the masks
for (ComparaisonCouple cp : couples){
for(Integer Id : cp.getMaskList())
if(!printedMask.contains(Id)) {
usedRootElement.appendChild(refMask.get(Id).toXML(useddoc));
printedMask.add(Id);
}
}
useddoc.appendChild(usedRootElement);
printToFile(useddoc, refDirectory+Platform.FILE_SEPARATOR+maskXmlFileName);
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
}
public void saveRefDescriptions() {
Logger.getLogger(this.getClass() ).debug("saveRefDescription");
try {
useddoc=DocumentBuilderFactory.newInstance()
.newDocumentBuilder().newDocument();
Element usedRootElement = useddoc.createElement("RefDescription");
Iterator refNames = refScDesc.keySet().iterator();
while (refNames.hasNext()) {
String name = (String) refNames.next();
String desc = refScDesc.get(name);
Element e = useddoc.createElement("Screenshot");
Element eName=useddoc.createElement("Name");
eName.setTextContent(name);
e.appendChild(eName);
Element eDesc=useddoc.createElement("Description");
eDesc.setTextContent(desc);
e.appendChild(eDesc);
usedRootElement.appendChild(e);
}
useddoc.appendChild(usedRootElement);
printToFile(useddoc, refDirectory+Platform.FILE_SEPARATOR+refXmlFileName);
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
}
private Element addNewImg(Element usedRootElement, ImageFileMask imgRef) {
Element e = useddoc.createElement("img");
e.setAttribute("id",imgRef.getId());
String listMask = "";
for(Integer Id: imgRef.getMaskListId()){
if(listMask!="")
listMask+=",";
listMask+=Id;
}
e.setAttribute("mask",listMask);
usedRootElement.appendChild(e);
return e;
}
/**
*print an XML report into the test directory
*/
public void saveReport(){
try {
resultDoc=DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
resultRootElement=resultDoc.createElement("Report");
for (ComparaisonCouple cp : couples) {
Element e = resultDoc.createElement("img");
Element eRef=resultDoc.createElement("Ref");
eRef.setAttribute("name", cp.getImgRefId());
eRef.setTextContent(cp.getImgRef().getImage().getAbsolutePath());
e.appendChild(eRef);
Element eTest=resultDoc.createElement("Test");
eTest.setAttribute("name", cp.getImgTest().getName());
eTest.setTextContent(cp.getImgTest().getAbsolutePath());
e.appendChild(eTest);
Element ePass=resultDoc.createElement("Pass");
String pass =cp.getPass();
ePass.setTextContent(pass);
e.appendChild(ePass);
Element eRefDesc=resultDoc.createElement("RefDescription");
String refDesc =refScDesc.get(cp.getImgRefId());
eRefDesc.setTextContent(refDesc);
e.appendChild(eRefDesc);
Element eComm=resultDoc.createElement("Comment");
eComm.setTextContent(cp.getComment());
e.appendChild(eComm);
for(Integer maskId : cp.getMaskList()){
Element eMask=resultDoc.createElement("Mask");
eMask.setTextContent(maskId+" - "+refMask.get(maskId).getLabel());
e.appendChild(eMask);
}
resultRootElement.appendChild(e);
}
resultDoc.appendChild(resultRootElement);
printToFile(resultDoc, getTestDirectory()+Platform.FILE_SEPARATOR+xmlReportName);
} catch (ParserConfigurationException e1) {
e1.printStackTrace();
}
}
/**
* print a PDF report into the test directory
*/
public void printPDFReport() {
try {
PDFGenerator gen = new PDFGenerator(new FileOutputStream(getTestDirectory()+Platform.FILE_SEPARATOR+pdfReportName), getTestDirectory() , "JG", "FT R&D", "scriptname", true);
gen.dumpInStream(false, resultDoc, this);
} catch (FileNotFoundException e) {
Logger.getLogger(this.getClass() ).warn("Error in PDF printing");
e.printStackTrace();
}
}
private void printToFile(Document dom, String fileName){
//Logger.getLogger(this.getClass() ).debug("Model.PrintToFile");
try
{
//print
OutputFormat format = new OutputFormat(dom);
format.setIndenting(true);
//to generate a file output use fileoutputstream instead of //System.out
XMLSerializer serializer = new XMLSerializer(
new FileOutputStream(new File(fileName)), format);
serializer.serialize(dom);
} catch(IOException ie) {
ie.printStackTrace();
}
}
/**
* Recompute differences in all couple of images
* @param m - the Mask you want to associate to all (not passed) images for recomputing
* @return the number of passed images help to re-computation
*/
public int recomputeAll() {
int nbFailed=0;
double nbTotal = couples.size();
int i=0;
for (ComparaisonCouple cp : couples){
try {
if (recompute(cp)==0){
cp.setPass( AUTOMATIC_PASS);
}
else {
cp.setPass( FAIL);
nbFailed++;
}
} catch (IOException e) {
e.printStackTrace();
}
if (progressListener !=null) {
i++;
int pourcent = (int)(((double)100 / nbTotal) * (double)i);
progressListener.setProgressValue(pourcent);
progressListener.setNbFailed(nbFailed);
}
}
return nbFailed;
}
public boolean testIsValid() {
return getNbFail()==0;
}
public ArrayList<ComparaisonCouple> getCouplesComparaison() {
return couples;
}
}