@@ -24,15 +24,21 @@ public class QoiEncoderCore : IImageEncoderInternals
2424 /// </summary>
2525 private readonly MemoryAllocator memoryAllocator ;
2626
27+ /// <summary>
28+ /// The configuration instance for the encoding operation.
29+ /// </summary>
30+ private readonly Configuration configuration ;
31+
2732 /// <summary>
2833 /// Initializes a new instance of the <see cref="QoiEncoderCore"/> class.
2934 /// </summary>
3035 /// <param name="encoder">The encoder with options.</param>
3136 /// <param name="memoryAllocator">The <see cref="MemoryAllocator" /> to use for buffer allocations.</param>
32- public QoiEncoderCore ( QoiEncoder encoder , MemoryAllocator memoryAllocator )
37+ public QoiEncoderCore ( QoiEncoder encoder , MemoryAllocator memoryAllocator , Configuration configuration )
3338 {
3439 this . encoder = encoder ;
3540 this . memoryAllocator = memoryAllocator ;
41+ this . configuration = configuration ;
3642 }
3743
3844 /// <inheritdoc />
@@ -75,15 +81,17 @@ private void WritePixels<TPixel>(Image<TPixel> image, Stream stream)
7581 Rgba32 previousPixel = new ( 0 , 0 , 0 , 255 ) ;
7682 Rgba32 currentRgba32 = default ;
7783 Buffer2D < TPixel > pixels = image . Frames [ 0 ] . PixelBuffer ;
84+ using IMemoryOwner < Rgba32 > rgbaRowBuffer = this . memoryAllocator . Allocate < Rgba32 > ( pixels . Width ) ;
85+ Span < Rgba32 > rgbaRow = rgbaRowBuffer . GetSpan ( ) ;
7886
7987 for ( int i = 0 ; i < pixels . Height ; i ++ )
8088 {
8189 Span < TPixel > row = pixels . DangerousGetRowSpan ( i ) ;
90+ PixelOperations < TPixel > . Instance . ToRgba32 ( this . configuration , row , rgbaRow ) ;
8291 for ( int j = 0 ; j < row . Length && i < pixels . Height ; j ++ )
8392 {
8493 // We get the RGBA value from pixels
85- TPixel currentPixel = row [ j ] ;
86- currentPixel . ToRgba32 ( ref currentRgba32 ) ;
94+ currentRgba32 = rgbaRow [ j ] ;
8795
8896 // First, we check if the current pixel is equal to the previous one
8997 // If so, we do a QOI_OP_RUN
@@ -97,7 +105,7 @@ private void WritePixels<TPixel>(Image<TPixel> image, Stream stream)
97105 * and we should discuss what to do about this approach and
98106 * if it's correct
99107 */
100- byte repetitions = 0 ;
108+ int repetitions = 0 ;
101109 do
102110 {
103111 repetitions ++ ;
@@ -112,15 +120,15 @@ private void WritePixels<TPixel>(Image<TPixel> image, Stream stream)
112120 }
113121
114122 row = pixels . DangerousGetRowSpan ( i ) ;
123+ PixelOperations < TPixel > . Instance . ToRgba32 ( this . configuration , row , rgbaRow ) ;
115124 }
116125
117- currentPixel = row [ j ] ;
118- currentPixel . ToRgba32 ( ref currentRgba32 ) ;
126+ currentRgba32 = rgbaRow [ j ] ;
119127 }
120128 while ( currentRgba32 . Equals ( previousPixel ) && repetitions < 62 ) ;
121129
122130 j -- ;
123- stream . WriteByte ( ( byte ) ( ( byte ) QoiChunk . QoiOpRun | ( repetitions - 1 ) ) ) ;
131+ stream . WriteByte ( ( byte ) ( ( int ) QoiChunk . QoiOpRun | ( repetitions - 1 ) ) ) ;
124132
125133 /* If it's a QOI_OP_RUN, we don't overwrite the previous pixel since
126134 * it will be taken and compared on the next iteration
@@ -131,7 +139,7 @@ private void WritePixels<TPixel>(Image<TPixel> image, Stream stream)
131139 // else, we check if it exists in the previously seen pixels
132140 // If so, we do a QOI_OP_INDEX
133141 int pixelArrayPosition = GetArrayPosition ( currentRgba32 ) ;
134- if ( previouslySeenPixels [ pixelArrayPosition ] . Equals ( currentPixel ) )
142+ if ( previouslySeenPixels [ pixelArrayPosition ] . Equals ( currentRgba32 ) )
135143 {
136144 stream . WriteByte ( ( byte ) pixelArrayPosition ) ;
137145 }
@@ -141,9 +149,9 @@ private void WritePixels<TPixel>(Image<TPixel> image, Stream stream)
141149 // Since it wasn't found on the previously seen pixels, we save it
142150 previouslySeenPixels [ pixelArrayPosition ] = currentRgba32 ;
143151
144- sbyte diffRed = ( sbyte ) ( currentRgba32 . R - previousPixel . R ) ;
145- sbyte diffGreen = ( sbyte ) ( currentRgba32 . G - previousPixel . G ) ;
146- sbyte diffBlue = ( sbyte ) ( currentRgba32 . B - previousPixel . B ) ;
152+ int diffRed = currentRgba32 . R - previousPixel . R ;
153+ int diffGreen = currentRgba32 . G - previousPixel . G ;
154+ int diffBlue = currentRgba32 . B - previousPixel . B ;
147155
148156 // If so, we do a QOI_OP_DIFF
149157 if ( diffRed is >= - 2 and <= 1 &&
@@ -152,26 +160,26 @@ private void WritePixels<TPixel>(Image<TPixel> image, Stream stream)
152160 currentRgba32 . A == previousPixel . A )
153161 {
154162 // Bottom limit is -2, so we add 2 to make it equal to 0
155- byte dr = ( byte ) ( diffRed + 2 ) ;
156- byte dg = ( byte ) ( diffGreen + 2 ) ;
157- byte db = ( byte ) ( diffBlue + 2 ) ;
158- byte valueToWrite = ( byte ) ( ( byte ) QoiChunk . QoiOpDiff | ( dr << 4 ) | ( dg << 2 ) | db ) ;
163+ int dr = diffRed + 2 ;
164+ int dg = diffGreen + 2 ;
165+ int db = diffBlue + 2 ;
166+ byte valueToWrite = ( byte ) ( ( int ) QoiChunk . QoiOpDiff | ( dr << 4 ) | ( dg << 2 ) | db ) ;
159167 stream . WriteByte ( valueToWrite ) ;
160168 }
161169 else
162170 {
163171 // else, we check if the green difference is less than -32..31 and the rest -8..7
164172 // If so, we do a QOI_OP_LUMA
165- sbyte diffRedGreen = ( sbyte ) ( diffRed - diffGreen ) ;
166- sbyte diffBlueGreen = ( sbyte ) ( diffBlue - diffGreen ) ;
173+ int diffRedGreen = diffRed - diffGreen ;
174+ int diffBlueGreen = diffBlue - diffGreen ;
167175 if ( diffGreen is >= - 32 and <= 31 &&
168176 diffRedGreen is >= - 8 and <= 7 &&
169177 diffBlueGreen is >= - 8 and <= 7 &&
170178 currentRgba32 . A == previousPixel . A )
171179 {
172- byte dr_dg = ( byte ) ( diffRedGreen + 8 ) ;
173- byte db_dg = ( byte ) ( diffBlueGreen + 8 ) ;
174- byte byteToWrite1 = ( byte ) ( ( byte ) QoiChunk . QoiOpLuma | ( diffGreen + 32 ) ) ;
180+ int dr_dg = diffRedGreen + 8 ;
181+ int db_dg = diffBlueGreen + 8 ;
182+ byte byteToWrite1 = ( byte ) ( ( int ) QoiChunk . QoiOpLuma | ( diffGreen + 32 ) ) ;
175183 byte byteToWrite2 = ( byte ) ( ( dr_dg << 4 ) | db_dg ) ;
176184 stream . WriteByte ( byteToWrite1 ) ;
177185 stream . WriteByte ( byteToWrite2 ) ;
0 commit comments