2017-07-28 10:18:24 -07:00
|
|
|
// Copyright 2017 The goimagehash Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package transforms
|
|
|
|
|
|
|
|
import (
|
|
|
|
"image"
|
2024-04-05 16:29:03 -07:00
|
|
|
"image/color"
|
2017-07-28 10:18:24 -07:00
|
|
|
)
|
|
|
|
|
2024-08-04 17:21:58 -07:00
|
|
|
var FastYCBCR = true
|
|
|
|
|
2024-04-05 16:29:03 -07:00
|
|
|
func toGray(r, g, b uint8) uint8 {
|
|
|
|
// 19595 + 38470 + 7471 equals 65536.
|
|
|
|
return uint8((19595*uint32(r) + 38470*uint32(g) + 7471*uint32(b) + 1<<15) >> 16)
|
2017-07-28 10:18:24 -07:00
|
|
|
}
|
|
|
|
|
2024-04-05 16:29:03 -07:00
|
|
|
// Rgb2Gray function converts RGB to a gray scale array.
|
2024-08-04 17:21:58 -07:00
|
|
|
func Rgb2Gray(colorImg image.Image, pixels []uint8) []uint8 {
|
2024-04-05 16:29:03 -07:00
|
|
|
colorImg.Bounds().Dx()
|
2022-05-25 23:56:47 -07:00
|
|
|
bounds := colorImg.Bounds()
|
2024-04-05 16:29:03 -07:00
|
|
|
w, h := bounds.Dx(), bounds.Dy()
|
2024-08-04 17:21:58 -07:00
|
|
|
if pixels == nil {
|
|
|
|
pixels = make([]uint8, h*w)
|
|
|
|
}
|
|
|
|
switch img := colorImg.(type) {
|
|
|
|
case *image.YCbCr:
|
|
|
|
var R, G, B uint8
|
|
|
|
var yi, ci int
|
|
|
|
for i := 0; i < h*w; i++ {
|
|
|
|
x, y := i%w, i/w
|
|
|
|
yi = img.YOffset(x, y)
|
|
|
|
if FastYCBCR {
|
|
|
|
pixels[i] = img.Y[yi]
|
|
|
|
} else {
|
|
|
|
ci = img.COffset(x, y)
|
|
|
|
|
|
|
|
R, G, B = color.YCbCrToRGB(img.Y[yi], img.Cb[ci], img.Cr[ci])
|
|
|
|
|
|
|
|
// Pillow only operates on 8bit data, operating on higher bit data produces rounding differences
|
|
|
|
pixels[i] = toGray(R, G, B)
|
|
|
|
}
|
2022-05-25 23:56:47 -07:00
|
|
|
}
|
2024-08-04 17:21:58 -07:00
|
|
|
default:
|
|
|
|
var R, G, B uint32
|
|
|
|
for i := 0; i < h*w; i++ {
|
|
|
|
x, y := i%w, i/w
|
|
|
|
switch v := img.At(x, y).(type) {
|
|
|
|
case color.NRGBA: // pillow discards alpha during conversion and provides no way to pre-multiply it
|
|
|
|
R, G, B = uint32(v.R)<<8, uint32(v.G)<<8, uint32(v.B)<<8
|
|
|
|
default:
|
|
|
|
R, G, B, _ = v.RGBA()
|
|
|
|
}
|
2022-05-25 23:56:47 -07:00
|
|
|
|
2024-08-04 17:21:58 -07:00
|
|
|
// Pillow only operates on 8bit data, operating on higher bit data produces rounding differences
|
|
|
|
pixels[i] = toGray(uint8(R>>8), uint8(G>>8), uint8(B>>8))
|
|
|
|
}
|
2022-05-25 23:56:47 -07:00
|
|
|
}
|
|
|
|
|
2024-04-05 16:29:03 -07:00
|
|
|
return pixels
|
2022-05-25 23:56:47 -07:00
|
|
|
}
|