public YCbCrForwardConverter420(ImageFrame <TPixel> frame) { // matrices would be filled during convert calls this.YLeft = default; this.YRight = default; this.Cb = default; this.Cr = default; // temporal pixel buffers this.pixelSpan = new TPixel[PixelsPerSample].AsSpan(); this.rgbSpan = MemoryMarshal.Cast <byte, Rgb24>(new byte[RgbSpanByteSize + RgbToYCbCrConverterVectorized.AvxCompatibilityPadding].AsSpan()); // frame data this.samplingAreaSize = new Size(frame.Width, frame.Height); this.config = frame.GetConfiguration(); // conversion vector fallback data if (!RgbToYCbCrConverterVectorized.IsSupported) { this.colorTables = RgbToYCbCrConverterLut.Create(); } else { this.colorTables = default; } }
/// <summary> /// Initializes the YCbCr tables /// </summary> /// <returns>The initialized <see cref="RgbToYCbCrConverterLut"/></returns> public static RgbToYCbCrConverterLut Create() { RgbToYCbCrConverterLut tables = default; for (int i = 0; i <= 255; i++) { // The values for the calculations are left scaled up since we must add them together before rounding. tables.YRTable[i] = Fix(0.299F) * i; tables.YGTable[i] = Fix(0.587F) * i; tables.YBTable[i] = (Fix(0.114F) * i) + Half; tables.CbRTable[i] = (-Fix(0.168735892F)) * i; tables.CbGTable[i] = (-Fix(0.331264108F)) * i; // We use a rounding fudge - factor of 0.5 - epsilon for Cb and Cr. // This ensures that the maximum output will round to 255 // not 256, and thus that we don't have to range-limit. // // B=>Cb and R=>Cr tables are the same tables.CbBTable[i] = (Fix(0.5F) * i) + CBCrOffset + Half - 1; tables.CrGTable[i] = (-Fix(0.418687589F)) * i; tables.CrBTable[i] = (-Fix(0.081312411F)) * i; } return(tables); }
public static YCbCrForwardConverter <TPixel> Create() { var result = default(YCbCrForwardConverter <TPixel>); if (!RgbToYCbCrConverterVectorized.IsSupported) { // Avoid creating lookup tables, when vectorized converter is supported result.colorTables = RgbToYCbCrConverterLut.Create(); } return(result); }