-- Leo's gemini proxy
-- Connecting to git.thebackupbox.net:1965...
-- Connected
-- Sending request
-- Meta line: 20 text/gemini
repo: janusweb action: commit revision: path_from: revision_from: 679dec1a390eadf6c70142c3ba8ab3c5382c799f: path_to: revision_to:
commit 679dec1a390eadf6c70142c3ba8ab3c5382c799f Author: James Baicoianu <james_github@baicoianu.com> Date: Mon May 30 14:56:50 2016 -0700 Added imagediff lib diff --git a/tests/imagediff.js b/tests/imagediff.js new file mode 100644 index 0000000000000000000000000000000000000000..522295107bbc65b36edefe9936e9d2438f7406f4 --- /dev/null +++ b/tests/imagediff.js @@ -0,0 +1,405 @@ +(function (name, definition) { + var root = this; + if (typeof module !== 'undefined') { + try { + var Canvas = require('canvas'); + } catch (e) { + throw new Error( + e.message + '\n' + + 'Please see https://github.com/HumbleSoftware/js-imagediff#cannot-find-module-canvas\n' + ); + } + module.exports = definition(root, name, Canvas); + } else if (typeof define === 'function' && typeof define.amd === 'object') { + define(definition); + } else { + root[name] = definition(root, name); + } +})('imagediff', function (root, name, Canvas) { + + var + TYPE_CANVAS = /\[object (Canvas|HTMLCanvasElement)\]/i, + TYPE_CONTEXT = /\[object CanvasRenderingContext2D\]/i, + TYPE_IMAGE = /\[object (Image|HTMLImageElement)\]/i, + TYPE_IMAGE_DATA = /\[object ImageData\]/i, + + UNDEFINED = 'undefined', + + canvas = getCanvas(), + context = canvas.getContext('2d'), + previous = root[name], + imagediff, jasmine; + + // Creation + function getCanvas (width, height) { + var + canvas = Canvas ? + new Canvas() : + document.createElement('canvas'); + if (width) canvas.width = width; + if (height) canvas.height = height; + return canvas; + } + function getImageData (width, height) { + canvas.width = width; + canvas.height = height; + context.clearRect(0, 0, width, height); + return context.createImageData(width, height); + } + + + // Type Checking + function isImage (object) { + return isType(object, TYPE_IMAGE); + } + function isCanvas (object) { + return isType(object, TYPE_CANVAS); + } + function isContext (object) { + return isType(object, TYPE_CONTEXT); + } + function isImageData (object) { + return !!(object && + isType(object, TYPE_IMAGE_DATA) && + typeof(object.width) !== UNDEFINED && + typeof(object.height) !== UNDEFINED && + typeof(object.data) !== UNDEFINED); + } + function isImageType (object) { + return ( + isImage(object) || + isCanvas(object) || + isContext(object) || + isImageData(object) + ); + } + function isType (object, type) { + return typeof (object) === 'object' && !!Object.prototype.toString.apply(object).match(type); + } + + + // Type Conversion + function copyImageData (imageData) { + var + height = imageData.height, + width = imageData.width, + data = imageData.data, + newImageData, newData, i; + + canvas.width = width; + canvas.height = height; + newImageData = context.getImageData(0, 0, width, height); + newData = newImageData.data; + + for (i = imageData.data.length; i--;) { + newData[i] = data[i]; + } + + return newImageData; + } + function toImageData (object) { + if (isImage(object)) { return toImageDataFromImage(object); } + if (isCanvas(object)) { return toImageDataFromCanvas(object); } + if (isContext(object)) { return toImageDataFromContext(object); } + if (isImageData(object)) { return object; } + } + function toImageDataFromImage (image) { + var + height = image.height, + width = image.width; + canvas.width = width; + canvas.height = height; + context.clearRect(0, 0, width, height); + context.drawImage(image, 0, 0); + return context.getImageData(0, 0, width, height); + } + function toImageDataFromCanvas (canvas) { + var + height = canvas.height, + width = canvas.width, + context = canvas.getContext('2d'); +console.log(canvas, context); + return context.getImageData(0, 0, width, height); + } + function toImageDataFromContext (context) { + var + canvas = context.canvas, + height = canvas.height, + width = canvas.width; + return context.getImageData(0, 0, width, height); + } + function toCanvas (object) { + var + data = toImageData(object), + canvas = getCanvas(data.width, data.height), + context = canvas.getContext('2d'); + + context.putImageData(data, 0, 0); + return canvas; + } + + + // ImageData Equality Operators + function equalWidth (a, b) { + return a.width === b.width; + } + function equalHeight (a, b) { + return a.height === b.height; + } + function equalDimensions (a, b) { + return equalHeight(a, b) && equalWidth(a, b); + } + function equal (a, b, tolerance) { + + var + aData = a.data, + bData = b.data, + length = aData.length, + i; + + tolerance = tolerance || 0; + + if (!equalDimensions(a, b)) return false; + for (i = length; i--;) if (aData[i] !== bData[i] && Math.abs(aData[i] - bData[i]) > tolerance) return false; + + return true; + } + + + // Diff + function diff (a, b, options) { + return (equalDimensions(a, b) ? diffEqual : diffUnequal)(a, b, options); + } + function diffEqual (a, b, options) { + + var + height = a.height, + width = a.width, + c = getImageData(width, height), // c = a - b + aData = a.data, + bData = b.data, + cData = c.data, + length = cData.length, + i; + + for (i = 0; i < length; i += 4) { + cData[i] = Math.abs(aData[i] - bData[i]); + cData[i+1] = Math.abs(aData[i+1] - bData[i+1]); + cData[i+2] = Math.abs(aData[i+2] - bData[i+2]); + cData[i+3] = Math.abs(255 - Math.abs(aData[i+3] - bData[i+3])); + } + + return c; + } + function diffUnequal (a, b, options) { + + var + height = Math.max(a.height, b.height), + width = Math.max(a.width, b.width), + c = getImageData(width, height), // c = a - b + aData = a.data, + bData = b.data, + cData = c.data, + align = options && options.align, + rowOffset, + columnOffset, + row, column, + i, j; + + + for (i = cData.length - 1; i > 0; i = i - 4) { + cData[i] = 255; + } + + // Add First Image + offsets(a); + for (row = a.height; row--;){ + for (column = a.width; column--;) { + i = 4 * ((row + rowOffset) * width + (column + columnOffset)); + j = 4 * (row * a.width + column); + cData[i+0] = aData[j+0]; // r + cData[i+1] = aData[j+1]; // g + cData[i+2] = aData[j+2]; // b + // cData[i+3] = aData[j+3]; // a + } + } + + // Subtract Second Image + offsets(b); + for (row = b.height; row--;){ + for (column = b.width; column--;) { + i = 4 * ((row + rowOffset) * width + (column + columnOffset)); + j = 4 * (row * b.width + column); + cData[i+0] = Math.abs(cData[i+0] - bData[j+0]); // r + cData[i+1] = Math.abs(cData[i+1] - bData[j+1]); // g + cData[i+2] = Math.abs(cData[i+2] - bData[j+2]); // b + } + } + + // Helpers + function offsets (imageData) { + if (align === 'top') { + rowOffset = 0; + columnOffset = 0; + } else { + rowOffset = Math.floor((height - imageData.height) / 2); + columnOffset = Math.floor((width - imageData.width) / 2); + } + } + + return c; + } + + + // Validation + function checkType () { + var i; + for (i = 0; i < arguments.length; i++) { + if (!isImageType(arguments[i])) { + throw { + name : 'ImageTypeError', + message : 'Submitted object was not an image.' + }; + } + } + } + + + // Jasmine Matchers + function get (element, content) { + element = document.createElement(element); + if (element && content) { + element.innerHTML = content; + } + return element; + } + + function imageDiffEqualMessage (actual, expected) { + var + div = get('div'), + a = get('div', '<div>Actual:</div>'), + b = get('div', '<div>Expected:</div>'), + c = get('div', '<div>Diff:</div>'), + diff = imagediff.diff(actual, expected), + canvas = getCanvas(), + context; + + canvas.height = diff.height; + canvas.width = diff.width; + + div.style.overflow = 'hidden'; + a.style.float = 'left'; + b.style.float = 'left'; + c.style.float = 'left'; + + context = canvas.getContext('2d'); + context.putImageData(diff, 0, 0); + + a.appendChild(toCanvas(actual)); + b.appendChild(toCanvas(expected)); + c.appendChild(canvas); + + div.appendChild(a); + div.appendChild(b); + div.appendChild(c); + + return div; + } + + jasmine = { + + toBeImageData : function () { + return { + compare: function (actual) { + return { + pass: imagediff.isImageData(actual) + }; + } + }; + }, + + toImageDiffEqual: function () { + return { + compare: function (actual, expected, tolerance) { + var + result = {}; + + result.pass = imagediff.equal(actual, expected, tolerance); + if (typeof (document) !== UNDEFINED) { + result.message = imageDiffEqualMessage(actual, expected); + } + return result; + }, + negativeCompare: function (actual, expected, tolerance) { + return { + pass: !imagediff.equal(actual, expected, tolerance), + message: 'Expected not to be equal.' + }; + } + }; + } + }; + + + // Image Output + function imageDataToPNG (imageData, outputFile, callback) { + + var + canvas = toCanvas(imageData), + base64Data, + decodedImage; + + callback = callback || Function; + + base64Data = canvas.toDataURL().replace(/^data:image\/\w+;base64,/,""); + decodedImage = new Buffer(base64Data, 'base64'); + require('fs').writeFile(outputFile, decodedImage, callback); + } + + + // Definition + imagediff = { + + createCanvas : getCanvas, + createImageData : getImageData, + + isImage : isImage, + isCanvas : isCanvas, + isContext : isContext, + isImageData : isImageData, + isImageType : isImageType, + + toImageData : function (object) { + checkType(object); + if (isImageData(object)) { return copyImageData(object); } + return toImageData(object); + }, + + equal : function (a, b, tolerance) { + checkType(a, b); + a = toImageData(a); + b = toImageData(b); + return equal(a, b, tolerance); + }, + diff : function (a, b, options) { + checkType(a, b); + a = toImageData(a); + b = toImageData(b); + return diff(a, b, options); + }, + + jasmine : jasmine, + + // Compatibility + noConflict : function () { + root[name] = previous; + return imagediff; + } + }; + + if (typeof module !== 'undefined') { + imagediff.imageDataToPNG = imageDataToPNG; + } + + return imagediff; +}); diff --git a/tests/karma.conf.js b/tests/karma.conf.js
--- a/tests/karma.conf.js +++ b/tests/karma.conf.js @@ -15,9 +15,9 @@ module.exports = function(config) { // list of files / patterns to load in the browser files: [ - //'build/**', {pattern: 'build/*', watched: true, included: true, served: true}, {pattern: 'build/media/**', watched: false, included: false, served: true}, + 'tests/imagediff.js', 'tests/*.test.js' ],
-----END OF PAGE-----
-- Response ended
-- Page fetched on Sun Jun 2 18:38:27 2024