@ -16,6 +16,15 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder
internal ref struct YCbCrForwardConverter420 < TPixel >
where TPixel : unmanaged , IPixel < TPixel >
{
// TODO: docs
private const int PixelsPerSample = 1 6 * 8 ;
// TODO: docs
private static int RgbSpanByteSize = PixelsPerSample * 3 ;
// TODO: docs
private static readonly Size SampleSize = new Size ( 1 6 , 8 ) ;
/// <summary>
/// The left Y component
/// </summary>
@ -51,35 +60,45 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder
/// </summary>
private Span < Rgb24 > rgbSpan ;
public static YCbCrForwardConverter420 < TPixel > Create ( )
// TODO: docs
private Size samplingAreaSize ;
// TODO: docs
private Configuration config ;
public YCbCrForwardConverter420 ( ImageFrame < TPixel > frame )
{
var result = default ( YCbCrForwardConverter420 < TPixel > ) ;
// matrices would be filled during convert calls
this . YLeft = default ;
this . YRight = default ;
this . Cb = default ;
this . Cr = default ;
// TODO: this is subject to discuss
const int twoBlocksByteSizeWithPadding = 3 8 4 + 8 ; // converter.Convert comments for +8 padding
result . rgbSpan = MemoryMarshal . Cast < byte , Rgb24 > ( new byte [ twoBlocksByteSizeWithPadding ] . AsSpan ( ) ) ;
// temporal pixel buffer s
this . pixelSpan = new TPixel [ PixelsPerSample ] . AsSpan ( ) ;
this . rgbSpan = MemoryMarshal . Cast < byte , Rgb24 > ( new byte [ RgbSpanByteSize + RgbToYCbCrConverterVectorized . AvxRegisterRgbCompatibility Padding] . AsSpan ( ) ) ;
// TODO: this size should be configurable
result . pixelSpan = new TPixel [ 1 2 8 ] . AsSpan ( ) ;
// frame data
this . samplingAreaSize = new Size ( frame . Width , frame . Height ) ;
this . config = frame . GetConfiguration ( ) ;
// Avoid creating lookup tables, when vectorized converter is supported
// conversion vector fallback data
if ( ! RgbToYCbCrConverterVectorized . IsSupported )
{
result . colorTables = RgbToYCbCrConverterLut . Create ( ) ;
this . colorTables = RgbToYCbCrConverterLut . Create ( ) ;
}
else
{
this . colorTables = default ;
}
return result ;
}
/// <summary>
/// Converts a 8x8 image area inside 'pixels' at position (x,y) placing the result members of the structure (<see cref="Y"/>, <see cref="Cb"/>, <see cref="Cr"/>)
/// </summary>
public void Convert ( ImageFrame < TPixel > frame , int x , int y , ref RowOctet < TPixel > currentRows , int idx )
public void Convert ( int x , int y , ref RowOctet < TPixel > currentRows , int idx )
{
Memory . Buffer2D < TPixel > buffer = frame . PixelBuffer ;
YCbCrForwardConverter < TPixel > . LoadAndStretchEdges ( currentRows , this . pixelSpan , new Point ( x , y ) , new Size ( 1 6 , 8 ) , new Size ( buffer . Width , buffer . Height ) ) ;
YCbCrForwardConverter < TPixel > . LoadAndStretchEdges ( currentRows , this . pixelSpan , new Point ( x , y ) , SampleSize , this . samplingAreaSize ) ;
PixelOperations < TPixel > . Instance . ToRgb24 ( frame . GetConfiguration ( ) , this . pixelSpan , this . rgbSpan ) ;
PixelOperations < TPixel > . Instance . ToRgb24 ( this . config , this . pixelSpan , this . rgbSpan ) ;
if ( RgbToYCbCrConverterVectorized . IsSupported )
{