// 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" "image/color" ) var FastYCBCR = true 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) } // Rgb2Gray function converts RGB to a gray scale array. func Rgb2Gray(colorImg image.Image, pixels []uint8) []uint8 { colorImg.Bounds().Dx() bounds := colorImg.Bounds() w, h := bounds.Dx(), bounds.Dy() 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) } } 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() } // 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)) } } return pixels }