Repository: commonsmachinery/blockhash-js
Branch: master
Commit: 2084417e4000
Files: 46
Total size: 21.3 KB
Directory structure:
gitextract_ib4rtlel/
├── .gitignore
├── .jshint-emacs.js
├── .jshintrc
├── LICENSE
├── Makefile
├── README.md
├── index.js
├── package.json
└── test/
├── .jshintrc
├── data/
│ ├── 00002701_16_1.txt
│ ├── 00002701_16_2.txt
│ ├── 00011601_16_1.txt
│ ├── 00011601_16_2.txt
│ ├── 00094701_16_1.txt
│ ├── 00094701_16_2.txt
│ ├── 00106901_16_1.txt
│ ├── 00106901_16_2.txt
│ ├── 00133601_16_1.txt
│ ├── 00133601_16_2.txt
│ ├── 00136101_16_1.txt
│ ├── 00136101_16_2.txt
│ ├── 00631701_16_1.txt
│ ├── 00631701_16_2.txt
│ ├── 00631801_16_1.txt
│ ├── 00631801_16_2.txt
│ ├── 01109801_16_1.txt
│ ├── 01109801_16_2.txt
│ ├── 06855701_16_1.txt
│ ├── 06855701_16_2.txt
│ ├── 24442301_16_1.txt
│ ├── 24442301_16_2.txt
│ ├── 32499201_16_1.txt
│ ├── 32499201_16_2.txt
│ ├── Babylonian_16_1.txt
│ ├── Babylonian_16_2.txt
│ ├── clipper_ship_16_1.txt
│ ├── clipper_ship_16_2.txt
│ ├── emptyBasket_16_1.txt
│ ├── emptyBasket_16_2.txt
│ ├── puffy_white_16_1.txt
│ ├── puffy_white_16_2.txt
│ ├── sources.txt
│ ├── stoplights_16_1.txt
│ ├── stoplights_16_2.txt
│ └── values.txt
└── tests.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
*~
node_modules
================================================
FILE: .jshint-emacs.js
================================================
/*jshint node: true */
var reporter_name = "jhlint";
module.exports = {
reporter: function (data) {
"use strict";
var str = '',
errors = [];
data.forEach(function (data) {
var file = data.file;
if (data.error) {
data.error.file = file;
errors.push( data.error );
}
});
errors.forEach(function (error) {
var file = error.file,
error_id;
if (error.id === '(error)') {
error_id = 'ERROR';
} else {
error_id = 'WARNING';
}
str += file + ':' + error.line + ':' + error.character + ': error ( ' + error.code + ' ) ' + error.reason + '\n' + error.evidence + '\n';
});
if (str) {
process.stdout.write(str + "\n");
}
}
};
================================================
FILE: .jshintrc
================================================
{
"bitwise": false,
"curly": true,
"eqeqeq": true,
"forin": true,
"freeze": true,
"immed": true,
"latedef": true,
"newcap": true,
"undef": true,
"unused": "vars",
"strict": true,
"browser": true
}
================================================
FILE: LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2014 Commons Machinery
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: Makefile
================================================
top := $(CURDIR)
JSHINT = $(top)/node_modules/.bin/jshint
MOCHA = $(top)/node_modules/.bin/mocha
src = $(top)/blockhash.js
# Modules should add files to be checked with jshint
jshint-files = $(src) $(mocha-files)
# Modules should add files to be run as unit tests
mocha-files = $(top)/test/tests.js
REPORTER=
ifeq ($(EMACS),t)
REPORTER=--reporter=.jshint-emacs.js
endif
all: lint
clean:
lint:
$(JSHINT) $(REPORTER) $(jshint-files)
test:
$(MOCHA) $(MOCHA_FLAGS) $(mocha-files)
.PHONY: all clean lint test
================================================
FILE: README.md
================================================
blockhash-js
============
This is a perceptual image hash calculation tool based on algorithm descibed in
Block Mean Value Based Image Perceptual Hashing by Bian Yang, Fan Gu and Xiamu Niu.
Installation
-----
This module is installed via npm:
```
$ npm install blockhash
```
Use in the browser
-----
To use this library in the browser, you can build it with Browserify
with something like `browserify index.js --standalone blockhashjs >
blockhash.js`
Include it and `zlib.js` on your page:
```html
Blockhash
```
Call `blockhash(src, bits, method, callback)`, where
`src` is an image URL, `bits` is the number of bits in a row, `method`
is a number 1-2 (see below), and `callback` is a function with
`(error, result)` signature. On success, `result` will be array of
binary values.
The available methods are:
1. Quick and crude, non-overlapping blocks
2. Precise but slower, non-overlapping blocks
Method 2 is recommended as a good tradeoff between speed and good
matches on any image size. The quick ones are only advisable when the
image width and height are an even multiple of the number of blocks
used.
License
-------
Copyright 2014 Commons Machinery http://commonsmachinery.se/
Distributed under an MIT license, please see LICENSE in the top dir.
Contact: dev@commonsmachinery.se
================================================
FILE: index.js
================================================
// Perceptual image hash calculation tool based on algorithm descibed in
// Block Mean Value Based Image Perceptual Hashing by Bian Yang, Fan Gu and Xiamu Niu
//
// Copyright 2014 Commons Machinery http://commonsmachinery.se/
// Distributed under an MIT license, please see LICENSE in the top dir.
var PNG = require('png-js');
var jpeg = require('jpeg-js');
var one_bits = [0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4];
/* Calculate the hamming distance for two hashes in hex format */
var hammingDistance = function(hash1, hash2) {
var d = 0;
var i;
if (hash1.length !== hash2.length) {
throw new Error("Can't compare hashes with different length");
}
for (i = 0; i < hash1.length; i++) {
var n1 = parseInt(hash1[i], 16);
var n2 = parseInt(hash2[i], 16);
d += one_bits[n1 ^ n2];
}
return d;
};
var median = function(data) {
var mdarr = data.slice(0);
mdarr.sort(function(a, b) { return a-b; });
if (mdarr.length % 2 === 0) {
return (mdarr[mdarr.length/2 - 1] + mdarr[mdarr.length/2]) / 2.0;
}
return mdarr[Math.floor(mdarr.length/2)];
};
var translate_blocks_to_bits = function(blocks, pixels_per_block) {
var half_block_value = pixels_per_block * 256 * 3 / 2;
var bandsize = blocks.length / 4;
// Compare medians across four horizontal bands
for (var i = 0; i < 4; i++) {
var m = median(blocks.slice(i * bandsize, (i + 1) * bandsize));
for (var j = i * bandsize; j < (i + 1) * bandsize; j++) {
var v = blocks[j];
// Output a 1 if the block is brighter than the median.
// With images dominated by black or white, the median may
// end up being 0 or the max value, and thus having a lot
// of blocks of value equal to the median. To avoid
// generating hashes of all zeros or ones, in that case output
// 0 if the median is in the lower value space, 1 otherwise
blocks[j] = Number(v > m || (Math.abs(v - m) < 1 && m > half_block_value));
}
}
};
var bits_to_hexhash = function(bitsArray) {
var hex = [];
for (var i = 0; i < bitsArray.length; i += 4) {
var nibble = bitsArray.slice(i, i + 4);
hex.push(parseInt(nibble.join(''), 2).toString(16));
}
return hex.join('');
};
var bmvbhash_even = function(data, bits) {
var blocksize_x = Math.floor(data.width / bits);
var blocksize_y = Math.floor(data.height / bits);
var result = [];
for (var y = 0; y < bits; y++) {
for (var x = 0; x < bits; x++) {
var total = 0;
for (var iy = 0; iy < blocksize_y; iy++) {
for (var ix = 0; ix < blocksize_x; ix++) {
var cx = x * blocksize_x + ix;
var cy = y * blocksize_y + iy;
var ii = (cy * data.width + cx) * 4;
var alpha = data.data[ii+3];
if (alpha === 0) {
total += 765;
} else {
total += data.data[ii] + data.data[ii+1] + data.data[ii+2];
}
}
}
result.push(total);
}
}
translate_blocks_to_bits(result, blocksize_x * blocksize_y);
return bits_to_hexhash(result);
};
var bmvbhash = function(data, bits) {
var result = [];
var i, j, x, y;
var block_width, block_height;
var weight_top, weight_bottom, weight_left, weight_right;
var block_top, block_bottom, block_left, block_right;
var y_mod, y_frac, y_int;
var x_mod, x_frac, x_int;
var blocks = [];
var even_x = data.width % bits === 0;
var even_y = data.height % bits === 0;
if (even_x && even_y) {
return bmvbhash_even(data, bits);
}
// initialize blocks array with 0s
for (i = 0; i < bits; i++) {
blocks.push([]);
for (j = 0; j < bits; j++) {
blocks[i].push(0);
}
}
block_width = data.width / bits;
block_height = data.height / bits;
for (y = 0; y < data.height; y++) {
if (even_y) {
// don't bother dividing y, if the size evenly divides by bits
block_top = block_bottom = Math.floor(y / block_height);
weight_top = 1;
weight_bottom = 0;
} else {
y_mod = (y + 1) % block_height;
y_frac = y_mod - Math.floor(y_mod);
y_int = y_mod - y_frac;
weight_top = (1 - y_frac);
weight_bottom = (y_frac);
// y_int will be 0 on bottom/right borders and on block boundaries
if (y_int > 0 || (y + 1) === data.height) {
block_top = block_bottom = Math.floor(y / block_height);
} else {
block_top = Math.floor(y / block_height);
block_bottom = Math.ceil(y / block_height);
}
}
for (x = 0; x < data.width; x++) {
var ii = (y * data.width + x) * 4;
var avgvalue, alpha = data.data[ii+3];
if (alpha === 0) {
avgvalue = 765;
} else {
avgvalue = data.data[ii] + data.data[ii+1] + data.data[ii+2];
}
if (even_x) {
block_left = block_right = Math.floor(x / block_width);
weight_left = 1;
weight_right = 0;
} else {
x_mod = (x + 1) % block_width;
x_frac = x_mod - Math.floor(x_mod);
x_int = x_mod - x_frac;
weight_left = (1 - x_frac);
weight_right = x_frac;
// x_int will be 0 on bottom/right borders and on block boundaries
if (x_int > 0 || (x + 1) === data.width) {
block_left = block_right = Math.floor(x / block_width);
} else {
block_left = Math.floor(x / block_width);
block_right = Math.ceil(x / block_width);
}
}
// add weighted pixel value to relevant blocks
blocks[block_top][block_left] += avgvalue * weight_top * weight_left;
blocks[block_top][block_right] += avgvalue * weight_top * weight_right;
blocks[block_bottom][block_left] += avgvalue * weight_bottom * weight_left;
blocks[block_bottom][block_right] += avgvalue * weight_bottom * weight_right;
}
}
for (i = 0; i < bits; i++) {
for (j = 0; j < bits; j++) {
result.push(blocks[i][j]);
}
}
translate_blocks_to_bits(result, block_width * block_height);
return bits_to_hexhash(result);
};
var blockhashData = function(imgData, bits, method) {
var hash;
if (method === 1) {
hash = bmvbhash_even(imgData, bits);
}
else if (method === 2) {
hash = bmvbhash(imgData, bits);
}
else {
throw new Error("Bad hashing method");
}
return hash;
};
var blockhash = function(src, bits, method, callback) {
var xhr;
xhr = new XMLHttpRequest();
xhr.open('GET', src, true);
xhr.responseType = "arraybuffer";
xhr.onload = function() {
var data, contentType, imgData, jpg, png, hash;
data = new Uint8Array(xhr.response || xhr.mozResponseArrayBuffer);
contentType = xhr.getResponseHeader('content-type');
try {
if (contentType === 'image/png') {
png = new PNG(data);
imgData = {
width: png.width,
height: png.height,
data: new Uint8Array(png.width * png.height * 4)
};
png.copyToImageData(imgData, png.decodePixels());
}
else if (contentType === 'image/jpeg') {
imgData = jpeg.decode(data);
}
if (!imgData) {
throw new Error("Couldn't decode image");
}
// TODO: resize if required
hash = blockhashData(imgData, bits, method);
callback(null, hash);
} catch (err) {
callback(err, null);
}
};
xhr.onerror = function(err) {
callback(err, null);
};
xhr.send();
};
module.exports = {
hammingDistance: hammingDistance,
blockhash: blockhash,
blockhashData: blockhashData
};
================================================
FILE: package.json
================================================
{
"name": "blockhash",
"version": "0.3",
"homepage": "https://github.com/commonsmachinery/blockhash-js",
"author": "Commons Machinery ",
"description": "Perceptual image hash calculation tool",
"repository": {
"type": "git",
"url": "https://github.com/commonsmachinery/blockhash-js.git"
},
"scripts": {
"test": "mocha"
},
"main": "index.js",
"browser": {
"png-js": "./node_modules/png-js/png.js"
},
"browserify-shim": {
"png-js": "PNG"
},
"browserify": {
"transform": [
"browserify-shim"
]
},
"keywords": [
"image",
"hashing",
"perceptual"
],
"devDependencies": {
"browserify-shim": "^3.8.0",
"expect.js": "*",
"glob": "*",
"jpeg-js": "0.0.4",
"jshint": "*",
"mocha": "*",
"png-js": "^0.1.1"
},
"license": "MIT"
}
================================================
FILE: test/.jshintrc
================================================
{
"bitwise": true,
"curly": true,
"eqeqeq": true,
"forin": true,
"freeze": true,
"immed": true,
"latedef": true,
"newcap": true,
"undef": true,
"unused": "vars",
"strict": true,
"node": true,
"predef": [ "-Promise" ]
}
================================================
FILE: test/data/00002701_16_1.txt
================================================
f81bf99ffb803400e07f8c5d849f049707033a033fe33fe1bfe00e618ee30ca7 00002701.jpg
================================================
FILE: test/data/00002701_16_2.txt
================================================
f81bf99ffb803400e07f8c7d049f058706013e233fe33fe11f600e638ea30def 00002701.jpg
================================================
FILE: test/data/00011601_16_1.txt
================================================
3fff1ca004e80fe81fe00fe01fe81de8fffb8ffb00e3000000f303ff83ff4185 00011601.jpg
================================================
FILE: test/data/00011601_16_2.txt
================================================
3fff1ca004e80fe81fe00fe01fe81de8fffb0ffb00610031003b03ff80df01ff 00011601.jpg
================================================
FILE: test/data/00094701_16_1.txt
================================================
03ff007d02da33f325e366f90501379fd103c12ffd04fc787ff31e511f111702 00094701.jpg
================================================
FILE: test/data/00094701_16_2.txt
================================================
03ff007d02da33f325e366690581b79fd103f307fc0474f93ff31e117f550700 00094701.jpg
================================================
FILE: test/data/00106901_16_1.txt
================================================
ff80fe80fe00fe01ff00ff00ff00ff00fec0ff00f820fae0fcc0e7f0e7e0e0c0 00106901.jpg
================================================
FILE: test/data/00106901_16_2.txt
================================================
ff80fe80fc01fe01ff00ff00ff00ff00fec0fd20f0e0fac0ecf0e7f0e7e0e040 00106901.jpg
================================================
FILE: test/data/00133601_16_1.txt
================================================
00000fe07ff8fff81ff839d831883bcc39dc31ac300c3ffc9ef88e708041f1bf 00133601.jpg
================================================
FILE: test/data/00133601_16_2.txt
================================================
00000fe07ff8fff81ff8399831983bcc35ac303c384c3ffc8ef00660c003ffff 00133601.jpg
================================================
FILE: test/data/00136101_16_1.txt
================================================
000081f887ff8fff0fe00fe00ff80ff807fc07fc03f803f803e001e007f0ffff 00136101.jpg
================================================
FILE: test/data/00136101_16_2.txt
================================================
000083f887fe8fff0fe00fe00ff80ff807fc07f807f803f803e003e007e0ffff 00136101.jpg
================================================
FILE: test/data/00631701_16_1.txt
================================================
fffffc01bd0180018c61806fcf7181efae6d8e71893983878001800fc0ffefff 00631701.jpg
================================================
FILE: test/data/00631701_16_2.txt
================================================
fffff803bd018001886382e78f7382afceef8e71813187070001800fc0ffffff 00631701.jpg
================================================
FILE: test/data/00631801_16_1.txt
================================================
ffff8001bfb182018e8186e58dd587e58641807187df9be780018007e07fffff 00631801.jpg
================================================
FILE: test/data/00631801_16_2.txt
================================================
ffffc001bfa182018aa186e1877786e78623827385399fcf0001800fc0ffffff 00631801.jpg
================================================
FILE: test/data/01109801_16_1.txt
================================================
f80ff80ff007f007f007f183f4c3c5c3c7c3c7e3c1e3c007c003c007e087ffff 01109801.jpg
================================================
FILE: test/data/01109801_16_2.txt
================================================
f80ff80ff007f007f007f183f4c3c5c3c7c3c7e3c1e3c007c007c007e007ffff 01109801.jpg
================================================
FILE: test/data/06855701_16_1.txt
================================================
fefd0fff000f0003037f03bc00bd11ff01ff01fe01bc01ff01ff007f03fd03f8 06855701.jpg
================================================
FILE: test/data/06855701_16_2.txt
================================================
fefd0fff000f0003037f03bc01bc11ff01fe01be01bd03ff007f007f0ffd0bf0 06855701.jpg
================================================
FILE: test/data/24442301_16_1.txt
================================================
ffff8101bf0192059005860f9d8fbf8d9f818f818f998e8b8f8982e18001ffff 24442301.jpg
================================================
FILE: test/data/24442301_16_2.txt
================================================
ffff8101bf0192059005860f9d8fbfa99f818f818f999e198fc182e18001ffff 24442301.jpg
================================================
FILE: test/data/32499201_16_1.txt
================================================
0002001f1fff1fff7ff31ff303f300006f9178f0f8701ee0ffc8ce88c1cc01fc 32499201.jpg
================================================
FILE: test/data/32499201_16_2.txt
================================================
0002001f1fff1fff7ff71ff301f300007f9278f0f8700fc0ff98cc88c1cc03fc 32499201.jpg
================================================
FILE: test/data/Babylonian_16_1.txt
================================================
fe7ffe7ffe7ffc7ffc7ffc7ffc7f0000c103e187f18ff08f8003fc3ff81ff81f Babylonian.png
================================================
FILE: test/data/Babylonian_16_2.txt
================================================
fe7ffe7ffe7ffc7ffc7ffc7ffc000000e107e187f89fe007c00ff81ff81ff83f Babylonian.png
================================================
FILE: test/data/clipper_ship_16_1.txt
================================================
00007ff07ff07fe07fe67ff07560600077fe701e7f5e000079fd40410001ffff clipper_ship.jpg
================================================
FILE: test/data/clipper_ship_16_2.txt
================================================
00007ff07ff07fe07fe67ff07560600077fe701e7f5e000079fd40410001ffff clipper_ship.jpg
================================================
FILE: test/data/emptyBasket_16_1.txt
================================================
fffffe07e00380009b899f818f8f8c439f9fdc0fc807c803c003c00fe03ff1ff emptyBasket.png
================================================
FILE: test/data/emptyBasket_16_2.txt
================================================
fffffe07e00380009f899f818f0b8c4b9f9fd00fcc07cc03c003e00fe07ff1ff emptyBasket.png
================================================
FILE: test/data/puffy_white_16_1.txt
================================================
00000000fffffffff803f807f807f80ff90ff90fb90c9980ffffffff00000000 puffy_white.png
================================================
FILE: test/data/puffy_white_16_2.txt
================================================
00000000fffffffff803f807f807f80ff90ff90fb90c9980ffffffff00000000 puffy_white.png
================================================
FILE: test/data/sources.txt
================================================
puffy_white.jpg - http://www.nasa.gov/multimedia/imagegallery/image_feature_2466.html
clipper_ship.jpg - http://commons.wikimedia.org/wiki/File:%27Clipper_Ship_Great_Republic%27_by_James_Butterworth,_c._1853_-_Old_State_House_Museum,_Boston,_MA_-_IMG_6709.JPG
emptyBasket.png - https://openclipart.org/detail/194657/plastic-laundry-basket-by-gubrww2-194657
Babylonian.png - https://openclipart.org/detail/194594/babylonian-or-summerian-religious-deity-by-lordoftheloch-194594
The remaining test images come from http://www.getty.edu/about/opencontent.html
================================================
FILE: test/data/stoplights_16_1.txt
================================================
0fe01fe007e027c037c077c00fe00fe007e047c001c003c007e007e007e003e0 stoplights.jpg
================================================
FILE: test/data/stoplights_16_2.txt
================================================
0fe01fe007e027c037c077c00fc00fe007e047c001c003c007e007e007e003c0 stoplights.jpg
================================================
FILE: test/data/values.txt
================================================
00136101_16_1 = 000001f887ff8fff0fe00fe00ff00ff807fc07f803f803f801e001e007f0ffff
00106901_16_1 = ff80fe80fc00fe01fe00ff00ff00ff00fec0ff00f820f8e0fcc0e5f0e7e0e0c0
00002701_16_1 = f81bf91ffb803400e07f8c5d049f049706033a033fe33fe1bfe00e618ee30ca3
00133601_16_1 = 00000fe03ff8fff81f7839d831883bcc31dc31ac300c3ffc9ef88e608041f1bf
00631701_16_1 = fffffc019d0180018c61806fcf7181cfae6d8e71891983878000800fc0ffefff
00631801_16_1 = ffff8001bfb180018e8186e58dd187e586418071879f9be780018007c07fffff
01109801_16_1 = f80ff80ff007f003f007f183f4c3c1c3c7c3c7e3c1e3c003c003c007c087ffff
32499201_16_1 = 0002000f1fff1fff7ff31ff301f300006f9078f0f8701ee0ffc8ce88c1c401fc
24442301_16_1 = ffff8101bf018205900586079d8fbf8d9f818f818f998e0b8f8982618001ffff
06855701_16_1 = fe7d0fff000f0003037f03bc00bc11ff01ff01be01bc01ff01ff003f03fd03f8
Babylonian_16_1 = fe7ffe7ffe7ffc7ffc7ffc7ffc7f0000c103e187f18ff00f8003fc3ff81ff81f
clipper_ship_16_1 = 00007ff07fe07fe07fe67ff07520600077fe601e7f5e000079fd40410001fffe
emptyBasket_16_1 = fffffc07e00380009b099f818f8f8c439f9fcc0fc807c803c003c00fe03ff1ff
puffy_white_16_1 = 00000000ffbffffff803f807f807f807f90ff90fb90c9900ffff7fff00000000
00011601_16_1 = 3fff1c2004e80fe81fe00fe00fe81de8fffb8ffb0063000000f303ff81ff4185
00094701_16_1 = 03ff007d025a33f325e366f905013797d103c12ffd04fc687ff31e111f111702
00002701_16_2 = f81bf91ffb803400e07f0c7d049f058706013e033fe33fe11f600e618ea30def
00136101_16_2 = 000003f887fe8fff0fe00fe00ff00ff807fc07f807f803f003e003e007e0fffe
00106901_16_2 = ff80fe80fc01fe00fe00ff00ff00ff00fec0fd00f0e0fac0ecf0e7f0e7e0e000
00133601_16_2 = 00000fe03ff8fff81ff8399831883bcc35ac301c384c3ffc8ef006608003ffff
00631701_16_2 = fffff803b9018001886382e7877382afceef8e61813187070001800f80ffffff
00631801_16_2 = ffff8001bfa182018aa186e1873786e78623827385319fcf0000800fc0ffffff
01109801_16_2 = f80ff80ff007f003f007f183e4c3c5c3c7c3c6e3c1e3c007c007c007e007efff
32499201_16_2 = 0002001f0fff1fff7ff71ff300f300007f1278f0f8700fc0ff98cc88c1cc01fc
06855701_16_2 = fefd07ff000f0003037f02bc01bc11ff01fe01be01bc03ff007f007f07fd0bf0
24442301_16_2 = ffff8101bf0192019005860f9d8fbf899f818f818f998e198fc182618001ffff
Babylonian_16_2 = fe7ffe7ffe7ffc7ffc7ffc7f7c000000e107e183f89fe007c00ff81ff81ff83f
clipper_ship_16_2 = 00007ff07fe07fe07fe67ff07520600077fe601e7f5e000079fd40410001fffe
emptyBasket_16_2 = fffffc07e00380009f099f818f0b8c4b9f9fc00fcc07cc03c003e00fe07ff1ff
puffy_white_16_2 = 00000000ffbffffff803f807f807f807f90ff90fb90c9900ffff7fff00000000
00011601_16_2 = 3fff1c2004e80fe81fe00fe01fe81de0fffb0ffb00210031003b03ff00df01ff
00094701_16_2 = 03ff007d025a33f325e366690501b79fd103f3077c0474f93ff31e113f550700
================================================
FILE: test/tests.js
================================================
/* global describe, it, JpegImage */
'use strict';
var expect = require('expect.js');
var glob = require('glob');
var path = require('path');
var fs = require('fs');
var blockhash = require('..');
var PNG = require('png-js');
var jpeg = require('jpeg-js');
var testFiles = glob.sync('test/data/*.jpg')
.concat(glob.sync('test/data/*.png'));
testFiles.forEach(function(fn) {
describe(fn, function(){
var ext = path.extname(fn);
var basename = path.basename(fn, ext);
var bits = 16;
[1, 2].forEach(function(m) {
it('method' + m, function(done) {
var data, getImgData, hash, expectedHash;
data = new Uint8Array(fs.readFileSync(fn));
switch (ext) {
case '.jpg':
getImgData = function(next) {
next(jpeg.decode(data));
};
break;
case '.png':
getImgData = function(next) {
var png = new PNG(data);
var imgData = {
width: png.width,
height: png.height,
data: new Uint8Array(png.width * png.height * 4)
};
png.decodePixels(function(pixels) {
png.copyToImageData(imgData, pixels);
next(imgData);
});
};
}
getImgData(function(imgData) {
hash = blockhash.blockhashData(imgData, bits, m);
expectedHash = fs.readFileSync("test/data/" + basename + "_" + bits + "_" + m + ".txt", {
encoding: 'utf-8'
}).split(/\s/)[0];
// use hamming distance to iron out little
// differences between this jpeg decoder and the one in PIL
var hd = blockhash.hammingDistance(expectedHash, hash);
expect(hd).to.be.lessThan(3);
done();
});
});
});
});
});