ch.kostceco.tools.kostsimy.comparison.moduleim.impl.CompareImageModuleImpl.java Source code

Java tutorial

Introduction

Here is the source code for ch.kostceco.tools.kostsimy.comparison.moduleim.impl.CompareImageModuleImpl.java

Source

/* == KOST-Simy =================================================================================
 * The KOST-Simy application is used for Compare Image-Files. Copyright (C) 2015-2016 Claire
 * Rthlisberger (KOST-CECO)
 * -----------------------------------------------------------------------------------------------
 * KOST-Simy is a development of the KOST-CECO. All rights rest with the KOST-CECO. This application
 * is free software: you can redistribute it and/or modify it under the terms of the GNU General
 * Public License as published by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version. This application is distributed in the hope that it will be
 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the follow GNU General Public License for more details. You should
 * have received a copy of the GNU General Public License along with this program; if not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or
 * see <http://www.gnu.org/licenses/>.
 * ============================================================================================== */

package ch.kostceco.tools.kostsimy.comparison.moduleim.impl;

import static org.apache.commons.io.IOUtils.closeQuietly;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;

import ch.kostceco.tools.kostsimy.comparison.ComparisonModuleImpl;
import ch.kostceco.tools.kostsimy.comparison.moduleim.CompareImageModule;
import ch.kostceco.tools.kostsimy.exception.moduleim.CompareImageException;
import ch.kostceco.tools.kostsimy.service.ConfigurationService;
import ch.kostceco.tools.kostsimy.util.StreamGobbler;
import ch.kostceco.tools.kostsimy.util.Util;

/** Vergleicht die beiden Bilder mit ImageMagick Compare und wertet das Resultat aus
 * 
 * @author Rc Claire Rthlisberger, KOST-CECO */

public class CompareImageModuleImpl extends ComparisonModuleImpl implements CompareImageModule {
    public static String NEWLINE = System.getProperty("line.separator");
    private ConfigurationService configurationService;

    public ConfigurationService getConfigurationService() {
        return configurationService;
    }

    public void setConfigurationService(ConfigurationService configurationService) {
        this.configurationService = configurationService;
    }

