yahoo/blink-diff

View on GitHub
bin/blink-diff2

Summary

Maintainability
Test Coverage
#!/usr/bin/env node

// Copyright 2014-2015 Yahoo! Inc.
// Copyrights licensed under the Mit License. See the accompanying LICENSE file for terms.

var BlinkDiff = require('../index2');
var Compatibility = require('../lib/compatibility');

try {

    printLicense();

    var options = parseArgs(process.argv.slice(1));

    var compatibility = new Compatibility(options);

    var diff = new BlinkDiff(compatibility.generate());
    if (options.verbose) {
        diff.verbose = true;
    }

    // Setup console logger
    diff.log = function (text) {
        if (this.verbose) {
            console.log(text);
        }
    };

    if (diff.verbose) {
        console.time('Time');
    }
    var result = diff.process();

    var passed = diff.hasPassed(result.code);

    if (diff.verbose) {
        console.timeEnd('Time');

        console.log('Differences:', result.differences, '(' + Math.round((result.differences / result.dimension) * 10000) / 100 + '%)');
    }

    if (passed) {
        if (diff.verbose) {
            console.log("PASS");
        }
    } else {
        console.log("FAIL");
    }

    process.exit(passed ? 0 : 1);

} catch (exception) {
    console.error(exception.message);
    process.exit(1);
}

/**
 * Prints the license
 */
function printLicense () {
    console.log("Blink-Diff " + BlinkDiff.version);
    console.log("Copyright (C) 2014 Yahoo! Inc.");
}

/**
 * Prints the help info
 */
function printHelp () {
    console.log("Usage: blink-diff <image1> <image2>");
    console.log("");
    console.log("  Compares image1 and image2.");
    console.log("");
    console.log("  Options:");
    console.log("    --verbose           Turn on verbose mode");
    console.log("    --debug             Turn on debug mode - leaving all filters and modifications on the result");
    console.log("    --threshold p       Number of pixels/percent 'p' below which differences are ignored");
    console.log("    --threshold-type t  'pixel' and 'percent' as type of threshold. (default: pixel)");
    console.log("    --delta p           Max. distance colors in the 4 dimensional color-space without triggering a difference. (default: 20)");
    console.log("    --copyImageA        Copies first image to output as base. (default: true)");
    console.log("    --copyImageB        Copies second image to output as base.");
    console.log("    --no-copy           Doesn't copy anything to output as base.");
    console.log("    --output o          Write difference to the file 'o'");
    console.log("    --filter f          Filters f (separated with comma) that will be applied before the comparison.");
    console.log("    --no-composition    Turns the composition feature off");
    console.log("    --compose-ltr       Compose output image from left to right");
    console.log("    --compose-ttb       Compose output image from top to bottom");
    console.log("    --hide-shift        Hides shift highlighting (default: false)");
    console.log("    --h-shift           Acceptable horizontal shift of pixel. (default: 0)");
    console.log("    --v-shift           Acceptable vertical shift of pixel. (default: 0)");
    console.log("    --block-out x,y,w,h Block-out area. Can be repeated multiple times.");
    console.log("    --version           Print version");
    console.log("    --help              This help");
    console.log("");
}

/**
 * Parses the arguments and returns an option list
 *
 * @param {string[]} argv
 * @return {object}
 */
function parseArgs (argv) {

    var i, temporary, imageCount = 0, argLength = argv.length, options = {};

    if (argLength <= 1) {
        printHelp();
        process.exit(1);
    }

    options.blockOut = [];

    for (i = 1; i < argLength; i++) {

        try {

            if (argv[i] == "--help") {
                printHelp();
                process.exit(0);

            } else if (argv[i] == "--verbose") {
                options.verbose = true;

            } else if (argv[i] == "--debug") {
                options.debug = true;

            } else if (argv[i] == "--no-composition") {
                options.composition = false;

            } else if (argv[i] == "--compose-ltr") {
                options.composeLeftToRight = true;

            } else if (argv[i] == "--compose-ttb") {
                options.composeTopToBottom = true;

            } else if (argv[i] == "--no-copy") {
                options.copyImageAToOutput = false;
                options.copyImageBToOutput = false;

            } else if (argv[i] == "--hide-shift") {
                options.hideShift = true;

            } else if (argv[i] == "--copyImageA") {
                options.copyImageAToOutput = true;
                options.copyImageBToOutput = false;

            } else if (argv[i] == "--copyImageB") {
                options.copyImageAToOutput = false;
                options.copyImageBToOutput = true;

            } else if (argv[i] == "--threshold-type") {
                if (++i < argLength) {
                    if (argv[i] === 'pixel') {
                        options.thresholdType = BlinkDiff.THRESHOLD_PIXEL;

                    } else if (argv[i] === 'percent') {
                        options.thresholdType = BlinkDiff.THRESHOLD_PERCENT;

                    } else {
                        throw new Error("--threshold-type can be either 'pixel' or 'percent'");
                    }
                }

            } else if (argv[i] == "--threshold") {
                if (++i < argLength) {

                    temporary = parseFloat(argv[i]);
                    if (temporary < 0) {
                        throw new Error("--threshold must be positive");
                    }
                    options.threshold = temporary;
                }

            } else if (argv[i] == "--h-shift") {
                if (++i < argLength) {

                    temporary = parseInt(argv[i], 10);
                    if (temporary < 0) {
                        throw new Error("--h-shift must be positive");
                    }
                    options.hShift = temporary;
                }

            } else if (argv[i] == "--v-shift") {
                if (++i < argLength) {

                    temporary = parseInt(argv[i], 10);
                    if (temporary < 0) {
                        throw new Error("--v-shift must be positive");
                    }
                    options.vShift = temporary;
                }

            } else if (argv[i] == "--delta") {
                if (++i < argLength) {

                    temporary = parseFloat(argv[i]);
                    if (temporary < 0) {
                        throw new Error("--delta must be positive");
                    }
                    options.delta = temporary;
                }

            } else if (argv[i] == "--block-out") {
                if (++i < argLength) {

                    temporary = argv[i].split(',');
                    if (temporary.length < 2) {
                        throw new Error("--block-out should at least have the x and y coordinate");
                    }
                    options.blockOut.push({
                        x: parseInt(temporary[0], 10),
                        y: parseInt(temporary[1], 10),
                        width: parseInt(temporary[2], 10),
                        height: parseInt(temporary[3], 10)
                    });
                }

            } else if (argv[i] == "--filter") {
                if (++i < argLength) {
                    options.filter = argv[i].split(',');
                }

            } else if (argv[i] == "--output") {
                if (++i < argLength) {
                    options.imageOutputPath = argv[i];
                }

            } else if (argv[i] == "--version") {
                console.log("Blink-Diff " + BlinkDiff.version);

            } else if (imageCount < 2) {

                ++imageCount;
                if (imageCount == 1) {
                    options.imageAPath = argv[i];
                } else {
                    options.imageBPath = argv[i];
                }

            } else {
                console.log('Warning: parameter "' + argv[i] + '" ignored. Unknown.');
            }

        } catch (exception) {
            var reason = (exception.message !== '') ? "; " + exception.message : '';
            throw new Error("Invalid argument '" + argv[i] + "' for " + argv[i - 1] + reason);
        }
    }

    if (!options.imageAPath || !options.imageBPath) {
        throw new Error("Please specify two images.");
    }

    return options;
}