diff --git a/colorspace/colorspace.go b/colorformat/colorspace.go similarity index 64% rename from colorspace/colorspace.go rename to colorformat/colorspace.go index 7d28a65..edf134b 100644 --- a/colorspace/colorspace.go +++ b/colorformat/colorspace.go @@ -1,4 +1,4 @@ -package colorspace +package colorformat import ( "encoding/binary" @@ -18,42 +18,42 @@ type SubsamplingScheme struct { B byte } -type ColorSpace struct { +type ColorFormat struct { Subsampling SubsamplingScheme BitDepth byte } -func (c ColorSpace) ToInteger() uint32 { +func (c ColorFormat) ToInteger() uint32 { return binary.BigEndian.Uint32([]byte{c.Subsampling.J, c.Subsampling.A, c.Subsampling.B, c.BitDepth}) } // ElementPixels returns the number of pixels for a full element -func (c ColorSpace) ElementPixels() int { +func (c ColorFormat) ElementPixels() int { return int(c.Subsampling.J) * 2 } // ElementSamples returns the number of actual samples (total Y, Cb, Cr) for an encoded element -func (c ColorSpace) ElementSamples() int { +func (c ColorFormat) ElementSamples() int { return int(c.Subsampling.J)*2 + c.ElementChromaSamples() } -func (c ColorSpace) ElementChromaSamples() int { +func (c ColorFormat) ElementChromaSamples() int { return int(c.Subsampling.A)*2 + int(c.Subsampling.B)*2 } -func (c ColorSpace) PlaneLumaSamples(width, height int) int { +func (c ColorFormat) PlaneLumaSamples(width, height int) int { return width * height } -func (c ColorSpace) PlaneCrSamples(width, height int) int { +func (c ColorFormat) PlaneCrSamples(width, height int) int { return int((int64(width) * int64(height) * (int64(c.Subsampling.A) + int64(c.Subsampling.B))) / int64(c.ElementPixels())) } -func (c ColorSpace) PlaneCbSamples(width, height int) int { +func (c ColorFormat) PlaneCbSamples(width, height int) int { return int((int64(width) * int64(height) * (int64(c.Subsampling.A) + int64(c.Subsampling.B))) / int64(c.ElementPixels())) } -func (c ColorSpace) FrameSizePacked(width, height int) (int, error) { +func (c ColorFormat) FrameSizePacked(width, height int) (int, error) { a1 := int64(width) * int64(height) a2 := int64(c.ElementPixels()) if a1%a2 != 0 { @@ -67,7 +67,7 @@ func (c ColorSpace) FrameSizePacked(width, height int) (int, error) { return int(a3 / 8), nil } -func (c ColorSpace) FrameSize(width, height int) (int, error) { +func (c ColorFormat) FrameSize(width, height int) (int, error) { actualBitDepth := int64(c.BitDepth) if actualBitDepth&0b111 != 0 { actualBitDepth = ((actualBitDepth + 8) >> 3) << 3 @@ -86,7 +86,7 @@ func (c ColorSpace) FrameSize(width, height int) (int, error) { return int(a3 / 8), nil } -func (c ColorSpace) check() error { +func (c ColorFormat) check() error { if c.Subsampling.J <= 0 { return fmt.Errorf("unsupported J %d", c.Subsampling.J) } @@ -103,11 +103,11 @@ func (c ColorSpace) check() error { return nil } -func NewColorSpaceFromInteger(colorSpace uint32) (ColorSpace, error) { +func NewColorFormatFromInteger(colorFormat uint32) (ColorFormat, error) { buf := make([]byte, 4) - binary.BigEndian.PutUint32(buf, colorSpace) + binary.BigEndian.PutUint32(buf, colorFormat) - space := ColorSpace{ + space := ColorFormat{ Subsampling: SubsamplingScheme{ J: buf[0], A: buf[1], @@ -119,17 +119,17 @@ func NewColorSpaceFromInteger(colorSpace uint32) (ColorSpace, error) { return space, space.check() } -func NewColorSpaceFromString(colorSpace string) (ColorSpace, error) { - colorSpace = strings.ToLower(colorSpace) - if colorSpace == "420mpeg2" { - return NewColorSpaceFromString("420p8") +func NewColorFormatFromString(colorFormat string) (ColorFormat, error) { + colorFormat = strings.ToLower(colorFormat) + if colorFormat == "420mpeg2" { + return NewColorFormatFromString("420p8") } - splits := strings.Split(colorSpace, "p") + splits := strings.Split(colorFormat, "p") if len(splits) == 1 { //default 8 bit splits = append(splits, "8") } - space := ColorSpace{} + space := ColorFormat{} switch strings.ReplaceAll(splits[0], ":", "") { case "420": space.Subsampling.J = 4 @@ -156,22 +156,22 @@ func NewColorSpaceFromString(colorSpace string) (ColorSpace, error) { return space, space.check() } -func newColorSpaceFromStringInternal(colorSpace string) ColorSpace { - space, _ := NewColorSpaceFromString(colorSpace) +func newColorFormatFromStringInternal(colorFormat string) ColorFormat { + space, _ := NewColorFormatFromString(colorFormat) return space } var ( - Space420 ColorSpace = newColorSpaceFromStringInternal("420") - Space422 ColorSpace = newColorSpaceFromStringInternal("422") - Space444 ColorSpace = newColorSpaceFromStringInternal("444") - Space420P10 ColorSpace = newColorSpaceFromStringInternal("420p10") - Space422P10 ColorSpace = newColorSpaceFromStringInternal("422p10") - Space444P10 ColorSpace = newColorSpaceFromStringInternal("444p10") - Space420P12 ColorSpace = newColorSpaceFromStringInternal("420p12") - Space422P12 ColorSpace = newColorSpaceFromStringInternal("422p12") - Space444P12 ColorSpace = newColorSpaceFromStringInternal("444p12") - Space420P16 ColorSpace = newColorSpaceFromStringInternal("420p16") - Space422P16 ColorSpace = newColorSpaceFromStringInternal("422p16") - Space444P16 ColorSpace = newColorSpaceFromStringInternal("444p16") + Space420 ColorFormat = newColorFormatFromStringInternal("420") + Space422 ColorFormat = newColorFormatFromStringInternal("422") + Space444 ColorFormat = newColorFormatFromStringInternal("444") + Space420P10 ColorFormat = newColorFormatFromStringInternal("420p10") + Space422P10 ColorFormat = newColorFormatFromStringInternal("422p10") + Space444P10 ColorFormat = newColorFormatFromStringInternal("444p10") + Space420P12 ColorFormat = newColorFormatFromStringInternal("420p12") + Space422P12 ColorFormat = newColorFormatFromStringInternal("422p12") + Space444P12 ColorFormat = newColorFormatFromStringInternal("444p12") + Space420P16 ColorFormat = newColorFormatFromStringInternal("420p16") + Space422P16 ColorFormat = newColorFormatFromStringInternal("422p16") + Space444P16 ColorFormat = newColorFormatFromStringInternal("444p16") ) diff --git a/encoder/libaom/libaom.go b/encoder/libaom/libaom.go index 47e4d9b..20dbd5d 100644 --- a/encoder/libaom/libaom.go +++ b/encoder/libaom/libaom.go @@ -55,13 +55,13 @@ func NewEncoder(w io.Writer, stream *y4m.Stream, settings map[string]any) (*Enco } switch true { - case stream.ColorSpace().Subsampling.J == 4 && stream.ColorSpace().Subsampling.A == 4 && stream.ColorSpace().Subsampling.B == 4: + case stream.ColorFormat().Subsampling.J == 4 && stream.ColorFormat().Subsampling.A == 4 && stream.ColorFormat().Subsampling.B == 4: imageFormat = C.AOM_IMG_FMT_I444 e.cfg.g_profile = 1 - case stream.ColorSpace().Subsampling.J == 4 && stream.ColorSpace().Subsampling.A == 2 && stream.ColorSpace().Subsampling.B == 2: + case stream.ColorFormat().Subsampling.J == 4 && stream.ColorFormat().Subsampling.A == 2 && stream.ColorFormat().Subsampling.B == 2: imageFormat = C.AOM_IMG_FMT_I422 e.cfg.g_profile = 2 - case stream.ColorSpace().Subsampling.J == 4 && stream.ColorSpace().Subsampling.A == 2 && stream.ColorSpace().Subsampling.B == 0: + case stream.ColorFormat().Subsampling.J == 4 && stream.ColorFormat().Subsampling.A == 2 && stream.ColorFormat().Subsampling.B == 0: imageFormat = C.AOM_IMG_FMT_I420 e.cfg.g_profile = 0 default: @@ -69,12 +69,12 @@ func NewEncoder(w io.Writer, stream *y4m.Stream, settings map[string]any) (*Enco } - if stream.ColorSpace().BitDepth > 8 { + if stream.ColorFormat().BitDepth > 8 { imageFormat |= C.AOM_IMG_FMT_HIGHBITDEPTH } - e.cfg.g_input_bit_depth = C.uint(stream.ColorSpace().BitDepth) - e.cfg.g_bit_depth = C.aom_bit_depth_t(stream.ColorSpace().BitDepth) + e.cfg.g_input_bit_depth = C.uint(stream.ColorFormat().BitDepth) + e.cfg.g_bit_depth = C.aom_bit_depth_t(stream.ColorFormat().BitDepth) if e.cfg.g_bit_depth >= 12 { e.cfg.g_bit_depth = 12 diff --git a/encoder/x264/x264.go b/encoder/x264/x264.go index a76d9c8..b71e92f 100644 --- a/encoder/x264/x264.go +++ b/encoder/x264/x264.go @@ -55,13 +55,13 @@ func NewEncoder(w io.Writer, stream *y4m.Stream, settings map[string]any) (*Enco defaultProfile := "high" switch true { - case stream.ColorSpace().Subsampling.J == 4 && stream.ColorSpace().Subsampling.A == 4 && stream.ColorSpace().Subsampling.B == 4: + case stream.ColorFormat().Subsampling.J == 4 && stream.ColorFormat().Subsampling.A == 4 && stream.ColorFormat().Subsampling.B == 4: e.params.i_csp = C.X264_CSP_I444 defaultProfile = "high444" - case stream.ColorSpace().Subsampling.J == 4 && stream.ColorSpace().Subsampling.A == 2 && stream.ColorSpace().Subsampling.B == 2: + case stream.ColorFormat().Subsampling.J == 4 && stream.ColorFormat().Subsampling.A == 2 && stream.ColorFormat().Subsampling.B == 2: e.params.i_csp = C.X264_CSP_I422 defaultProfile = "high422" - case stream.ColorSpace().Subsampling.J == 4 && stream.ColorSpace().Subsampling.A == 2 && stream.ColorSpace().Subsampling.B == 0: + case stream.ColorFormat().Subsampling.J == 4 && stream.ColorFormat().Subsampling.A == 2 && stream.ColorFormat().Subsampling.B == 0: e.params.i_csp = C.X264_CSP_I420 defaultProfile = "high" default: @@ -72,13 +72,13 @@ func NewEncoder(w io.Writer, stream *y4m.Stream, settings map[string]any) (*Enco profile := C.CString(getSettingString(settings, "profile", defaultProfile)) defer C.free(unsafe.Pointer(profile)) - if stream.ColorSpace().BitDepth > 8 { + if stream.ColorFormat().BitDepth > 8 { e.params.i_csp |= C.X264_CSP_HIGH_DEPTH if defaultProfile == "high" { defaultProfile = "high10" } } - e.params.i_bitdepth = C.int(stream.ColorSpace().BitDepth) + e.params.i_bitdepth = C.int(stream.ColorFormat().BitDepth) width, height := stream.Resolution() e.params.i_width = C.int(width) diff --git a/frame/frame.go b/frame/frame.go index 4fdef8d..fcdfaf0 100644 --- a/frame/frame.go +++ b/frame/frame.go @@ -1,6 +1,8 @@ package frame -import "git.gammaspectra.live/S.O.N.G/Ignite/colorspace" +import ( + "git.gammaspectra.live/S.O.N.G/Ignite/colorformat" +) type AllowedFrameTypes interface { uint8 | uint16 @@ -9,7 +11,7 @@ type AllowedFrameTypes interface { type Frame interface { Width() int Height() int - ColorSpace() colorspace.ColorSpace + ColorFormat() colorformat.ColorFormat Get16(x, y int) (Y uint16, Cb uint16, Cr uint16) Get8(x, y int) (Y uint8, Cb uint8, Cr uint8) } diff --git a/frame/frame_uint16.go b/frame/frame_uint16.go index d780f8c..9791d39 100644 --- a/frame/frame_uint16.go +++ b/frame/frame_uint16.go @@ -2,21 +2,21 @@ package frame import ( "errors" - "git.gammaspectra.live/S.O.N.G/Ignite/colorspace" + "git.gammaspectra.live/S.O.N.G/Ignite/colorformat" "runtime" "unsafe" ) type uint16Frame struct { - colorSpace colorspace.ColorSpace - width int - height int - Y []uint16 - Cb []uint16 - Cr []uint16 + colorFormat colorformat.ColorFormat + width int + height int + Y []uint16 + Cb []uint16 + Cr []uint16 } -func NewUint16FrameFromBytes(space colorspace.ColorSpace, width, height int, data []byte) (*uint16Frame, error) { +func NewUint16FrameFromBytes(space colorformat.ColorFormat, width, height int, data []byte) (*uint16Frame, error) { if frameLength, _ := space.FrameSize(width, height); frameLength != len(data) { return nil, errors.New("wrong length of data") } @@ -34,25 +34,25 @@ func NewUint16FrameFromBytes(space colorspace.ColorSpace, width, height int, dat iCr := space.PlaneCrSamples(width, height) return &uint16Frame{ - colorSpace: space, - height: height, - width: width, - Y: buf[:iY], - Cb: buf[iY : iY+iCb], - Cr: buf[iY+iCb : iY+iCb+iCr], + colorFormat: space, + height: height, + width: width, + Y: buf[:iY], + Cb: buf[iY : iY+iCb], + Cr: buf[iY+iCb : iY+iCb+iCr], }, nil } func (i *uint16Frame) Get16(x, y int) (Y uint16, Cb uint16, Cr uint16) { cy, cb, cr := i.GetNative(x, y) - return cy << (16 - i.colorSpace.BitDepth), cb << (16 - i.colorSpace.BitDepth), cr << (16 - i.colorSpace.BitDepth) + return cy << (16 - i.colorFormat.BitDepth), cb << (16 - i.colorFormat.BitDepth), cr << (16 - i.colorFormat.BitDepth) } func (i *uint16Frame) Get8(x, y int) (Y uint8, Cb uint8, Cr uint8) { cy, cb, cr := i.GetNative(x, y) - return uint8(cy >> (i.colorSpace.BitDepth - 8)), uint8(cb >> (i.colorSpace.BitDepth - 8)), uint8(cr >> (i.colorSpace.BitDepth - 8)) + return uint8(cy >> (i.colorFormat.BitDepth - 8)), uint8(cb >> (i.colorFormat.BitDepth - 8)), uint8(cr >> (i.colorFormat.BitDepth - 8)) } func (i *uint16Frame) Width() int { @@ -63,18 +63,18 @@ func (i *uint16Frame) Height() int { return i.height } -func (i *uint16Frame) ColorSpace() colorspace.ColorSpace { - return i.colorSpace +func (i *uint16Frame) ColorFormat() colorformat.ColorFormat { + return i.colorFormat } func (i *uint16Frame) GetNative(x, y int) (Y uint16, Cb uint16, Cr uint16) { Yindex := x + y*i.width - Cwidth := (i.width * int(i.colorSpace.Subsampling.A)) / int(i.colorSpace.Subsampling.J) - if i.colorSpace.Subsampling.B == 0 { + Cwidth := (i.width * int(i.colorFormat.Subsampling.A)) / int(i.colorFormat.Subsampling.J) + if i.colorFormat.Subsampling.B == 0 { y /= 2 } - Cindex := (x*int(i.colorSpace.Subsampling.A))/int(i.colorSpace.Subsampling.J) + y*Cwidth + Cindex := (x*int(i.colorFormat.Subsampling.A))/int(i.colorFormat.Subsampling.J) + y*Cwidth Y = i.Y[Yindex] Cb = i.Cb[Cindex] Cr = i.Cr[Cindex] diff --git a/frame/frame_uint8.go b/frame/frame_uint8.go index 0eca4a2..2d5b8ee 100644 --- a/frame/frame_uint8.go +++ b/frame/frame_uint8.go @@ -2,19 +2,19 @@ package frame import ( "errors" - "git.gammaspectra.live/S.O.N.G/Ignite/colorspace" + "git.gammaspectra.live/S.O.N.G/Ignite/colorformat" ) type uint8Frame struct { - colorSpace colorspace.ColorSpace - width int - height int - Y []uint8 - Cb []uint8 - Cr []uint8 + colorFormat colorformat.ColorFormat + width int + height int + Y []uint8 + Cb []uint8 + Cr []uint8 } -func NewUint8FrameFromBytes(space colorspace.ColorSpace, width, height int, data []byte) (*uint8Frame, error) { +func NewUint8FrameFromBytes(space colorformat.ColorFormat, width, height int, data []byte) (*uint8Frame, error) { if frameLength, _ := space.FrameSize(width, height); frameLength != len(data) { return nil, errors.New("wrong length of data") } @@ -28,19 +28,19 @@ func NewUint8FrameFromBytes(space colorspace.ColorSpace, width, height int, data iCr := space.PlaneCrSamples(width, height) return &uint8Frame{ - colorSpace: space, - height: height, - width: width, - Y: data[:iY], - Cb: data[iY : iY+iCb], - Cr: data[iY+iCb : iY+iCb+iCr], + colorFormat: space, + height: height, + width: width, + Y: data[:iY], + Cb: data[iY : iY+iCb], + Cr: data[iY+iCb : iY+iCb+iCr], }, nil } func (i *uint8Frame) Get16(x, y int) (Y uint16, Cb uint16, Cr uint16) { cy, cb, cr := i.GetNative(x, y) - return uint16(cy) << (16 - i.colorSpace.BitDepth), uint16(cb) << (16 - i.colorSpace.BitDepth), uint16(cr) << (16 - i.colorSpace.BitDepth) + return uint16(cy) << (16 - i.colorFormat.BitDepth), uint16(cb) << (16 - i.colorFormat.BitDepth), uint16(cr) << (16 - i.colorFormat.BitDepth) } func (i *uint8Frame) Get8(x, y int) (Y uint8, Cb uint8, Cr uint8) { @@ -55,18 +55,18 @@ func (i *uint8Frame) Height() int { return i.height } -func (i *uint8Frame) ColorSpace() colorspace.ColorSpace { - return i.colorSpace +func (i *uint8Frame) ColorFormat() colorformat.ColorFormat { + return i.colorFormat } func (i *uint8Frame) GetNative(x, y int) (Y uint8, Cb uint8, Cr uint8) { Yindex := x + y*i.width - Cwidth := (i.width * int(i.colorSpace.Subsampling.A)) / int(i.colorSpace.Subsampling.J) - if i.colorSpace.Subsampling.B == 0 { + Cwidth := (i.width * int(i.colorFormat.Subsampling.A)) / int(i.colorFormat.Subsampling.J) + if i.colorFormat.Subsampling.B == 0 { y /= 2 } - Cindex := (x*int(i.colorSpace.Subsampling.A))/int(i.colorSpace.Subsampling.J) + y*Cwidth + Cindex := (x*int(i.colorFormat.Subsampling.A))/int(i.colorFormat.Subsampling.J) + y*Cwidth Y = i.Y[Yindex] Cb = i.Cb[Cindex] Cr = i.Cr[Cindex] diff --git a/y4m/y4m.go b/y4m/y4m.go index 2cef954..f61d648 100644 --- a/y4m/y4m.go +++ b/y4m/y4m.go @@ -3,7 +3,7 @@ package y4m import ( "errors" "fmt" - "git.gammaspectra.live/S.O.N.G/Ignite/colorspace" + "git.gammaspectra.live/S.O.N.G/Ignite/colorformat" "git.gammaspectra.live/S.O.N.G/Ignite/frame" "git.gammaspectra.live/S.O.N.G/Ignite/utilities" "io" @@ -20,7 +20,7 @@ type Stream struct { height int frameRate utilities.Ratio pixelAspectRatio utilities.Ratio - colorSpace colorspace.ColorSpace + colorFormat colorformat.ColorFormat colorRangeFull bool frameSize int @@ -36,7 +36,7 @@ const ( ParameterFrameRate Parameter = 'F' ParameterInterlacing Parameter = 'I' ParameterPixelAspectRatio Parameter = 'A' - ParameterColorSpace Parameter = 'C' + ParameterColorFormat Parameter = 'C' ParameterExtension Parameter = 'X' ) @@ -68,8 +68,8 @@ func (s *Stream) FrameRate() utilities.Ratio { return s.frameRate } -func (s *Stream) ColorSpace() colorspace.ColorSpace { - return s.colorSpace +func (s *Stream) ColorFormat() colorformat.ColorFormat { + return s.colorFormat } func (s *Stream) ColorRange() bool { @@ -125,12 +125,12 @@ func (s *Stream) GetFrame() (frameNumber int, parameters map[Parameter][]string, return 0, nil, nil, err } - if s.colorSpace.BitDepth > 8 { - if frameObject, err = frame.NewUint16FrameFromBytes(s.colorSpace, s.width, s.height, buf); err != nil { + if s.colorFormat.BitDepth > 8 { + if frameObject, err = frame.NewUint16FrameFromBytes(s.colorFormat, s.width, s.height, buf); err != nil { return 0, nil, nil, err } } else { - if frameObject, err = frame.NewUint8FrameFromBytes(s.colorSpace, s.width, s.height, buf); err != nil { + if frameObject, err = frame.NewUint8FrameFromBytes(s.colorFormat, s.width, s.height, buf); err != nil { return 0, nil, nil, err } } @@ -260,8 +260,8 @@ func (s *Stream) parseParameters() (err error) { if s.pixelAspectRatio.Denominator, err = strconv.Atoi(v[1]); err != nil { return err } - case ParameterColorSpace: - if s.colorSpace, err = colorspace.NewColorSpaceFromString(values[0]); err != nil { + case ParameterColorFormat: + if s.colorFormat, err = colorformat.NewColorFormatFromString(values[0]); err != nil { return err } case ParameterExtension: @@ -283,9 +283,9 @@ func (s *Stream) parseParameters() (err error) { } } - //TODO: check for missing values width, height, colorspace etc. + //TODO: check for missing values width, height, colorformat etc. - s.frameSize, err = s.colorSpace.FrameSize(s.width, s.height) + s.frameSize, err = s.colorFormat.FrameSize(s.width, s.height) return err }