xyz2yuv/convert.go
2024-02-19 20:06:49 +01:00

81 lines
2.2 KiB
Go

package main
import (
"git.gammaspectra.live/WeebDataHoarder/xyz2yuv/colorspace"
"git.gammaspectra.live/WeebDataHoarder/xyz2yuv/conv"
"gonum.org/v1/gonum/mat"
)
var useCConverter, useFloat bool
func ConvertFrame(in []uint32, y, cb, cr []uint16, width, height int) {
if useCConverter {
if useFloat {
conv.ConvertFrameDCIXYZToYUV16Float(in, y, cb, cr, width, height)
} else {
conv.ConvertFrameDCIXYZToYUV16Double(in, y, cb, cr, width, height)
}
return
}
for i := 0; i < height; i++ {
ConvertLine(in, y, cb, cr, width, height)
in = in[width*3:]
y = y[width:]
cb = cb[width:]
cr = cr[width:]
}
}
func ConvertLine(in []uint32, y, cb, cr []uint16, width, height int) {
if useCConverter {
if useFloat {
conv.ConvertLineDCIXYZToYUV16Float(in, y, cb, cr, width, height)
} else {
conv.ConvertLineDCIXYZToYUV16Double(in, y, cb, cr, width, height)
}
return
}
var r, g, b float64
xyz, rgb, yuv := mat.NewVecDense(3, nil), mat.NewVecDense(3, nil), mat.NewVecDense(3, nil)
for j := 0; j < width; j++ {
// LUT
xyz.SetVec(0, colorspace.DCIXYZSystem.ToLinearLUT[uint16(in[j*3])<<4])
xyz.SetVec(1, colorspace.DCIXYZSystem.ToLinearLUT[uint16(in[j*3+1])<<4])
xyz.SetVec(2, colorspace.DCIXYZSystem.ToLinearLUT[uint16(in[j*3+2])<<4])
//TODO: apply white point correction here if necessary (but after denorm)
//denormalize + xyz2rgb
rgb.MulVec(xyz2rgbDenorm, xyz)
//todo: some out of bounds r,g,b come up from here, maybe just fine
//clamp values into proper values. necessary due to XYZ ranges, todo: check conversion matrix for preserving this
r = min(1.0, max(0, rgb.AtVec(0)))
g = min(1.0, max(0, rgb.AtVec(1)))
b = min(1.0, max(0, rgb.AtVec(2)))
// companding / adjustment with gamma curve
//TODO: why is it not using normal Rec709 and instead using straight gamma curve
r = space.FromLinear(r)
g = space.FromLinear(g)
b = space.FromLinear(b)
rgb.SetVec(0, r)
rgb.SetVec(1, g)
rgb.SetVec(2, b)
yuv.MulVec(rgb2yuv, rgb)
// map RGB to components
// scale float range to 16bit precision, in full swing
y[j] = LumaToFull16(yuv.AtVec(0))
cb[j] = ChromaToFull16(yuv.AtVec(1))
cr[j] = ChromaToFull16(yuv.AtVec(2))
}
}