@@ -24,15 +24,21 @@ public class QoiEncoderCore : IImageEncoderInternals
24
24
/// </summary>
25
25
private readonly MemoryAllocator memoryAllocator ;
26
26
27
+ /// <summary>
28
+ /// The configuration instance for the encoding operation.
29
+ /// </summary>
30
+ private readonly Configuration configuration ;
31
+
27
32
/// <summary>
28
33
/// Initializes a new instance of the <see cref="QoiEncoderCore"/> class.
29
34
/// </summary>
30
35
/// <param name="encoder">The encoder with options.</param>
31
36
/// <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 )
33
38
{
34
39
this . encoder = encoder ;
35
40
this . memoryAllocator = memoryAllocator ;
41
+ this . configuration = configuration ;
36
42
}
37
43
38
44
/// <inheritdoc />
@@ -75,15 +81,17 @@ private void WritePixels<TPixel>(Image<TPixel> image, Stream stream)
75
81
Rgba32 previousPixel = new ( 0 , 0 , 0 , 255 ) ;
76
82
Rgba32 currentRgba32 = default ;
77
83
Buffer2D < TPixel > pixels = image . Frames [ 0 ] . PixelBuffer ;
84
+ using IMemoryOwner < Rgba32 > rgbaRowBuffer = this . memoryAllocator . Allocate < Rgba32 > ( pixels . Width ) ;
85
+ Span < Rgba32 > rgbaRow = rgbaRowBuffer . GetSpan ( ) ;
78
86
79
87
for ( int i = 0 ; i < pixels . Height ; i ++ )
80
88
{
81
89
Span < TPixel > row = pixels . DangerousGetRowSpan ( i ) ;
90
+ PixelOperations < TPixel > . Instance . ToRgba32 ( this . configuration , row , rgbaRow ) ;
82
91
for ( int j = 0 ; j < row . Length && i < pixels . Height ; j ++ )
83
92
{
84
93
// We get the RGBA value from pixels
85
- TPixel currentPixel = row [ j ] ;
86
- currentPixel . ToRgba32 ( ref currentRgba32 ) ;
94
+ currentRgba32 = rgbaRow [ j ] ;
87
95
88
96
// First, we check if the current pixel is equal to the previous one
89
97
// If so, we do a QOI_OP_RUN
@@ -97,7 +105,7 @@ private void WritePixels<TPixel>(Image<TPixel> image, Stream stream)
97
105
* and we should discuss what to do about this approach and
98
106
* if it's correct
99
107
*/
100
- byte repetitions = 0 ;
108
+ int repetitions = 0 ;
101
109
do
102
110
{
103
111
repetitions ++ ;
@@ -112,15 +120,15 @@ private void WritePixels<TPixel>(Image<TPixel> image, Stream stream)
112
120
}
113
121
114
122
row = pixels . DangerousGetRowSpan ( i ) ;
123
+ PixelOperations < TPixel > . Instance . ToRgba32 ( this . configuration , row , rgbaRow ) ;
115
124
}
116
125
117
- currentPixel = row [ j ] ;
118
- currentPixel . ToRgba32 ( ref currentRgba32 ) ;
126
+ currentRgba32 = rgbaRow [ j ] ;
119
127
}
120
128
while ( currentRgba32 . Equals ( previousPixel ) && repetitions < 62 ) ;
121
129
122
130
j -- ;
123
- stream . WriteByte ( ( byte ) ( ( byte ) QoiChunk . QoiOpRun | ( repetitions - 1 ) ) ) ;
131
+ stream . WriteByte ( ( byte ) ( ( int ) QoiChunk . QoiOpRun | ( repetitions - 1 ) ) ) ;
124
132
125
133
/* If it's a QOI_OP_RUN, we don't overwrite the previous pixel since
126
134
* it will be taken and compared on the next iteration
@@ -131,7 +139,7 @@ private void WritePixels<TPixel>(Image<TPixel> image, Stream stream)
131
139
// else, we check if it exists in the previously seen pixels
132
140
// If so, we do a QOI_OP_INDEX
133
141
int pixelArrayPosition = GetArrayPosition ( currentRgba32 ) ;
134
- if ( previouslySeenPixels [ pixelArrayPosition ] . Equals ( currentPixel ) )
142
+ if ( previouslySeenPixels [ pixelArrayPosition ] . Equals ( currentRgba32 ) )
135
143
{
136
144
stream . WriteByte ( ( byte ) pixelArrayPosition ) ;
137
145
}
@@ -141,9 +149,9 @@ private void WritePixels<TPixel>(Image<TPixel> image, Stream stream)
141
149
// Since it wasn't found on the previously seen pixels, we save it
142
150
previouslySeenPixels [ pixelArrayPosition ] = currentRgba32 ;
143
151
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 ;
147
155
148
156
// If so, we do a QOI_OP_DIFF
149
157
if ( diffRed is >= - 2 and <= 1 &&
@@ -152,26 +160,26 @@ private void WritePixels<TPixel>(Image<TPixel> image, Stream stream)
152
160
currentRgba32 . A == previousPixel . A )
153
161
{
154
162
// 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 ) ;
159
167
stream . WriteByte ( valueToWrite ) ;
160
168
}
161
169
else
162
170
{
163
171
// else, we check if the green difference is less than -32..31 and the rest -8..7
164
172
// 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 ;
167
175
if ( diffGreen is >= - 32 and <= 31 &&
168
176
diffRedGreen is >= - 8 and <= 7 &&
169
177
diffBlueGreen is >= - 8 and <= 7 &&
170
178
currentRgba32 . A == previousPixel . A )
171
179
{
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 ) ) ;
175
183
byte byteToWrite2 = ( byte ) ( ( dr_dg << 4 ) | db_dg ) ;
176
184
stream . WriteByte ( byteToWrite1 ) ;
177
185
stream . WriteByte ( byteToWrite2 ) ;
0 commit comments