#!/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 "); 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; }