mirror of
https://github.com/esimov/forensic.git
synced 2025-09-26 12:31:14 +08:00
125 lines
2.9 KiB
Go
125 lines
2.9 KiB
Go
package main
|
|
|
|
import (
|
|
"math"
|
|
"image"
|
|
"image/color"
|
|
)
|
|
|
|
// round rounds float number to it's nearest integer part.
|
|
func round(x float64) float64 {
|
|
t := math.Trunc(x)
|
|
if math.Abs(x-t) >= 0.5 {
|
|
return t + math.Copysign(1, x)
|
|
}
|
|
return t
|
|
}
|
|
|
|
// clamp255 converts a float64 number to uint8.
|
|
func clamp255(x float64) uint8 {
|
|
if x < 0 {
|
|
return 0
|
|
}
|
|
if x > 255 {
|
|
return 255
|
|
}
|
|
return uint8(x)
|
|
}
|
|
|
|
// max returns the biggest value between two numbers.
|
|
func max(x, y int) float64 {
|
|
if x > y {
|
|
return float64(x)
|
|
}
|
|
return float64(y)
|
|
}
|
|
|
|
// unique returns slice's unique values.
|
|
func unique(intSlice []int) []int {
|
|
keys := make(map[int]bool)
|
|
list := []int{}
|
|
for _, entry := range intSlice {
|
|
if _, value := keys[entry]; !value {
|
|
keys[entry] = true
|
|
list = append(list, entry)
|
|
}
|
|
}
|
|
return list
|
|
}
|
|
|
|
// RGBtoYUV converts RGB to YUV color space.
|
|
func RGBtoYUV(r, g, b uint32) (uint32, uint32, uint32) {
|
|
y := 0.299*float64(r) + 0.587*float64(g) + 0.114*float64(b)
|
|
u := (((float64(b) - float64(y)) * 0.493) + 111) / 222 * 255
|
|
v := (((float64(r) - float64(y)) * 0.877) + 155) / 312 * 255
|
|
|
|
return uint32(y), uint32(u), uint32(v)
|
|
}
|
|
|
|
// YUVtoRGB converts YUV to RGB color space.
|
|
func YUVtoRGB(y, u, v uint32) (uint32, uint32, uint32) {
|
|
r := float64(y) + (1.13983 * float64(v))
|
|
g := float64(y) - (0.39465 * float64(u)) - (0.58060 * float64(v))
|
|
b := float64(y) + (2.03211 * float64(u))
|
|
|
|
return uint32(r), uint32(g), uint32(b)
|
|
}
|
|
|
|
// Converts any image type to *image.NRGBA with min-point at (0, 0).
|
|
func imgToNRGBA(img image.Image) *image.NRGBA {
|
|
srcBounds := img.Bounds()
|
|
if srcBounds.Min.X == 0 && srcBounds.Min.Y == 0 {
|
|
if src0, ok := img.(*image.NRGBA); ok {
|
|
return src0
|
|
}
|
|
}
|
|
srcMinX := srcBounds.Min.X
|
|
srcMinY := srcBounds.Min.Y
|
|
|
|
dstBounds := srcBounds.Sub(srcBounds.Min)
|
|
dstW := dstBounds.Dx()
|
|
dstH := dstBounds.Dy()
|
|
dst := image.NewNRGBA(dstBounds)
|
|
|
|
switch src := img.(type) {
|
|
case *image.NRGBA:
|
|
rowSize := srcBounds.Dx() * 4
|
|
for dstY := 0; dstY < dstH; dstY++ {
|
|
di := dst.PixOffset(0, dstY)
|
|
si := src.PixOffset(srcMinX, srcMinY+dstY)
|
|
for dstX := 0; dstX < dstW; dstX++ {
|
|
copy(dst.Pix[di:di+rowSize], src.Pix[si:si+rowSize])
|
|
}
|
|
}
|
|
case *image.YCbCr:
|
|
for dstY := 0; dstY < dstH; dstY++ {
|
|
di := dst.PixOffset(0, dstY)
|
|
for dstX := 0; dstX < dstW; dstX++ {
|
|
srcX := srcMinX + dstX
|
|
srcY := srcMinY + dstY
|
|
siy := src.YOffset(srcX, srcY)
|
|
sic := src.COffset(srcX, srcY)
|
|
r, g, b := color.YCbCrToRGB(src.Y[siy], src.Cb[sic], src.Cr[sic])
|
|
dst.Pix[di+0] = r
|
|
dst.Pix[di+1] = g
|
|
dst.Pix[di+2] = b
|
|
dst.Pix[di+3] = 0xff
|
|
di += 4
|
|
}
|
|
}
|
|
default:
|
|
for dstY := 0; dstY < dstH; dstY++ {
|
|
di := dst.PixOffset(0, dstY)
|
|
for dstX := 0; dstX < dstW; dstX++ {
|
|
c := color.NRGBAModel.Convert(img.At(srcMinX+dstX, srcMinY+dstY)).(color.NRGBA)
|
|
dst.Pix[di+0] = c.R
|
|
dst.Pix[di+1] = c.G
|
|
dst.Pix[di+2] = c.B
|
|
dst.Pix[di+3] = c.A
|
|
di += 4
|
|
}
|
|
}
|
|
}
|
|
return dst
|
|
}
|