@@ -87,21 +87,20 @@ protected void ResizeBuffer(int maxBytes, int sizeRequired)
8787 /// <summary>
8888 /// Writes the RIFF header to the stream.
8989 /// </summary>
90- /// <remarks>Think of it as a static method — none of the other members are called except for <see cref="scratchBuffer"/></remarks>
9190 /// <param name="stream">The stream to write to.</param>
9291 /// <param name="riffSize">The block length.</param>
93- protected void WriteRiffHeader ( Stream stream , uint riffSize )
92+ protected static void WriteRiffHeader ( Stream stream , uint riffSize )
9493 {
9594 stream . Write ( WebpConstants . RiffFourCc ) ;
96- BinaryPrimitives . WriteUInt32LittleEndian ( this . scratchBuffer . Span , riffSize ) ;
97- stream . Write ( this . scratchBuffer . Span [ ..4 ] ) ;
95+ Span < byte > buf = stackalloc byte [ 4 ] ;
96+ BinaryPrimitives . WriteUInt32LittleEndian ( buf , riffSize ) ;
97+ stream . Write ( buf ) ;
9898 stream . Write ( WebpConstants . WebpHeader ) ;
9999 }
100100
101101 /// <summary>
102102 /// Calculates the chunk size of EXIF, XMP or ICCP metadata.
103103 /// </summary>
104- /// <remarks>Think of it as a static method — none of the other members are called except for <see cref="scratchBuffer"/></remarks>
105104 /// <param name="metadataBytes">The metadata profile bytes.</param>
106105 /// <returns>The metadata chunk size in bytes.</returns>
107106 protected static uint MetadataChunkSize ( byte [ ] metadataBytes )
@@ -125,59 +124,41 @@ protected static uint AlphaChunkSize(Span<byte> alphaBytes)
125124 /// Overwrites ides the write file size.
126125 /// </summary>
127126 /// <param name="stream">The stream to write to.</param>
128- protected static void OverwriteFileSize ( Stream stream )
129- {
130- uint position = ( uint ) stream . Position ;
131- stream . Position = 4 ;
132- byte [ ] buffer = new byte [ 4 ] ;
133-
134- // "RIFF"(4)+uint32 size(4)
135- BinaryPrimitives . WriteUInt32LittleEndian ( buffer , position - WebpConstants . ChunkHeaderSize ) ;
136- stream . Write ( buffer ) ;
137- stream . Position = position ;
138- }
127+ protected static void OverwriteFileSize ( Stream stream ) => OverwriteFrameSize ( stream , 4 ) ;
139128
140129 /// <summary>
141130 /// Write the trunks before data trunk.
142131 /// </summary>
143- /// <remarks>Think of it as a static method — none of the other members are called except for <see cref="BitWriterBase.scratchBuffer"/></remarks>
144132 /// <param name="stream">The stream to write to.</param>
145133 /// <param name="width">The width of the image.</param>
146134 /// <param name="height">The height of the image.</param>
147135 /// <param name="exifProfile">The exif profile.</param>
148136 /// <param name="xmpProfile">The XMP profile.</param>
149137 /// <param name="iccProfile">The color profile.</param>
150138 /// <param name="hasAlpha">Flag indicating, if a alpha channel is present.</param>
151- /// <param name="alphaData">The alpha channel data.</param>
152- /// <param name="alphaDataIsCompressed">Indicates, if the alpha data is compressed.</param>
153- public void WriteTrunksBeforeData (
139+ /// <param name="hasAnimation">Flag indicating, if an animation parameter is present.</param>
140+ public static void WriteTrunksBeforeData (
154141 Stream stream ,
155142 uint width ,
156143 uint height ,
157144 ExifProfile ? exifProfile ,
158145 XmpProfile ? xmpProfile ,
159146 IccProfile ? iccProfile ,
160147 bool hasAlpha ,
161- Span < byte > alphaData ,
162- bool alphaDataIsCompressed )
148+ bool hasAnimation )
163149 {
164150 // Write file size later
165- this . WriteRiffHeader ( stream , 0 ) ;
151+ WriteRiffHeader ( stream , 0 ) ;
166152
167153 // Write VP8X, header if necessary.
168- bool isVp8X = exifProfile != null || xmpProfile != null || iccProfile != null || hasAlpha ;
154+ bool isVp8X = exifProfile != null || xmpProfile != null || iccProfile != null || hasAlpha || hasAnimation ;
169155 if ( isVp8X )
170156 {
171- this . WriteVp8XHeader ( stream , exifProfile , xmpProfile , iccProfile , width , height , hasAlpha ) ;
157+ WriteVp8XHeader ( stream , exifProfile , xmpProfile , iccProfile , width , height , hasAlpha , hasAnimation ) ;
172158
173159 if ( iccProfile != null )
174160 {
175- this . WriteColorProfile ( stream , iccProfile . ToByteArray ( ) ) ;
176- }
177-
178- if ( hasAlpha )
179- {
180- this . WriteAlphaChunk ( stream , alphaData , alphaDataIsCompressed ) ;
161+ WriteColorProfile ( stream , iccProfile . ToByteArray ( ) ) ;
181162 }
182163 }
183164 }
@@ -191,23 +172,22 @@ public void WriteTrunksBeforeData(
191172 /// <summary>
192173 /// Write the trunks after data trunk.
193174 /// </summary>
194- /// <remarks>Think of it as a static method — none of the other members are called except for <see cref="BitWriterBase.scratchBuffer"/></remarks>
195175 /// <param name="stream">The stream to write to.</param>
196176 /// <param name="exifProfile">The exif profile.</param>
197177 /// <param name="xmpProfile">The XMP profile.</param>
198- public void WriteTrunksAfterData (
178+ public static void WriteTrunksAfterData (
199179 Stream stream ,
200180 ExifProfile ? exifProfile ,
201181 XmpProfile ? xmpProfile )
202182 {
203183 if ( exifProfile != null )
204184 {
205- this . WriteMetadataProfile ( stream , exifProfile . ToByteArray ( ) , WebpChunkType . Exif ) ;
185+ WriteMetadataProfile ( stream , exifProfile . ToByteArray ( ) , WebpChunkType . Exif ) ;
206186 }
207187
208188 if ( xmpProfile != null )
209189 {
210- this . WriteMetadataProfile ( stream , xmpProfile . Data , WebpChunkType . Xmp ) ;
190+ WriteMetadataProfile ( stream , xmpProfile . Data , WebpChunkType . Xmp ) ;
211191 }
212192
213193 OverwriteFileSize ( stream ) ;
@@ -216,16 +196,15 @@ public void WriteTrunksAfterData(
216196 /// <summary>
217197 /// Writes a metadata profile (EXIF or XMP) to the stream.
218198 /// </summary>
219- /// <remarks>Think of it as a static method — none of the other members are called except for <see cref="scratchBuffer"/></remarks>
220199 /// <param name="stream">The stream to write to.</param>
221200 /// <param name="metadataBytes">The metadata profile's bytes.</param>
222201 /// <param name="chunkType">The chuck type to write.</param>
223- protected void WriteMetadataProfile ( Stream stream , byte [ ] ? metadataBytes , WebpChunkType chunkType )
202+ protected static void WriteMetadataProfile ( Stream stream , byte [ ] ? metadataBytes , WebpChunkType chunkType )
224203 {
225204 DebugGuard . NotNull ( metadataBytes , nameof ( metadataBytes ) ) ;
226205
227206 uint size = ( uint ) metadataBytes . Length ;
228- Span < byte > buf = this . scratchBuffer . Span [ .. 4 ] ;
207+ Span < byte > buf = stackalloc byte [ 4 ] ;
229208 BinaryPrimitives . WriteUInt32BigEndian ( buf , ( uint ) chunkType ) ;
230209 stream . Write ( buf ) ;
231210 BinaryPrimitives . WriteUInt32LittleEndian ( buf , size ) ;
@@ -242,15 +221,13 @@ protected void WriteMetadataProfile(Stream stream, byte[]? metadataBytes, WebpCh
242221 /// <summary>
243222 /// Writes the color profile(<see cref="WebpChunkType.Iccp"/>) to the stream.
244223 /// </summary>
245- /// <remarks>Think of it as a static method — none of the other members are called except for <see cref="scratchBuffer"/></remarks>
246224 /// <param name="stream">The stream to write to.</param>
247225 /// <param name="iccProfileBytes">The color profile bytes.</param>
248- protected void WriteColorProfile ( Stream stream , byte [ ] iccProfileBytes ) => this . WriteMetadataProfile ( stream , iccProfileBytes , WebpChunkType . Iccp ) ;
226+ protected static void WriteColorProfile ( Stream stream , byte [ ] iccProfileBytes ) => WriteMetadataProfile ( stream , iccProfileBytes , WebpChunkType . Iccp ) ;
249227
250228 /// <summary>
251229 /// Writes the animation parameter(<see cref="WebpChunkType.AnimationParameter"/>) to the stream.
252230 /// </summary>
253- /// <remarks>Think of it as a static method — none of the other members are called except for <see cref="scratchBuffer"/></remarks>
254231 /// <param name="stream">The stream to write to.</param>
255232 /// <param name="background">
256233 /// The default background color of the canvas in [Blue, Green, Red, Alpha] byte order.
@@ -259,9 +236,9 @@ protected void WriteMetadataProfile(Stream stream, byte[]? metadataBytes, WebpCh
259236 /// The background color is also used when the Disposal method is 1.
260237 /// </param>
261238 /// <param name="loopCount">The number of times to loop the animation. If it is 0, this means infinitely.</param>
262- protected void WriteAnimationParameter ( Stream stream , uint background , ushort loopCount )
239+ public static void WriteAnimationParameter ( Stream stream , uint background , ushort loopCount )
263240 {
264- Span < byte > buf = this . scratchBuffer . Span [ .. 4 ] ;
241+ Span < byte > buf = stackalloc byte [ 4 ] ;
265242 BinaryPrimitives . WriteUInt32BigEndian ( buf , ( uint ) WebpChunkType . AnimationParameter ) ;
266243 stream . Write ( buf ) ;
267244 BinaryPrimitives . WriteUInt32LittleEndian ( buf , sizeof ( uint ) + sizeof ( ushort ) ) ;
@@ -275,17 +252,15 @@ protected void WriteAnimationParameter(Stream stream, uint background, ushort lo
275252 /// <summary>
276253 /// Writes the animation frame(<see cref="WebpChunkType.Animation"/>) to the stream.
277254 /// </summary>
278- /// <remarks>Think of it as a static method — none of the other members are called except for <see cref="scratchBuffer"/></remarks>
279255 /// <param name="stream">The stream to write to.</param>
280256 /// <param name="animation">Animation frame data.</param>
281- /// <param name="data">Frame data.</param>
282- protected void WriteAnimationFrame ( Stream stream , AnimationFrameData animation , Span < byte > data )
257+ public static long WriteAnimationFrame ( Stream stream , AnimationFrameData animation )
283258 {
284- uint size = AnimationFrameData . HeaderSize + ( uint ) data . Length ;
285- Span < byte > buf = this . scratchBuffer . Span [ ..4 ] ;
259+ Span < byte > buf = stackalloc byte [ 4 ] ;
286260 BinaryPrimitives . WriteUInt32BigEndian ( buf , ( uint ) WebpChunkType . Animation ) ;
287261 stream . Write ( buf ) ;
288- BinaryPrimitives . WriteUInt32BigEndian ( buf , size ) ;
262+ long position = stream . Position ;
263+ BinaryPrimitives . WriteUInt32BigEndian ( buf , 0 ) ;
289264 stream . Write ( buf ) ;
290265 WebpChunkParsingUtils . WriteUInt24LittleEndian ( stream , animation . X ) ;
291266 WebpChunkParsingUtils . WriteUInt24LittleEndian ( stream , animation . Y ) ;
@@ -294,20 +269,35 @@ protected void WriteAnimationFrame(Stream stream, AnimationFrameData animation,
294269 WebpChunkParsingUtils . WriteUInt24LittleEndian ( stream , animation . Duration ) ;
295270 byte flag = ( byte ) ( ( ( int ) animation . BlendingMethod << 1 ) | ( int ) animation . DisposalMethod ) ;
296271 stream . WriteByte ( flag ) ;
297- stream . Write ( data ) ;
272+ return position ;
273+ }
274+
275+ /// <summary>
276+ /// Overwrites ides the write frame size.
277+ /// </summary>
278+ /// <param name="stream">The stream to write to.</param>
279+ /// <param name="prevPosition">Previous position.</param>
280+ public static void OverwriteFrameSize ( Stream stream , long prevPosition )
281+ {
282+ uint position = ( uint ) stream . Position ;
283+ stream . Position = prevPosition ;
284+ byte [ ] buffer = new byte [ 4 ] ;
285+
286+ BinaryPrimitives . WriteUInt32LittleEndian ( buffer , ( uint ) ( position - prevPosition - 4 ) ) ;
287+ stream . Write ( buffer ) ;
288+ stream . Position = position ;
298289 }
299290
300291 /// <summary>
301292 /// Writes the alpha chunk to the stream.
302293 /// </summary>
303- /// <remarks>Think of it as a static method — none of the other members are called except for <see cref="scratchBuffer"/></remarks>
304294 /// <param name="stream">The stream to write to.</param>
305295 /// <param name="dataBytes">The alpha channel data bytes.</param>
306296 /// <param name="alphaDataIsCompressed">Indicates, if the alpha channel data is compressed.</param>
307- protected void WriteAlphaChunk ( Stream stream , Span < byte > dataBytes , bool alphaDataIsCompressed )
297+ public static void WriteAlphaChunk ( Stream stream , Span < byte > dataBytes , bool alphaDataIsCompressed )
308298 {
309299 uint size = ( uint ) dataBytes . Length + 1 ;
310- Span < byte > buf = this . scratchBuffer . Span [ .. 4 ] ;
300+ Span < byte > buf = stackalloc byte [ 4 ] ;
311301 BinaryPrimitives . WriteUInt32BigEndian ( buf , ( uint ) WebpChunkType . Alpha ) ;
312302 stream . Write ( buf ) ;
313303 BinaryPrimitives . WriteUInt32LittleEndian ( buf , size ) ;
@@ -332,15 +322,15 @@ protected void WriteAlphaChunk(Stream stream, Span<byte> dataBytes, bool alphaDa
332322 /// <summary>
333323 /// Writes a VP8X header to the stream.
334324 /// </summary>
335- /// <remarks>Think of it as a static method — none of the other members are called except for <see cref="scratchBuffer"/></remarks>
336325 /// <param name="stream">The stream to write to.</param>
337326 /// <param name="exifProfile">A exif profile or null, if it does not exist.</param>
338327 /// <param name="xmpProfile">A XMP profile or null, if it does not exist.</param>
339328 /// <param name="iccProfile">The color profile.</param>
340329 /// <param name="width">The width of the image.</param>
341330 /// <param name="height">The height of the image.</param>
342331 /// <param name="hasAlpha">Flag indicating, if a alpha channel is present.</param>
343- protected void WriteVp8XHeader ( Stream stream , ExifProfile ? exifProfile , XmpProfile ? xmpProfile , IccProfile ? iccProfile , uint width , uint height , bool hasAlpha )
332+ /// <param name="hasAnimation">Flag indicating, if an animation parameter is present.</param>
333+ protected static void WriteVp8XHeader ( Stream stream , ExifProfile ? exifProfile , XmpProfile ? xmpProfile , IccProfile ? iccProfile , uint width , uint height , bool hasAlpha , bool hasAnimation )
344334 {
345335 if ( width > MaxDimension || height > MaxDimension )
346336 {
@@ -360,13 +350,11 @@ protected void WriteVp8XHeader(Stream stream, ExifProfile? exifProfile, XmpProfi
360350 flags |= 8 ;
361351 }
362352
363- /*
364- if (isAnimated)
353+ if ( hasAnimation )
365354 {
366355 // Set animated flag.
367356 flags |= 2 ;
368357 }
369- */
370358
371359 if ( xmpProfile != null )
372360 {
@@ -386,7 +374,7 @@ protected void WriteVp8XHeader(Stream stream, ExifProfile? exifProfile, XmpProfi
386374 flags |= 32 ;
387375 }
388376
389- Span < byte > buf = this . scratchBuffer . Span [ .. 4 ] ;
377+ Span < byte > buf = stackalloc byte [ 4 ] ;
390378 BinaryPrimitives . WriteUInt32BigEndian ( buf , ( uint ) WebpChunkType . Vp8X ) ;
391379 stream . Write ( buf ) ;
392380 BinaryPrimitives . WriteUInt32LittleEndian ( buf , WebpConstants . Vp8XChunkSize ) ;
0 commit comments