@@ -38,15 +38,10 @@ internal sealed class PngEncoderCore : IImageEncoderInternals, IDisposable
38
38
/// </summary>
39
39
private readonly Configuration configuration ;
40
40
41
- /// <summary>
42
- /// Reusable buffer for writing general data.
43
- /// </summary>
44
- private readonly byte [ ] buffer = new byte [ 8 ] ;
45
-
46
41
/// <summary>
47
42
/// Reusable buffer for writing chunk data.
48
43
/// </summary>
49
- private readonly byte [ ] chunkDataBuffer = new byte [ 16 ] ;
44
+ private ScratchBuffer chunkDataBuffer ; // mutable struct, don't make readonly
50
45
51
46
/// <summary>
52
47
/// The encoder with options
@@ -576,9 +571,9 @@ private void WriteHeaderChunk(Stream stream)
576
571
filterMethod : 0 ,
577
572
interlaceMethod : this . interlaceMode ) ;
578
573
579
- header . WriteTo ( this . chunkDataBuffer ) ;
574
+ header . WriteTo ( this . chunkDataBuffer . Span ) ;
580
575
581
- this . WriteChunk ( stream , PngChunkType . Header , this . chunkDataBuffer , 0 , PngHeader . Size ) ;
576
+ this . WriteChunk ( stream , PngChunkType . Header , this . chunkDataBuffer . Span , 0 , PngHeader . Size ) ;
582
577
}
583
578
584
579
/// <summary>
@@ -652,9 +647,9 @@ private void WritePhysicalChunk(Stream stream, ImageMetadata meta)
652
647
return ;
653
648
}
654
649
655
- PhysicalChunkData . FromMetadata ( meta ) . WriteTo ( this . chunkDataBuffer ) ;
650
+ PhysicalChunkData . FromMetadata ( meta ) . WriteTo ( this . chunkDataBuffer . Span ) ;
656
651
657
- this . WriteChunk ( stream , PngChunkType . Physical , this . chunkDataBuffer , 0 , PhysicalChunkData . Size ) ;
652
+ this . WriteChunk ( stream , PngChunkType . Physical , this . chunkDataBuffer . Span , 0 , PhysicalChunkData . Size ) ;
658
653
}
659
654
660
655
/// <summary>
@@ -880,9 +875,9 @@ private void WriteGammaChunk(Stream stream)
880
875
// 4-byte unsigned integer of gamma * 100,000.
881
876
uint gammaValue = ( uint ) ( this . gamma * 100_000F ) ;
882
877
883
- BinaryPrimitives . WriteUInt32BigEndian ( this . chunkDataBuffer . AsSpan ( 0 , 4 ) , gammaValue ) ;
878
+ BinaryPrimitives . WriteUInt32BigEndian ( this . chunkDataBuffer . Span . Slice ( 0 , 4 ) , gammaValue ) ;
884
879
885
- this . WriteChunk ( stream , PngChunkType . Gamma , this . chunkDataBuffer , 0 , 4 ) ;
880
+ this . WriteChunk ( stream , PngChunkType . Gamma , this . chunkDataBuffer . Span , 0 , 4 ) ;
886
881
}
887
882
}
888
883
@@ -899,7 +894,7 @@ private void WriteTransparencyChunk(Stream stream, PngMetadata pngMetadata)
899
894
return ;
900
895
}
901
896
902
- Span < byte > alpha = this . chunkDataBuffer . AsSpan ( ) ;
897
+ Span < byte > alpha = this . chunkDataBuffer . Span ;
903
898
if ( pngMetadata . ColorType == PngColorType . Rgb )
904
899
{
905
900
if ( pngMetadata . TransparentRgb48 . HasValue && this . use16Bit )
@@ -909,7 +904,7 @@ private void WriteTransparencyChunk(Stream stream, PngMetadata pngMetadata)
909
904
BinaryPrimitives . WriteUInt16LittleEndian ( alpha . Slice ( 2 , 2 ) , rgb . G ) ;
910
905
BinaryPrimitives . WriteUInt16LittleEndian ( alpha . Slice ( 4 , 2 ) , rgb . B ) ;
911
906
912
- this . WriteChunk ( stream , PngChunkType . Transparency , this . chunkDataBuffer , 0 , 6 ) ;
907
+ this . WriteChunk ( stream , PngChunkType . Transparency , this . chunkDataBuffer . Span , 0 , 6 ) ;
913
908
}
914
909
else if ( pngMetadata . TransparentRgb24 . HasValue )
915
910
{
@@ -918,21 +913,21 @@ private void WriteTransparencyChunk(Stream stream, PngMetadata pngMetadata)
918
913
alpha [ 1 ] = rgb . R ;
919
914
alpha [ 3 ] = rgb . G ;
920
915
alpha [ 5 ] = rgb . B ;
921
- this . WriteChunk ( stream , PngChunkType . Transparency , this . chunkDataBuffer , 0 , 6 ) ;
916
+ this . WriteChunk ( stream , PngChunkType . Transparency , this . chunkDataBuffer . Span , 0 , 6 ) ;
922
917
}
923
918
}
924
919
else if ( pngMetadata . ColorType == PngColorType . Grayscale )
925
920
{
926
921
if ( pngMetadata . TransparentL16 . HasValue && this . use16Bit )
927
922
{
928
923
BinaryPrimitives . WriteUInt16LittleEndian ( alpha , pngMetadata . TransparentL16 . Value . PackedValue ) ;
929
- this . WriteChunk ( stream , PngChunkType . Transparency , this . chunkDataBuffer , 0 , 2 ) ;
924
+ this . WriteChunk ( stream , PngChunkType . Transparency , this . chunkDataBuffer . Span , 0 , 2 ) ;
930
925
}
931
926
else if ( pngMetadata . TransparentL8 . HasValue )
932
927
{
933
928
alpha . Clear ( ) ;
934
929
alpha [ 1 ] = pngMetadata . TransparentL8 . Value . PackedValue ;
935
- this . WriteChunk ( stream , PngChunkType . Transparency , this . chunkDataBuffer , 0 , 2 ) ;
930
+ this . WriteChunk ( stream , PngChunkType . Transparency , this . chunkDataBuffer . Span , 0 , 2 ) ;
936
931
}
937
932
}
938
933
}
@@ -1173,12 +1168,14 @@ private void WriteChunk(Stream stream, PngChunkType type, Span<byte> data)
1173
1168
/// <param name="length">The of the data to write.</param>
1174
1169
private void WriteChunk ( Stream stream , PngChunkType type , Span < byte > data , int offset , int length )
1175
1170
{
1176
- BinaryPrimitives . WriteInt32BigEndian ( this . buffer , length ) ;
1177
- BinaryPrimitives . WriteUInt32BigEndian ( this . buffer . AsSpan ( 4 , 4 ) , ( uint ) type ) ;
1171
+ Span < byte > buffer = stackalloc byte [ 8 ] ;
1172
+
1173
+ BinaryPrimitives . WriteInt32BigEndian ( buffer , length ) ;
1174
+ BinaryPrimitives . WriteUInt32BigEndian ( buffer . Slice ( 4 , 4 ) , ( uint ) type ) ;
1178
1175
1179
- stream . Write ( this . buffer , 0 , 8 ) ;
1176
+ stream . Write ( buffer ) ;
1180
1177
1181
- uint crc = Crc32 . Calculate ( this . buffer . AsSpan ( 4 , 4 ) ) ; // Write the type buffer
1178
+ uint crc = Crc32 . Calculate ( buffer . Slice ( 4 ) ) ; // Write the type buffer
1182
1179
1183
1180
if ( data . Length > 0 && length > 0 )
1184
1181
{
@@ -1187,9 +1184,9 @@ private void WriteChunk(Stream stream, PngChunkType type, Span<byte> data, int o
1187
1184
crc = Crc32 . Calculate ( crc , data . Slice ( offset , length ) ) ;
1188
1185
}
1189
1186
1190
- BinaryPrimitives . WriteUInt32BigEndian ( this . buffer , crc ) ;
1187
+ BinaryPrimitives . WriteUInt32BigEndian ( buffer , crc ) ;
1191
1188
1192
- stream . Write ( this . buffer , 0 , 4 ) ; // write the crc
1189
+ stream . Write ( buffer , 0 , 4 ) ; // write the crc
1193
1190
}
1194
1191
1195
1192
/// <summary>
@@ -1412,4 +1409,11 @@ private static PngBitDepth SuggestBitDepth<TPixel>()
1412
1409
Type t when t == typeof ( RgbaVector ) => PngBitDepth . Bit16 ,
1413
1410
_ => PngBitDepth . Bit8
1414
1411
} ;
1412
+
1413
+ private unsafe struct ScratchBuffer
1414
+ {
1415
+ private fixed byte scratch [ 16 ] ;
1416
+
1417
+ public Span < byte > Span => MemoryMarshal . CreateSpan ( ref this . scratch [ 0 ] , 16 ) ;
1418
+ }
1415
1419
}
0 commit comments