Exporting 1 const and 2 funcs

pull/3/head v1.1.0
Vitali Fedulov 2022-08-09 01:43:12 +02:00
parent 4258b41f4d
commit 009a20cb7c
3 changed files with 23 additions and 21 deletions

View File

@ -4,14 +4,14 @@ const (
// Icon parameters. // Icon parameters.
// Image resolution of the icon // Image resolution of the icon is very small
// is very small (11x11 pixels), therefore original // (11x11 pixels), therefore original image details
// image details are lost in downsampling, except // are lost in downsampling, except when source images
// when source images have very low resolution // have very low resolution (e.g. favicons or simple
// (e.g. favicons or simple logos). This is useful // logos). This is useful from the privacy perspective
// from the privacy perspective if you are to use // if you are to use generated icons in a large searchable
// generated icons in a large searchable database. // database.
iconSize = 11 IconSize = 11 // Exported to be used in package imagehash.
// Resampling rate defines how much information // Resampling rate defines how much information
// (how many pixels) from the source image are used // (how many pixels) from the source image are used
// to generate an icon. Too few will produce worse // to generate an icon. Too few will produce worse
@ -30,7 +30,7 @@ const (
// Similarity thresholds. // Similarity thresholds.
// Euclidean distance threshold (squared) for Y-channel. // Euclidean distance threshold (squared) for Y-channel.
thY = float64(iconSize*iconSize) * float64(colorDiff*colorDiff) * euclCoeff thY = float64(IconSize*IconSize) * float64(colorDiff*colorDiff) * euclCoeff
// Euclidean distance threshold (squared) for Cb and Cr channels. // Euclidean distance threshold (squared) for Cb and Cr channels.
thCbCr = thY * chanCoeff thCbCr = thY * chanCoeff
// Proportion similarity threshold (5%). // Proportion similarity threshold (5%).
@ -38,8 +38,8 @@ const (
// Auxiliary constants. // Auxiliary constants.
numPix = iconSize * iconSize numPix = IconSize * IconSize
largeIconSize = iconSize*2 + 1 largeIconSize = IconSize*2 + 1
resizedImgSize = largeIconSize * samples resizedImgSize = largeIconSize * samples
invSamplePixels2 = 1 / float64(samples*samples) invSamplePixels2 = 1 / float64(samples*samples)
oneNinth = 1 / float64(9) oneNinth = 1 / float64(9)

18
icon.go
View File

@ -62,7 +62,7 @@ func IconNN(img image.Image) IconT {
sumB += b >> 8 sumB += b >> 8
} }
} }
set(largeIcon, largeIconSize, image.Point{x, y}, Set(largeIcon, largeIconSize, image.Point{x, y},
float64(sumR)*invSamplePixels2, float64(sumR)*invSamplePixels2,
float64(sumG)*invSamplePixels2, float64(sumG)*invSamplePixels2,
float64(sumB)*invSamplePixels2) float64(sumB)*invSamplePixels2)
@ -71,7 +71,7 @@ func IconNN(img image.Image) IconT {
// Box blur filter with resizing to the final icon of smaller size. // Box blur filter with resizing to the final icon of smaller size.
icon := sizedIcon(iconSize) icon := sizedIcon(IconSize)
// Pixel positions in the final icon. // Pixel positions in the final icon.
var xd, yd int var xd, yd int
var c1, c2, c3, s1, s2, s3 float64 var c1, c2, c3, s1, s2, s3 float64
@ -85,14 +85,14 @@ func IconNN(img image.Image) IconT {
for n := -1; n <= 1; n++ { for n := -1; n <= 1; n++ {
for m := -1; m <= 1; m++ { for m := -1; m <= 1; m++ {
c1, c2, c3 = c1, c2, c3 =
get(largeIcon, largeIconSize, Get(largeIcon, largeIconSize,
image.Point{x + n, y + m}) image.Point{x + n, y + m})
s1, s2, s3 = s1+c1, s2+c2, s3+c3 s1, s2, s3 = s1+c1, s2+c2, s3+c3
} }
} }
yc, cb, cr = yCbCr( yc, cb, cr = yCbCr(
s1*oneNinth, s2*oneNinth, s3*oneNinth) s1*oneNinth, s2*oneNinth, s3*oneNinth)
set(icon, iconSize, image.Point{xd, yd}, Set(icon, IconSize, image.Point{xd, yd},
yc, cb, cr) yc, cb, cr)
s1, s2, s3 = 0, 0, 0 s1, s2, s3 = 0, 0, 0
} }
@ -106,7 +106,7 @@ func IconNN(img image.Image) IconT {
// with nil values, for example for convenient error handling. // with nil values, for example for convenient error handling.
// Then you can use icon.Pixels == nil condition. // Then you can use icon.Pixels == nil condition.
func EmptyIcon() (icon IconT) { func EmptyIcon() (icon IconT) {
icon = sizedIcon(iconSize) icon = sizedIcon(IconSize)
icon.Pixels = nil icon.Pixels = nil
return icon return icon
} }
@ -125,7 +125,8 @@ func arrIndex(p image.Point, size, ch int) (index int) {
// Set places pixel values in an icon at a point. // Set places pixel values in an icon at a point.
// c1, c2, c3 are color values for each channel // c1, c2, c3 are color values for each channel
// (RGB for example). Size is icon size. // (RGB for example). Size is icon size.
func set(icon IconT, size int, p image.Point, c1, c2, c3 float64) { // Exported to be used in package imagehash.
func Set(icon IconT, size int, p image.Point, c1, c2, c3 float64) {
// Multiplication by 255 is basically encoding float64 as uint16. // Multiplication by 255 is basically encoding float64 as uint16.
icon.Pixels[arrIndex(p, size, 0)] = uint16(c1 * 255) icon.Pixels[arrIndex(p, size, 0)] = uint16(c1 * 255)
icon.Pixels[arrIndex(p, size, 1)] = uint16(c2 * 255) icon.Pixels[arrIndex(p, size, 1)] = uint16(c2 * 255)
@ -135,7 +136,8 @@ func set(icon IconT, size int, p image.Point, c1, c2, c3 float64) {
// Get reads pixel values in an icon at a point. // Get reads pixel values in an icon at a point.
// c1, c2, c3 are color values for each channel // c1, c2, c3 are color values for each channel
// (RGB for example). // (RGB for example).
func get(icon IconT, size int, p image.Point) (c1, c2, c3 float64) { // Exported to be used in package imagehash.
func Get(icon IconT, size int, p image.Point) (c1, c2, c3 float64) {
// Division by 255 is basically decoding uint16 into float64. // Division by 255 is basically decoding uint16 into float64.
c1 = float64(icon.Pixels[arrIndex(p, size, 0)]) * one255th c1 = float64(icon.Pixels[arrIndex(p, size, 0)]) * one255th
c2 = float64(icon.Pixels[arrIndex(p, size, 1)]) * one255th c2 = float64(icon.Pixels[arrIndex(p, size, 1)]) * one255th
@ -224,7 +226,7 @@ func (icon IconT) ToRGBA(size int) *image.RGBA {
img := image.NewRGBA(image.Rect(0, 0, size, size)) img := image.NewRGBA(image.Rect(0, 0, size, size))
for x := 0; x < size; x++ { for x := 0; x < size; x++ {
for y := 0; y < size; y++ { for y := 0; y < size; y++ {
r, g, b := get(icon, size, image.Point{x, y}) r, g, b := Get(icon, size, image.Point{x, y})
img.Set(x, y, img.Set(x, y,
color.RGBA{uint8(r), uint8(g), uint8(b), 255}) color.RGBA{uint8(r), uint8(g), uint8(b), 255})
} }

View File

@ -59,7 +59,7 @@ func TestArrIndex(t *testing.T) {
func TestSet(t *testing.T) { func TestSet(t *testing.T) {
icon := sizedIcon(4) icon := sizedIcon(4)
set(icon, 4, image.Point{1, 1}, 13.5, 29.9, 95.9) Set(icon, 4, image.Point{1, 1}, 13.5, 29.9, 95.9)
expected := sizedIcon(4) expected := sizedIcon(4)
expectedPixels := []float64{0, 0, 0, 0, 0, 13.5, 0, 0, 0, 0, 0, expectedPixels := []float64{0, 0, 0, 0, 0, 13.5, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29.9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29.9, 0, 0, 0, 0,
@ -82,7 +82,7 @@ func TestGet(t *testing.T) {
for i := range iconPix { for i := range iconPix {
icon.Pixels[i] = uint16(iconPix[i] * 255) icon.Pixels[i] = uint16(iconPix[i] * 255)
} }
c1, c2, c3 := get(icon, 4, image.Point{1, 1}) c1, c2, c3 := Get(icon, 4, image.Point{1, 1})
if math.Abs(float64(c1)-13.5) > 0.1 || math.Abs(float64(c2)-29.9) > 0.1 || math.Abs(float64(c3)-95.9) > 0.1 { if math.Abs(float64(c1)-13.5) > 0.1 || math.Abs(float64(c2)-29.9) > 0.1 || math.Abs(float64(c3)-95.9) > 0.1 {
t.Errorf( t.Errorf(
"Expected near 13.5, 29.9, 95.9, got %v, %v, %v.", "Expected near 13.5, 29.9, 95.9, got %v, %v, %v.",