@@ -72,7 +72,7 @@ public Vp8BitWriter(int expectedSize, Vp8Encoder enc)
7272 }
7373
7474 /// <inheritdoc/>
75- public override int NumBytes ( ) => ( int ) this . pos ;
75+ public override int NumBytes => ( int ) this . pos ;
7676
7777 public int PutCoeffs ( int ctx , Vp8Residual residual )
7878 {
@@ -395,67 +395,58 @@ private void Flush()
395395 }
396396
397397 /// <summary>
398- /// Writes the encoded image to the stream .
398+ /// Write the trunks before data trunk .
399399 /// </summary>
400+ /// <remarks>Think of it as a static method — none of the other members are called except for <see cref="BitWriterBase.scratchBuffer"/></remarks>
400401 /// <param name="stream">The stream to write to.</param>
402+ /// <param name="width">The width of the image.</param>
403+ /// <param name="height">The height of the image.</param>
401404 /// <param name="exifProfile">The exif profile.</param>
402405 /// <param name="xmpProfile">The XMP profile.</param>
403406 /// <param name="iccProfile">The color profile.</param>
404- /// <param name="width">The width of the image.</param>
405- /// <param name="height">The height of the image.</param>
406407 /// <param name="hasAlpha">Flag indicating, if a alpha channel is present.</param>
407408 /// <param name="alphaData">The alpha channel data.</param>
408409 /// <param name="alphaDataIsCompressed">Indicates, if the alpha data is compressed.</param>
409- public void WriteEncodedImageToStream (
410+ public void WriteTrunksBeforeData (
410411 Stream stream ,
412+ uint width ,
413+ uint height ,
411414 ExifProfile ? exifProfile ,
412415 XmpProfile ? xmpProfile ,
413416 IccProfile ? iccProfile ,
414- uint width ,
415- uint height ,
416417 bool hasAlpha ,
417418 Span < byte > alphaData ,
418419 bool alphaDataIsCompressed )
419420 {
420- bool isVp8X = false ;
421- byte [ ] ? exifBytes = null ;
422- byte [ ] ? xmpBytes = null ;
423- byte [ ] ? iccProfileBytes = null ;
424- uint riffSize = 0 ;
425- if ( exifProfile != null )
426- {
427- isVp8X = true ;
428- exifBytes = exifProfile . ToByteArray ( ) ;
429- riffSize += MetadataChunkSize ( exifBytes ! ) ;
430- }
421+ // Write file size later
422+ this . WriteRiffHeader ( stream , 0 ) ;
431423
432- if ( xmpProfile != null )
424+ // Write VP8X, header if necessary.
425+ bool isVp8X = exifProfile != null || xmpProfile != null || iccProfile != null || hasAlpha ;
426+ if ( isVp8X )
433427 {
434- isVp8X = true ;
435- xmpBytes = xmpProfile . Data ;
436- riffSize += MetadataChunkSize ( xmpBytes ! ) ;
437- }
428+ this . WriteVp8XHeader ( stream , exifProfile , xmpProfile , iccProfile , width , height , hasAlpha ) ;
438429
439- if ( iccProfile != null )
440- {
441- isVp8X = true ;
442- iccProfileBytes = iccProfile . ToByteArray ( ) ;
443- riffSize += MetadataChunkSize ( iccProfileBytes ) ;
444- }
430+ if ( iccProfile != null )
431+ {
432+ this . WriteColorProfile ( stream , iccProfile . ToByteArray ( ) ) ;
433+ }
445434
446- if ( hasAlpha )
447- {
448- isVp8X = true ;
449- riffSize += AlphaChunkSize ( alphaData ) ;
435+ if ( hasAlpha )
436+ {
437+ this . WriteAlphaChunk ( stream , alphaData , alphaDataIsCompressed ) ;
438+ }
450439 }
440+ }
451441
452- if ( isVp8X )
453- {
454- riffSize += ExtendedFileChunkSize ;
455- }
442+ /// <summary>
443+ /// Writes the encoded image to the stream.
444+ /// </summary>
445+ /// <param name="stream">The stream to write to.</param>
446+ public void WriteEncodedImageToStream ( Stream stream )
447+ {
448+ uint numBytes = ( uint ) this . NumBytes ;
456449
457- this . Finish ( ) ;
458- uint numBytes = ( uint ) this . NumBytes ( ) ;
459450 int mbSize = this . enc . Mbw * this . enc . Mbh ;
460451 int expectedSize = ( int ) ( ( uint ) mbSize * 7 / 8 ) ;
461452
@@ -469,12 +460,10 @@ public void WriteEncodedImageToStream(
469460 uint pad = vp8Size & 1 ;
470461 vp8Size += pad ;
471462
472- // Compute RIFF size.
473- // At the minimum it is: "WEBPVP8 nnnn" + VP8 data size.
474- riffSize += WebpConstants . TagSize + WebpConstants . ChunkHeaderSize + vp8Size ;
463+ // Emit header and partition #0
464+ this . WriteVp8Header ( stream , vp8Size ) ;
465+ this . WriteFrameHeader ( stream , size0 ) ;
475466
476- // Emit headers and partition #0
477- this . WriteWebpHeaders ( stream , size0 , vp8Size , riffSize , isVp8X , width , height , exifProfile , xmpProfile , iccProfileBytes , hasAlpha , alphaData , alphaDataIsCompressed ) ;
478467 bitWriterPartZero . WriteToStream ( stream ) ;
479468
480469 // Write the encoded image to the stream.
@@ -483,16 +472,31 @@ public void WriteEncodedImageToStream(
483472 {
484473 stream . WriteByte ( 0 ) ;
485474 }
475+ }
486476
477+ /// <summary>
478+ /// Write the trunks after data trunk.
479+ /// </summary>
480+ /// <remarks>Think of it as a static method — none of the other members are called except for <see cref="BitWriterBase.scratchBuffer"/></remarks>
481+ /// <param name="stream">The stream to write to.</param>
482+ /// <param name="exifProfile">The exif profile.</param>
483+ /// <param name="xmpProfile">The XMP profile.</param>
484+ public void WriteTrunksAfterData (
485+ Stream stream ,
486+ ExifProfile ? exifProfile ,
487+ XmpProfile ? xmpProfile )
488+ {
487489 if ( exifProfile != null )
488490 {
489- this . WriteMetadataProfile ( stream , exifBytes , WebpChunkType . Exif ) ;
491+ this . WriteMetadataProfile ( stream , exifProfile . ToByteArray ( ) , WebpChunkType . Exif ) ;
490492 }
491493
492494 if ( xmpProfile != null )
493495 {
494- this . WriteMetadataProfile ( stream , xmpBytes , WebpChunkType . Xmp ) ;
496+ this . WriteMetadataProfile ( stream , xmpProfile . Data , WebpChunkType . Xmp ) ;
495497 }
498+
499+ OverwriteFileSize ( stream ) ;
496500 }
497501
498502 private uint GeneratePartition0 ( )
@@ -512,7 +516,7 @@ private uint GeneratePartition0()
512516
513517 this . Finish ( ) ;
514518
515- return ( uint ) this . NumBytes ( ) ;
519+ return ( uint ) this . NumBytes ;
516520 }
517521
518522 private void WriteSegmentHeader ( )
@@ -662,43 +666,6 @@ private void CodeIntraModes()
662666 while ( it . Next ( ) ) ;
663667 }
664668
665- private void WriteWebpHeaders (
666- Stream stream ,
667- uint size0 ,
668- uint vp8Size ,
669- uint riffSize ,
670- bool isVp8X ,
671- uint width ,
672- uint height ,
673- ExifProfile ? exifProfile ,
674- XmpProfile ? xmpProfile ,
675- byte [ ] ? iccProfileBytes ,
676- bool hasAlpha ,
677- Span < byte > alphaData ,
678- bool alphaDataIsCompressed )
679- {
680- this . WriteRiffHeader ( stream , riffSize ) ;
681-
682- // Write VP8X, header if necessary.
683- if ( isVp8X )
684- {
685- this . WriteVp8XHeader ( stream , exifProfile , xmpProfile , iccProfileBytes , width , height , hasAlpha ) ;
686-
687- if ( iccProfileBytes != null )
688- {
689- this . WriteColorProfile ( stream , iccProfileBytes ) ;
690- }
691-
692- if ( hasAlpha )
693- {
694- this . WriteAlphaChunk ( stream , alphaData , alphaDataIsCompressed ) ;
695- }
696- }
697-
698- this . WriteVp8Header ( stream , vp8Size ) ;
699- this . WriteFrameHeader ( stream , size0 ) ;
700- }
701-
702669 private void WriteVp8Header ( Stream stream , uint size )
703670 {
704671 Span < byte > buf = stackalloc byte [ WebpConstants . TagSize ] ;
0 commit comments