    @Override
    public boolean validate(File origDatei, File repDatei, File directoryOfLogfile) throws CompareImageException {
        boolean isValid = true;
        // boolean isValidFailed = false;
        boolean compResult = false;
        int allInt = 0;
        boolean allNoInt = false;
        String allStr = "";

        String imToleranceTxt = getConfigurationService().getImTolerance();
        String imTolerance = "5%";
        float percentageInvalid = 99.9999f;
        /* Nicht vergessen in "src/main/resources/config/applicationContext-services.xml" beim
         * entsprechenden Modul die property anzugeben: <property name="configurationService"
         * ref="configurationService" /> */

        /* Initialisierung ImageMagick -> berprfen der Angaben: existiert die compare.exe,
         * msvcp120.dll, msvcr120.dll, vcomp120.dll am vorgegebenen Ort? */
        String compareExe = "compare.exe";
        String msvcp120Dll = "msvcp120.dll";
        String msvcr120Dll = "msvcr120.dll";
        String vcomp120Dll = "vcomp120.dll";
        String im = "resources" + File.separator + "ImageMagickCompare-6.9.1-Q16";
        boolean imExist = true;
        File fCompareExe = new File(im + File.separator + compareExe);
        if (!fCompareExe.exists()) {
            // Compare.exe von ImageMagick existiert nicht, kein Vergleich --> Abbruch
            getMessageService().logError(getTextResourceService().getText(MESSAGE_XML_MODUL_CI)
                    + getTextResourceService().getText(ERROR_XML_IMCMP_MISSING, compareExe));
            imExist = false;
        }
        File fMsvcp120Dll = new File(im + File.separator + msvcp120Dll);
        if (!fMsvcp120Dll.exists()) {
            // msvcp120.dll von ImageMagick existiert nicht, kein Vergleich --> Abbruch
            getMessageService().logError(getTextResourceService().getText(MESSAGE_XML_MODUL_CI)
                    + getTextResourceService().getText(ERROR_XML_IMCMP_MISSING, msvcp120Dll));
            imExist = false;
        }
        File fMsvcr120Dll = new File(im + File.separator + msvcr120Dll);
        if (!fMsvcr120Dll.exists()) {
            // msvcr120.dll von ImageMagick existiert nicht, kein Vergleich --> Abbruch
            getMessageService().logError(getTextResourceService().getText(MESSAGE_XML_MODUL_CI)
                    + getTextResourceService().getText(ERROR_XML_IMCMP_MISSING, msvcr120Dll));
            imExist = false;
        }
        File fVcomp120Dll = new File(im + File.separator + vcomp120Dll);
        if (!fVcomp120Dll.exists()) {
            // vcomp120.dll von ImageMagick existiert nicht, kein Vergleich --> Abbruch
            getMessageService().logError(getTextResourceService().getText(MESSAGE_XML_MODUL_CI)
                    + getTextResourceService().getText(ERROR_XML_IMCMP_MISSING, vcomp120Dll));
            imExist = false;
        }
        if (!imExist) {
            // compare.exe/msvcp120.dll/msvcr120.dll/vcomp120.dll von ImageMagick existiert nicht --> Abbruch
            getMessageService().logError(getTextResourceService().getText(MESSAGE_XML_MODUL_CI)
                    + getTextResourceService().getText(ERROR_XML_IMCMP_MISSING, vcomp120Dll));
            return false;
        }

        if (imToleranceTxt.contains("N") || imToleranceTxt.contains("n")) {
            // null = 0%
            imTolerance = "0%";
            percentageInvalid = (float) 100.000000000;
            imToleranceTxt = "N";
        } else if (imToleranceTxt.contains("S") || imToleranceTxt.contains("s")) {
            // small = 2%
            imTolerance = "2%";
            percentageInvalid = (float) 99.9999;
            imToleranceTxt = "S";
        } else if (imToleranceTxt.contains("XL") || imToleranceTxt.contains("xl")) {
            // xlarge = 15%
            imTolerance = "15%";
            percentageInvalid = (float) 99.9;
            imToleranceTxt = "XL";
        } else if (imToleranceTxt.contains("L") || imToleranceTxt.contains("l")) {
            // large = 10%
            imTolerance = "10%";
            percentageInvalid = (float) 99.99;
            imToleranceTxt = "L";
        } else {
            // medium = 5%
            imTolerance = "5%";
            imToleranceTxt = "M";
            percentageInvalid = (float) 99.999;
        }
        String pathToCompareExe = fCompareExe.getAbsolutePath();

        File report;
        File reportId;
        String imgPx1 = "1";

        StringBuffer concatenatedOutputs = new StringBuffer();

        try {

            String pathToOutput = directoryOfLogfile.getAbsolutePath() + File.separator + origDatei.getName()
                    + "_compare_report.txt";
            String pathToOutputId = directoryOfLogfile.getAbsolutePath() + File.separator + origDatei.getName()
                    + "_identify_report.txt";
            String pathToMask = directoryOfLogfile.getAbsolutePath() + File.separator + origDatei.getName()
                    + "_mask.jpg";

            /* compare -fuzz 15% -metric AE -quiet -identify -verbose -highlight-color DarkRed Image_1.jpg
             * Image_2.jpg mask.jpg >>results_id.txt 2>results.txt */

            String command = "cmd /c \"\"" + pathToCompareExe + "\" -fuzz " + imTolerance
                    + " -metric AE -quiet -identify -verbose -highlight-color DarkRed \""
                    + origDatei.getAbsolutePath() + "\" \"" + repDatei.getAbsolutePath() + "\" \"" + pathToMask
                    + "\" >>\"" + pathToOutputId + "\" 2>\"" + pathToOutput + "\"";
            /* Das redirect Zeichen verunmglicht eine direkte eingabe. mit dem geschachtellten Befehl
             * gehts: cmd /c\"urspruenlicher Befehl\" */

            Process proc = null;
            Runtime rt = null;

            try {
                report = new File(pathToOutput);
                reportId = new File(pathToOutputId);
                // falls das File bereits existiert, z.B. von einem vorhergehenden Durchlauf, lschen
                // wir es
                if (report.exists()) {
                    report.delete();
                }
                if (reportId.exists()) {
                    reportId.delete();
                }
                Util.switchOffConsole();
                rt = Runtime.getRuntime();
                proc = rt.exec(command.toString().split(" "));
                // .split(" ") ist notwendig wenn in einem Pfad ein Doppelleerschlag vorhanden ist!

                // Fehleroutput holen
                StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(), "ERROR");

                // Output holen
                StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), "OUTPUT");

                // Threads starten
                errorGobbler.start();
                outputGobbler.start();

                // Warte, bis wget fertig ist
                proc.waitFor();

