merge the formfield patch from ooo-build
[ooovba.git] / qadevOOo / runner / graphical / JPEGComparator.java
blob06fa30bc13d26ed3494212ab09a1c0c22f466893
1 /*
2 * ************************************************************************
3 *
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * Copyright 2008 by Sun Microsystems, Inc.
7 *
8 * OpenOffice.org - a multi-platform office productivity suite
9 *
10 * $RCSfile: JPEGComparator.java,v $
11 * $Revision: 1.1.2.6 $
13 * This file is part of OpenOffice.org.
15 * OpenOffice.org is free software: you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License version 3
17 * only, as published by the Free Software Foundation.
19 * OpenOffice.org is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Lesser General Public License version 3 for more details
23 * (a copy is included in the LICENSE file that accompanied this code).
25 * You should have received a copy of the GNU Lesser General Public License
26 * version 3 along with OpenOffice.org. If not, see
27 * <http://www.openoffice.org/license.html>
28 * for a copy of the LGPLv3 License.
30 * ***********************************************************************
33 package graphical;
35 import helper.OSHelper;
36 import helper.ProcessHandler;
37 import java.io.File;
39 /**
40 * Helper class to interpret a jpg filename
42 class NameDPIPage
44 String Name;
45 int DPI;
46 int Page;
48 private NameDPIPage(String _sName, int _nDPI, int _nPage)
50 Name = _sName;
51 DPI = _nDPI;
52 Page = _nPage;
55 public static NameDPIPage interpret(String _sFilename)
57 String sBasename = FileHelper.getBasename(_sFilename); // if exist a path, remove it
58 String sNameNoSuffix = FileHelper.getNameNoSuffix(sBasename); // remove extension (.jpg)
60 // check if there exist a 'DPI_' at specific position
61 String sDPICheck = sNameNoSuffix.substring(sNameNoSuffix.length() - 8, sNameNoSuffix.length() - 4);
62 String sName;
63 int nDPI = -1;
64 int nPage = -1;
65 if (sDPICheck.equals("DPI_"))
67 // seems to be a generated filename by us.
68 int nDPIStart = sNameNoSuffix.lastIndexOf("_", sNameNoSuffix.length() - 8);
69 sName = sNameNoSuffix.substring(0, nDPIStart);
70 if (nDPIStart > 0)
72 String sDPI = sNameNoSuffix.substring(nDPIStart + 1, sNameNoSuffix.length() - 8);
73 try
75 nDPI = Integer.valueOf(sDPI).intValue();
77 catch(java.lang.NumberFormatException e)
79 GlobalLogWriter.get().println("DPI: Number format exception");
81 String sPage = sNameNoSuffix.substring(sNameNoSuffix.length() - 4);
82 try
84 nPage = Integer.valueOf(sPage).intValue();
86 catch(java.lang.NumberFormatException e)
88 GlobalLogWriter.get().println("Page: Number format exception");
92 else
94 sName = sNameNoSuffix;
97 return new NameDPIPage(sName, nDPI, nPage);
103 * @author ll93751
105 public class JPEGComparator extends EnhancedComplexTestCase
107 // @Override
108 public String[] getTestMethodNames()
110 return new String[]{"CompareJPEGvsJPEG"};
114 * test function.
116 public void CompareJPEGvsJPEG()
118 GlobalLogWriter.set(log);
119 ParameterHelper aParam = new ParameterHelper(param);
121 // run through all documents found in Inputpath
122 foreachJPEGcompareWithJPEG(aParam);
125 public void checkOneFile(String _sDocumentName, String _sResult, ParameterHelper _aParams) throws OfficeException
127 // private void callEveryPictureInIniFile(IniFile _aIniFile, String _sSectionName, ParameterHelper _aParam)
128 // {
129 String sPath = FileHelper.getPath(_sDocumentName);
130 String sSectionName = FileHelper.getBasename(_sDocumentName);
132 // take the build id out of the ini file in the reference file and put it into the current parameter helper
133 String sIniFileForRefBuildID = FileHelper.appendPath(sPath, sSectionName + ".ini");
134 IniFile aIniFileForRefBuildID = new IniFile(sIniFileForRefBuildID);
135 String sRefBuildID = aIniFileForRefBuildID.getValue("global", "buildid");
136 aIniFileForRefBuildID.close();
138 _aParams.getTestParameters().put("RefBuildId", sRefBuildID);
140 String sIniFile = FileHelper.appendPath(sPath, "index.ini");
141 IniFile aIniFile = new IniFile(sIniFile);
142 if (aIniFile.hasValue(sSectionName, "pages"))
144 // only which has 'pages' has also pictures
145 int nPages = aIniFile.getIntValue(sSectionName, "pages", 0);
146 String sJPEGSchema = aIniFile.getValue(sSectionName, "jpegschema");
148 for (int i=1 ; i<=nPages ; i++)
150 String sJPEGFilename = JPEGCreator.getFilenameForJPEGSchema(sJPEGSchema, i);
151 // String sPath = FileHelper.getPath(_aParam.getInputPath());
152 String sJPEGPath = FileHelper.getPath(sJPEGFilename);
153 if (!sPath.equals(sJPEGPath))
155 GlobalLogWriter.println("Path where to find the index and where to file the JPEG pictures are not the same.");
158 // String sEntry = FileHelper.appendPath(sPath, sSection);
159 File aFile = new File(sJPEGFilename);
160 assure("File '" + sJPEGFilename + "' doesn't exists.", aFile.exists(), true);
161 if (aFile.exists())
163 GlobalLogWriter.println("Page: " + i);
164 checkOnePicture(sJPEGFilename, _sResult, _aParams);
168 else
170 GlobalLogWriter.println("The document '" + sSectionName + "' seems to have no picture representation.");
173 String sResultIniFile = FileHelper.appendPath(_sResult, sSectionName);
174 evaluateResult(sResultIniFile, _aParams);
178 private void evaluateResult(String _sDocument, ParameterHelper _aParams)
180 String sResultIniFile = _sDocument + ".ini";
181 File aFile = new File(sResultIniFile);
182 assure("Result file doesn't exists " + sResultIniFile, aFile.exists());
184 int good = 0;
185 int bad = 0;
186 int ugly = 0;
187 int ok_status = 1; // 1=ok 2=bad 3=ugly
189 IniFile aResultIniFile = new IniFile(sResultIniFile);
190 int nPages = aResultIniFile.getIntValue("global", "pages", 0);
191 for (int i=0;i<nPages;i++)
193 String sCurrentPage = "page" + String.valueOf(i + 1);
194 int nPercent = aResultIniFile.getIntValue(sCurrentPage, "percent", -1);
195 if (nPercent == 0)
197 good++;
199 else if (nPercent <= 5)
201 bad ++;
202 ok_status=2;
204 else
206 ugly ++;
207 ok_status=3;
211 assure("Error: document doesn't contains pages", nPages > 0);
213 // TODO: this information has to come out of the ini files
214 String sStatusRunThrough = "PASSED, ";
215 String sPassed = "OK";
217 String sStatusMessage = "From " + nPages + " page(s) are: ";
218 String sGood = "";
219 String sBad = "";
220 String sUgly = "";
222 if (good > 0)
224 sGood = " good:=" + good;
225 sStatusMessage += sGood;
227 if (bad > 0)
229 sBad = " bad:=" + bad;
230 sStatusMessage += sBad;
232 if (ugly > 0)
234 sUgly = " ugly:=" + ugly;
235 sStatusMessage += sUgly;
238 // Failure matrix
239 // 0 1
240 // ugly OK FAILED
241 // bad OK
242 // good OK
244 if (ugly > 0)
246 sPassed = "FAILED";
248 else
250 if (bad > 0)
252 sPassed = "NEED A LOOK";
254 else
256 sPassed = "OK";
259 sStatusRunThrough += sPassed;
260 aResultIniFile.insertValue("global", "state", sStatusRunThrough);
261 aResultIniFile.insertValue("global", "info", sStatusMessage);
262 aResultIniFile.close();
264 _aParams.getTestParameters().put("current_state", sStatusRunThrough);
265 _aParams.getTestParameters().put("current_info", sStatusMessage);
266 _aParams.getTestParameters().put("current_ok_status", ok_status);
268 // if we have a ugly page, we must return this as a FAILED STATUS in Log file!
269 // assure( "There exist pages marked as ugly.", ugly == 0)
272 private void checkOnePicture(String _sDocumentName, String _sResult, ParameterHelper _aParams)
274 GlobalLogWriter.println("JPEG: Compare difference between '" + _sDocumentName + "' and '" + _sResult + "'");
275 File aResultFile = new File(_sResult);
276 if (aResultFile.isDirectory())
278 // result is just a directory, so we search for the basename of the source and take this.
279 String sBasename = FileHelper.getBasename(_sDocumentName);
280 String sResultFilename = FileHelper.appendPath(_sResult, sBasename);
281 aResultFile = new File(sResultFilename);
282 if (aResultFile.exists())
284 // Original and Result exists
285 String sInputPath = _aParams.getInputPath();
286 if (sInputPath.toLowerCase().endsWith("index.ini"))
288 // special case
289 // we want to get the buildid from the info file.
293 compareJPEG(_sDocumentName, sResultFilename, _aParams);
296 else
298 GlobalLogWriter.println("Warning: Result JPEG doesn't exists '" + sResultFilename + "'");
301 else
303 // result is also a file
304 if (aResultFile.exists())
306 compareJPEG(_sDocumentName, _sResult, _aParams);
308 else
310 GlobalLogWriter.println("Warning: Result JPEG doesn't exists '" + _sResult + "'");
318 * compare 2 JPEGs, it is a need, that both _sDocumentName and _sResultFilename exist.
319 * @param _sDocumentName
320 * @param _sResult
321 * @param _aParams
322 * @return 0=no difference !=0 both files differ
325 private void compareJPEG(String _sDocumentName, String _sResult, ParameterHelper _aParams)
327 NameDPIPage aNameDPIPage = NameDPIPage.interpret(_sDocumentName);
329 String sSourceBasename = FileHelper.getBasename(_sDocumentName);
330 String sSourcePath = FileHelper.getPath(_sDocumentName);
331 String sDestinationBasename = FileHelper.getBasename(_sResult);
332 String sDestinationPath = FileHelper.getPath(_sResult);
334 if (! sSourcePath.equals(sDestinationPath))
336 // we want to have all in one Directory, Original, Reference and the Difference result.
337 // copy the original file to the reference path
338 String sNewSourceBasename = "Original_" + sSourceBasename;
339 // String sSource = FileHelper.appendPath(sSourcePath, sSourceBasename);
340 String sSource = _sDocumentName;
341 String sDestination = FileHelper.appendPath(sDestinationPath, sNewSourceBasename);
342 FileHelper.copy(sSource, sDestination);
343 sSourceBasename = sNewSourceBasename;
345 String sDifferenceBasename = "Difference_between_" + FileHelper.getNameNoSuffix(sSourceBasename) + "_and_" + FileHelper.getNameNoSuffix(sDestinationBasename) + ".jpg";
346 // String sDifferencePath = sDestinationPath;
348 String sSource = FileHelper.appendPath(sDestinationPath, sSourceBasename);
349 String sDestination = FileHelper.appendPath(sDestinationPath, sDestinationBasename);
350 String sDifference = FileHelper.appendPath(sDestinationPath, sDifferenceBasename);
351 int nErr = compareJPEG(sSource, sDestination, sDifference);
352 if (nErr == 0 && FileHelper.exists(sDifference))
354 // check the difference, returns the count of different colors
355 // this means, 1=only one color, no differences found.
356 int nResult = identify(sDifference);
357 int nPercentColorDiffer = 0;
358 String sResult = "NO";
359 if (nResult != 1)
363 nPercentColorDiffer = estimateGfx(sSource, sDestination, sDifference);
365 catch (java.io.IOException e)
367 GlobalLogWriter.println("Can't estimate the different colors. " + e.getMessage());
370 else
372 sResult = "YES";
375 // store the result in a result.ini file
376 String sResultFile = FileHelper.appendPath(sDestinationPath, aNameDPIPage.Name + ".ini");
377 int nPage = aNameDPIPage.Page;
378 if (nPage < 0)
380 nPage = 0;
382 IniFile aResultIni = new IniFile(sResultFile);
384 String[] aComment = {
385 "; This file is automatically created by a graphical.JPEGComparator run",
386 "; ",
387 "; If you see this file in a browser you may have forgotten to set the follows in the property file",
388 "; " + PropertyName.DOC_COMPARATOR_HTML_OUTPUT_PREFIX + "=http://<computer>/gfxcmp_ui/cw.php?inifile=",
389 "; Please check the documentation if you got confused.",
390 "; ",
391 "; "};
392 aResultIni.insertFirstComment(aComment);
394 // write down the global flags
395 int nMaxPage = Math.max(nPage, aResultIni.getIntValue("global", "pages", 0));
396 aResultIni.insertValue("global", "pages", nMaxPage);
398 // INIoutput.writeValue("buildid", _sBuildID);
399 // INIoutput.writeValue("refbuildid", _sRefBuildID);
400 String sRefBuildId = (String)_aParams.getTestParameters().get("RefBuildId");
401 if (sRefBuildId == null)
403 sRefBuildId = "";
405 aResultIni.insertValue("global", "refbuildid", sRefBuildId);
407 aResultIni.insertValue("global", "diffdiff", "no");
408 aResultIni.insertValue("global", "basename", aNameDPIPage.Name);
409 aResultIni.insertValue("global", "dpi", aNameDPIPage.DPI);
411 // write down flags for each page
412 String sSection = "page" + String.valueOf(nPage);
414 aResultIni.insertValue(sSection, "oldgfx", sSource);
415 aResultIni.insertValue(sSection, "newgfx", sDestination);
416 aResultIni.insertValue(sSection, "diffgfx", sDifference);
417 aResultIni.insertValue(sSection, "percent", nPercentColorDiffer);
418 aResultIni.insertValue(sSection, "BM", "false");
419 aResultIni.insertValue(sSection, "result", sResult);
421 aResultIni.close();
425 // // This creates a status for exact on document
426 // static boolean createINIStatus(StatusHelper[] aList, String _sFilenamePrefix, String _sOutputPath, String _sAbsoluteInputFile, String _sBuildID, String _sRefBuildID)
427 // {
428 // // Status
429 // String fs = System.getProperty("file.separator");
430 // String sBasename = FileHelper.getBasename(_sAbsoluteInputFile);
431 // String sNameNoSuffix = FileHelper.getNameNoSuffix(sBasename);
432 //// String sHTMLFile = _sFilenamePrefix + sNameNoSuffix + ".html";
433 //// HTMLOutputter HTMLoutput = HTMLOutputter.create(_sOutputPath, sHTMLFile, "", "");
434 //// HTMLoutput.header(sNameNoSuffix);
435 //// TODO: version info was fine
436 //// HTMLoutput.checkSection(sBasename);
437 // // Status end
439 // String sINIFile = _sFilenamePrefix + sNameNoSuffix + ".ini";
440 // INIOutputter INIoutput = INIOutputter.create(_sOutputPath, sINIFile, "", "");
441 // INIoutput.createHeader();
442 //// TODO: version info was fine
444 // INIoutput.writeSection("global");
445 // INIoutput.writeValue("pages", String.valueOf(aList.length));
446 // INIoutput.writeValue("buildid", _sBuildID);
447 // INIoutput.writeValue("refbuildid", _sRefBuildID);
448 // INIoutput.writeValue("diffdiff", "no");
449 // INIoutput.writeValue("basename", sBasename);
451 // boolean bResultIsOk = true; // result over all pages
452 // for (int i=0;i<aList.length; i++)
453 // {
454 // INIoutput.writeSection("page" + String.valueOf(i + 1)); // list start at point 0, but this is page 1 and so on... current_page = (i + 1)
455 // aList[i].printStatus();
457 // boolean bCurrentResult = true; // result over exact one page
459 // int nCurrentDiffStatus = aList[i].nDiffStatus;
461 // // check if the status is in a defined range
462 // if (nCurrentDiffStatus == StatusHelper.DIFF_NO_DIFFERENCES)
463 // {
464 // // ok.
465 // }
466 // else if (nCurrentDiffStatus == StatusHelper.DIFF_DIFFERENCES_FOUND && aList[i].nPercent < 5)
467 // {
468 // // ok.
469 // }
470 // else if (nCurrentDiffStatus == StatusHelper.DIFF_AFTER_MOVE_DONE_NO_PROBLEMS)
471 // {
472 // // ok.
473 // }
474 // else if (nCurrentDiffStatus == StatusHelper.DIFF_AFTER_MOVE_DONE_DIFFERENCES_FOUND && aList[i].nPercent2 < 5)
475 // {
476 // // ok.
477 // }
478 // else
479 // {
480 // // failed.
481 // bCurrentResult = false; // logic: nDiff==0 = true if there is no difference
482 // }
484 // // Status
485 //// HTMLoutput.checkLine(aList[i], bCurrentResult);
486 // INIoutput.checkLine(aList[i], bCurrentResult);
487 // bResultIsOk &= bCurrentResult;
488 // }
489 // // Status
490 //// HTMLoutput.close();
491 // INIoutput.close();
492 // return bResultIsOk;
493 // }
497 * count how much pixel differ and between Old or New and the Difference graphics
499 * First, count the old graphics, then the new graphics due to the fact both should be equal
500 * it should be legal to take result from old or new. We take the graphics with less values.
502 * Second, count the difference graphics, now take the percent algorithm and
503 * build a percent value, which contain the number of different pixels as a percent value
505 * Interpretation:
506 * 0% there is no difference
508 * &lt;100% Take a look into the difference graphics, maybe the difference graphics shows
509 * text like outlined or the text is little bit move left, right up or down.
511 * &gt;>100% Yes it's possible that there is a difference more then 100%, maybe a font problem
512 * between old and new graphics. The font of the new graphics is little bit bigger,
513 * so the pixel count between old graphics and new graphics is twice the more.
515 * @param _sOldGfx path & name to the jpeg file (1)
516 * @param _sNewGfx path & name to the other jpeg file (2)
517 * @param _sDiffGfx path & name to the new difference file which shows the difference between (1) and (2)
518 * @return the count of different pixels
519 * @throws java.io.IOException if file access is not possible
522 public static int estimateGfx(String _sOldGfx, String _sNewGfx, String _sDiffGfx)
523 throws java.io.IOException
525 // new count pixels
526 final int nNotWhiteCount_OldGraphic = PixelCounter.countNotWhitePixelsFromImage(_sOldGfx);
527 final int nNotWhiteCount_NewGraphic = PixelCounter.countNotWhitePixelsFromImage(_sNewGfx);
528 final int nNotBlackCount_DiffGraphic = PixelCounter.countNotBlackPixelsFromImage(_sDiffGfx);
530 int nMinNotWhiteCount = Math.min(nNotWhiteCount_NewGraphic, nNotWhiteCount_OldGraphic);
532 // check if not zero
533 if (nMinNotWhiteCount == 0)
535 nMinNotWhiteCount = Math.max(nNotWhiteCount_NewGraphic, nNotWhiteCount_OldGraphic);
536 if (nMinNotWhiteCount == 0)
538 nMinNotWhiteCount = 1;
542 int nPercent = Math.abs(nNotBlackCount_DiffGraphic * 100 / nMinNotWhiteCount);
543 GlobalLogWriter.get().println( "Graphics check, pixel based:" + String.valueOf(nPercent) + "% pixel differ ");
544 return nPercent;
547 private static int compareJPEG(String _sOldGfx, String _sNewGfx, String _sDiffGfx)
549 String sComposite = "composite";
550 if (OSHelper.isWindows())
552 sComposite = "composite.exe";
555 // String sCommand = sComposite + " -compose difference " +
556 // StringHelper.doubleQuoteIfNeed(_sOldGfx) + " " +
557 // StringHelper.doubleQuoteIfNeed(_sNewGfx) + " " +
558 // StringHelper.doubleQuoteIfNeed(_sDiffGfx);
560 String[] sCommandArray =
562 sComposite,
563 "-compose",
564 "difference",
565 _sOldGfx,
566 _sNewGfx,
567 _sDiffGfx
570 ProcessHandler aHandler = new ProcessHandler(sCommandArray);
571 boolean bBackValue = aHandler.executeSynchronously();
572 int nExitCode = aHandler.getExitCode();
573 if (nExitCode != 0)
575 GlobalLogWriter.println("'" + sComposite + "' return with ");
576 String sBack = aHandler.getOutputText();
577 GlobalLogWriter.get().println("'" + sBack + "'");
579 else
581 // creates an extra smaller difference picture
582 File aDiffFile = new File(_sDiffGfx);
583 if (aDiffFile.exists())
585 JPEGCreator.convertToNearSameFileWithWidth340(_sDiffGfx);
588 return nExitCode;
592 * wrapper for ImageMagick identify,
593 * function checks how many different colors a picture contains.
594 * if it's only one color (nResult==1), like background color, there is no difference.
596 int identify(String _sDiffGfx)
598 int nResult = 0;
599 // would like to know what the meaning of %k is for ImageMagick's 'identify'
600 String sIM_Format = "%k";
601 // if (OSHelper.isWindows())
602 // {
603 // sIM_Format = "%%k";
604 // }
606 String sIdentify = "identify";
607 if (OSHelper.isWindows())
609 sIdentify = "identify.exe";
612 // String sCommand = sIdentify + " " + sIM_Format + " " + StringHelper.doubleQuoteIfNeed(_sDiffGfx);
614 String[] sCommandArray =
616 sIdentify,
617 "-format",
618 sIM_Format,
619 _sDiffGfx
621 ProcessHandler aHandler = new ProcessHandler(sCommandArray);
622 boolean bBackValue = aHandler.executeSynchronously();
623 int nExitCode = aHandler.getExitCode();
625 String sBack = aHandler.getOutputText();
626 GlobalLogWriter.get().println("'" + sBack + "'");
628 // try to interpret the result, which we get as a String
631 int nIdx = sBack.indexOf("\n");
632 if (nIdx > 0)
634 sBack = sBack.substring(0, nIdx);
637 nResult = Integer.valueOf(sBack).intValue();
639 catch(java.lang.NumberFormatException e)
641 GlobalLogWriter.get().println("identify(): Number format exception");
642 nResult = 0;
644 return nResult;
649 public static void main(String [] _args)
651 // give an index.ini file, ok
652 // give a directory, where exist jpeg files ok
653 // inputpath (given file) doesn't exists
654 // give a jpeg file.
656 String args[] = {
657 "-TimeOut", "3600000",
658 "-tb", "java_complex",
659 "-o", "graphical.JPEGComparator",
660 "-DOC_COMPARATOR_INPUT_PATH", "C:\\CWS\\temp\\output\\index.ini",
661 "-DOC_COMPARATOR_OUTPUT_PATH", "C:\\CWS\\temp\\output2",
662 // "-DOC_COMPARATOR_INPUT_PATH", "C:\\CWS\\temp\\output\\GroupReport.odt.pdf_180DPI_0001.jpg",
663 // "-DOC_COMPARATOR_OUTPUT_PATH", "C:\\CWS\\temp\\output2\\Report1.odt.pdf_180DPI_0001.jpg",
664 "-DOC_COMPARATOR_HTML_OUTPUT_PREFIX", "http://so-gfxcmp-lin.germany.sun.com/gfxcmp_ui/cw.php?inifile=",
665 // "-DOC_COMPARATOR_REFERENCE_CREATOR_TYPE", "PDF", /* default: "OOo" */
666 // "-DOC_COMPARATOR_REFERENCE_CREATOR_TYPE", "msoffice", /* default: "OOo" */
667 // "-OFFICE_VIEWABLE", "false",
668 // "-AppExecutionCommand", "\"C:/Programme/sun/staroffice 9/program/soffice.exe\" -norestore -nocrashreport -accept=pipe,name=ll93751;urp;",
669 "-NoOffice"
672 org.openoffice.Runner.main(args);