@alttiri/image-hash
Version:
Alt-Image-Hash. An alternative image hashing library.
96 lines (95 loc) • 3.57 kB
JavaScript
import { BiImageData } from "./mono-image-data.js";
import { calculateAverage, calculateMedian } from "./median.js";
export function dHashCore({ data, width, height }) {
const _width = width - 1;
const hash = new Uint8Array(_width * height);
for (let y = 0; y < height; y++) {
for (let x = 0; x < _width; x++) {
hash[y * _width + x] = data[y * width + x + 1] > data[y * width + x] ? 255 : 0;
}
}
return new BiImageData(hash, _width, height);
}
export function aHashCore({ data, width, height }) {
const mean = calculateAverage(data);
const hash = new Uint8Array(width * height);
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
hash[y * width + x] = data[y * width + x] > mean ? 255 : 0;
}
}
return new BiImageData(hash, width, height);
}
export function _mHashCoreClassic(data, width, height) {
const median = calculateMedian(data);
const hash = new Uint8Array(width * height);
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
hash[y * width + x] = data[y * width + x] > median ? 255 : 0;
}
}
return hash;
}
export function mHashCoreClassic({ data, width, height }) {
return new BiImageData(_mHashCoreClassic(data, width, height), width, height);
}
export function mHashCore({ data, width, height }) {
return new BiImageData(_mHashCore(data, width, height), width, height);
}
/**
* Two conditions for the proper handling of images with extreme median values (~0 or ~255). Do not edit.
*
* On dark images the median value will be a black pixel.
* On light images the median value will be a white pixel.
*
* So, it prefers to display the light details on dark images and vice versa.
*
* Check the "big" hashes for the follow images:
* - `black-bg-orthocanna-500x500`
* - `screenshot-dark-purple-flower-1353x851` (look at the text on the screenshot)
*/
export function _mHashCore(data, width, height) {
const median = calculateMedian(data);
const hash = new Uint8Array(width * height);
if (median < 128) { // if value === median -> 0
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
hash[y * width + x] = data[y * width + x] > median ? 255 : 0;
}
}
}
else { // if value === median -> 255
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
hash[y * width + x] = data[y * width + x] < median ? 0 : 255;
}
}
}
return hash;
}
export function bHashCore({ data, width, height }, bandCount) {
if (bandCount) {
bandCount = Math.min(height, bandCount);
}
else {
bandCount = Math.ceil(height / 2);
}
const yScale = height / bandCount;
const hashes = [];
for (let bandNum = 0, offset = 0; bandNum < bandCount; bandNum++) {
const fromY = Math.round(yScale * bandNum);
const toY = Math.round(yScale * (bandNum + 1));
const bandHeight = toY - fromY;
const pixelsInBand = bandHeight * width;
const view = new Uint8Array(data.buffer, offset, pixelsInBand);
const hash = _mHashCore(view, width, bandHeight);
hashes.push(hash);
offset += pixelsInBand;
}
const result = new Uint8Array(width * height);
for (let i = 0, offset = 0; i < hashes.length; i++) {
result.set(hashes[i], offset);
offset += hashes[i].length;
}
return new BiImageData(result, width, height);
}