                Util.switchOnConsole();
                // Kontrolle ob die Reports existieren
                if (!report.exists()) {
                    getMessageService().logError(getTextResourceService().getText(MESSAGE_XML_MODUL_CI)
                            + getTextResourceService().getText(ERROR_XML_IMCMP_NOREPORT, report.getAbsolutePath()));
                    if (!reportId.exists()) {
                        getMessageService().logError(
                                getTextResourceService().getText(MESSAGE_XML_MODUL_CI) + getTextResourceService()
                                        .getText(ERROR_XML_IMCMP_NOREPORT, reportId.getAbsolutePath()));
                        return false;
                    }
                    return false;
                }
                if (!reportId.exists()) {
                    getMessageService().logError(
                            getTextResourceService().getText(MESSAGE_XML_MODUL_CI) + getTextResourceService()
                                    .getText(ERROR_XML_IMCMP_NOREPORT, reportId.getAbsolutePath()));
                    return false;
                }
            } catch (Exception e) {
                getMessageService().logError(getTextResourceService().getText(MESSAGE_XML_MODUL_CI)
                        + getTextResourceService().getText(ERROR_XML_IMCMP_SERVICEFAILED, e.getMessage()));
                return false;
            } finally {
                if (proc != null) {
                    closeQuietly(proc.getOutputStream());
                    closeQuietly(proc.getInputStream());
                    closeQuietly(proc.getErrorStream());
                }
            }
            // Kontrolle ob die Reports existieren
            if (!report.exists()) {
                getMessageService().logError(getTextResourceService().getText(MESSAGE_XML_MODUL_CI)
                        + getTextResourceService().getText(ERROR_XML_IMCMP_NOREPORT, report.getAbsolutePath()));
                if (!reportId.exists()) {
                    getMessageService().logError(
                            getTextResourceService().getText(MESSAGE_XML_MODUL_CI) + getTextResourceService()
                                    .getText(ERROR_XML_IMCMP_NOREPORT, reportId.getAbsolutePath()));
                    return false;
                }
                return false;
            }
            if (!reportId.exists()) {
                getMessageService().logError(getTextResourceService().getText(MESSAGE_XML_MODUL_CI)
                        + getTextResourceService().getText(ERROR_XML_IMCMP_NOREPORT, reportId.getAbsolutePath()));
                return false;
            }

            // Ende IMCMP direkt auszulsen

            // TODO: Marker: ReportId und auswerten (Grsse und der Pixel)
            try {
                BufferedReader in = new BufferedReader(new FileReader(reportId));
                String line;
                String imgSize1 = "1";
                String imgSize2 = "2";
                String imgPx2 = "2";

                while ((line = in.readLine()) != null) {

                    concatenatedOutputs.append(line);
                    concatenatedOutputs.append(NEWLINE);

                    /* Format: TIFF (Tagged Image File Format) Mime type: image/tiff
                     * 
                     * Geometry: 2469x3568+0+0
                     * 
                     * Channel statistics:
                     * 
                     * Pixels: 8809392
                     * 
                     * Geometry und Pixels scheinen immer ausgegeben zu werden
                     * 
                     * Gemotry und Pixels mssen identisch sein */
                    if (line.contains("  Geometry: ")) {
                        if (imgSize1.equals("1")) {
                            imgSize1 = line;
                        } else {
                            imgSize2 = line;
                        }
                    } else if (line.contains("  Pixels: ")) {
                        if (imgPx1.equals("1")) {
                            imgPx1 = line;
                        } else {
                            imgPx2 = line;
                        }
                    }

                    // TODO: Marker: Auswertung und Fehlerausgabe wenn nicht bestanden.
                }
                if (imgPx1.equals("1") && imgPx2.equals("2") && imgSize1.equals("1") && imgSize2.equals("2")) {
                    // identify_report ist leer oder enthlt nicht das was er sollte
                    isValid = false;
                    getMessageService().logError(getTextResourceService().getText(MESSAGE_XML_MODUL_CI)
                            + getTextResourceService().getText(ERROR_XML_IMCMP_NOREPORTTEXT));
                    in.close();
                    return false;
                }
                if (!imgPx1.equals(imgPx2)) {
                    // die beiden Bilder haben nicht gleich viel Pixels
                    isValid = false;
                    getMessageService().logError(getTextResourceService().getText(MESSAGE_XML_MODUL_CI)
                            + getTextResourceService().getText(ERROR_XML_CI_PIXELINVALID, imgPx1, imgPx2));
                }
                if (!imgSize1.equals(imgSize2)) {
                    // die beiden Bilder sind nicht gleich gross
                    isValid = false;
                    getMessageService().logError(getTextResourceService().getText(MESSAGE_XML_MODUL_CI)
                            + getTextResourceService().getText(ERROR_XML_CI_SIZEINVALID, imgSize1, imgSize2));
                }
                if (!isValid) {
                    // die beiden Bilder sind nicht gleich gross
                    in.close();
                    return false;
                }
                in.close();
            } catch (Exception e) {
                getMessageService().logError(getTextResourceService().getText(MESSAGE_XML_MODUL_CI)
                        + getTextResourceService().getText(ERROR_XML_UNKNOWN, "identify: " + e.getMessage()));
                return false;
            }

            // TODO: Marker: Report auswerten (Bildvergleich) wenn grsse & PixelAnzahl identisch
            try {
                BufferedReader in = new BufferedReader(new FileReader(report));
                String line;
                boolean allNull = false;
                boolean allExist = false;

                while ((line = in.readLine()) != null) {

                    concatenatedOutputs.append(line);
                    concatenatedOutputs.append(NEWLINE);

                    /* img1.tif[0] TIFF 2469x3568 2469x3568+0+0 8-bit Grayscale Gray 8.833MB 1.451u 0:01.774
                     * 
                     * img2.jp2[0] JP2 2469x3568 2469x3568+0+0 8-bit Gray 1.842MB 1.357u 0:01.378
                     * 
                     * all: 0
                     * 
                     * in den ersten zwei zeilen sind die eigenschaften der beiden Bilder enthalten
                     * 
                     * Danach die Anzahl Pixel mit einer grsseren Abweichung aus, allg: 0= vergleichbar */
                    if (line.contains(" all: ")) {
                        allExist = true;
                        if (line.contains(" all: 0")) {
                            allNull = true;
                        } else {
                            /* Invalide Px extrahieren "    all: 3563" extrahieren */
                            String lineReportAll = line.substring(9);
                            try {
                                // lineReport = 3563
                                allInt = Integer.parseInt(lineReportAll);
                            } catch (Exception e) {
                                allNoInt = true;
                                allStr = lineReportAll;
                            }
                        }
                    }

                    if (allNull) {
                        compResult = true;
                    }
                }
                in.close();
                if (!allExist) {
                    getMessageService().logError(getTextResourceService().getText(MESSAGE_XML_MODUL_CI)
                            + getTextResourceService().getText(ERROR_XML_IMCMP_NOALL));
                    return false;
                }
                if (!compResult) {
                    // Bildvergleich nicht bestanden
                    if (allNoInt) {
                        /* Bilder mit vielen Pixels die Abweichen (Potenz -> String): Vereinfachte Fehlerausgabe */

                        /* Invalide [allStr] und total px z2 aus imgPx1 "    Pixels: 8809392" extrahieren */
                        String lineReport = imgPx1.substring(12);
                        // lineReport = 8809392

                        isValid = false;

                        getMessageService().logError(
                                getTextResourceService().getText(MESSAGE_XML_MODUL_CI) + getTextResourceService()
                                        .getText(ERROR_XML_CI_CIINVALIDSTR, lineReport, imToleranceTxt, allStr));

                    } else {
                        /* Bilder mit einer Abweichung (Int): Prozent ermitteln und mit percentageInvalid
                         * abgleichen */
                        double z1 = 0;
                        double z2 = 0;
                        float percentageCalc = (float) 0.0;
                        float percentageCalcInv = (float) 0.0;

                        /* Invalide z1 [allInt] und total px z2 aus imgPx1 "    Pixels: 8809392" extrahieren */
                        String lineReport = imgPx1.substring(12);
                        // lineReport = 8809392
                        z2 = Double.parseDouble(lineReport);
                        z1 = allInt;

                        percentageCalc = (float) (100 - (100 / z2 * z1));
                        percentageCalcInv = 100 - percentageCalc;

                        // Prozentzahlen vergleichen
                        if (percentageInvalid > percentageCalc) {
                            // Bilder mit einer grsseren Abweichung
                            isValid = false;

                            getMessageService().logError(getTextResourceService().getText(MESSAGE_XML_MODUL_CI)
                                    + getTextResourceService().getText(ERROR_XML_CI_CIINVALID, percentageCalcInv,
                                            z2, imToleranceTxt, z1));
                        }
                    }
                }
            } catch (Exception e) {
                getMessageService().logError(getTextResourceService().getText(MESSAGE_XML_MODUL_CI)
                        + getTextResourceService().getText(ERROR_XML_UNKNOWN, "compare: " + e.getMessage()));
                return false;
            }
        } catch (Exception e) {
            getMessageService().logError(getTextResourceService().getText(MESSAGE_XML_MODUL_CI)
                    + getTextResourceService().getText(ERROR_XML_UNKNOWN, e.getMessage()));
            return false;
        }

        // reports lschen
        if (report.exists()) {
            report.delete();
        }
        if (reportId.exists()) {
            reportId.delete();
        }

        return isValid;
    }
}