diff --git a/src/ImageSharp/Formats/Webp/BitWriter/BitWriterBase.cs b/src/ImageSharp/Formats/Webp/BitWriter/BitWriterBase.cs index b82b764fc3..ad7d69f130 100644 --- a/src/ImageSharp/Formats/Webp/BitWriter/BitWriterBase.cs +++ b/src/ImageSharp/Formats/Webp/BitWriter/BitWriterBase.cs @@ -137,6 +137,82 @@ internal abstract class BitWriterBase stream.Position = position; } + /// + /// Write the trunks before data trunk. + /// + /// Think of it as a static method — none of the other members are called except for + /// The stream to write to. + /// The width of the image. + /// The height of the image. + /// The exif profile. + /// The XMP profile. + /// The color profile. + /// Flag indicating, if a alpha channel is present. + /// The alpha channel data. + /// Indicates, if the alpha data is compressed. + public void WriteTrunksBeforeData( + Stream stream, + uint width, + uint height, + ExifProfile? exifProfile, + XmpProfile? xmpProfile, + IccProfile? iccProfile, + bool hasAlpha, + Span alphaData, + bool alphaDataIsCompressed) + { + // Write file size later + this.WriteRiffHeader(stream, 0); + + // Write VP8X, header if necessary. + bool isVp8X = exifProfile != null || xmpProfile != null || iccProfile != null || hasAlpha; + if (isVp8X) + { + this.WriteVp8XHeader(stream, exifProfile, xmpProfile, iccProfile, width, height, hasAlpha); + + if (iccProfile != null) + { + this.WriteColorProfile(stream, iccProfile.ToByteArray()); + } + + if (hasAlpha) + { + this.WriteAlphaChunk(stream, alphaData, alphaDataIsCompressed); + } + } + } + + /// + /// Writes the encoded image to the stream. + /// + /// The stream to write to. + public abstract void WriteEncodedImageToStream(Stream stream); + + /// + /// Write the trunks after data trunk. + /// + /// Think of it as a static method — none of the other members are called except for + /// The stream to write to. + /// The exif profile. + /// The XMP profile. + public void WriteTrunksAfterData( + Stream stream, + ExifProfile? exifProfile, + XmpProfile? xmpProfile) + { + if (exifProfile != null) + { + this.WriteMetadataProfile(stream, exifProfile.ToByteArray(), WebpChunkType.Exif); + } + + if (xmpProfile != null) + { + this.WriteMetadataProfile(stream, xmpProfile.Data, WebpChunkType.Xmp); + } + + OverwriteFileSize(stream); + } + /// /// Writes a metadata profile (EXIF or XMP) to the stream. /// diff --git a/src/ImageSharp/Formats/Webp/BitWriter/Vp8BitWriter.cs b/src/ImageSharp/Formats/Webp/BitWriter/Vp8BitWriter.cs index 5dd5d335de..923d2a69c4 100644 --- a/src/ImageSharp/Formats/Webp/BitWriter/Vp8BitWriter.cs +++ b/src/ImageSharp/Formats/Webp/BitWriter/Vp8BitWriter.cs @@ -3,9 +3,6 @@ using System.Buffers.Binary; using SixLabors.ImageSharp.Formats.Webp.Lossy; -using SixLabors.ImageSharp.Metadata.Profiles.Exif; -using SixLabors.ImageSharp.Metadata.Profiles.Icc; -using SixLabors.ImageSharp.Metadata.Profiles.Xmp; namespace SixLabors.ImageSharp.Formats.Webp.BitWriter; @@ -394,56 +391,8 @@ internal class Vp8BitWriter : BitWriterBase } } - /// - /// Write the trunks before data trunk. - /// - /// Think of it as a static method — none of the other members are called except for - /// The stream to write to. - /// The width of the image. - /// The height of the image. - /// The exif profile. - /// The XMP profile. - /// The color profile. - /// Flag indicating, if a alpha channel is present. - /// The alpha channel data. - /// Indicates, if the alpha data is compressed. - public void WriteTrunksBeforeData( - Stream stream, - uint width, - uint height, - ExifProfile? exifProfile, - XmpProfile? xmpProfile, - IccProfile? iccProfile, - bool hasAlpha, - Span alphaData, - bool alphaDataIsCompressed) - { - // Write file size later - this.WriteRiffHeader(stream, 0); - - // Write VP8X, header if necessary. - bool isVp8X = exifProfile != null || xmpProfile != null || iccProfile != null || hasAlpha; - if (isVp8X) - { - this.WriteVp8XHeader(stream, exifProfile, xmpProfile, iccProfile, width, height, hasAlpha); - - if (iccProfile != null) - { - this.WriteColorProfile(stream, iccProfile.ToByteArray()); - } - - if (hasAlpha) - { - this.WriteAlphaChunk(stream, alphaData, alphaDataIsCompressed); - } - } - } - - /// - /// Writes the encoded image to the stream. - /// - /// The stream to write to. - public void WriteEncodedImageToStream(Stream stream) + /// + public override void WriteEncodedImageToStream(Stream stream) { uint numBytes = (uint)this.NumBytes; @@ -474,31 +423,6 @@ internal class Vp8BitWriter : BitWriterBase } } - /// - /// Write the trunks after data trunk. - /// - /// Think of it as a static method — none of the other members are called except for - /// The stream to write to. - /// The exif profile. - /// The XMP profile. - public void WriteTrunksAfterData( - Stream stream, - ExifProfile? exifProfile, - XmpProfile? xmpProfile) - { - if (exifProfile != null) - { - this.WriteMetadataProfile(stream, exifProfile.ToByteArray(), WebpChunkType.Exif); - } - - if (xmpProfile != null) - { - this.WriteMetadataProfile(stream, xmpProfile.Data, WebpChunkType.Xmp); - } - - OverwriteFileSize(stream); - } - private uint GeneratePartition0() { this.PutBitUniform(0); // colorspace diff --git a/src/ImageSharp/Formats/Webp/BitWriter/Vp8LBitWriter.cs b/src/ImageSharp/Formats/Webp/BitWriter/Vp8LBitWriter.cs index 0ac1b4038a..bce77c9e5c 100644 --- a/src/ImageSharp/Formats/Webp/BitWriter/Vp8LBitWriter.cs +++ b/src/ImageSharp/Formats/Webp/BitWriter/Vp8LBitWriter.cs @@ -3,9 +3,6 @@ using System.Buffers.Binary; using SixLabors.ImageSharp.Formats.Webp.Lossless; -using SixLabors.ImageSharp.Metadata.Profiles.Exif; -using SixLabors.ImageSharp.Metadata.Profiles.Icc; -using SixLabors.ImageSharp.Metadata.Profiles.Xmp; namespace SixLabors.ImageSharp.Formats.Webp.BitWriter; @@ -122,68 +119,11 @@ internal class Vp8LBitWriter : BitWriterBase this.used = 0; } - /// - /// Writes the encoded image to the stream. - /// - /// The stream to write to. - /// The exif profile. - /// The XMP profile. - /// The color profile. - /// The width of the image. - /// The height of the image. - /// Flag indicating, if a alpha channel is present. - public void WriteEncodedImageToStream(Stream stream, ExifProfile? exifProfile, XmpProfile? xmpProfile, IccProfile? iccProfile, uint width, uint height, bool hasAlpha) + /// + public override void WriteEncodedImageToStream(Stream stream) { - bool isVp8X = false; - byte[]? exifBytes = null; - byte[]? xmpBytes = null; - byte[]? iccBytes = null; - uint riffSize = 0; - if (exifProfile != null) - { - isVp8X = true; - exifBytes = exifProfile.ToByteArray(); - riffSize += MetadataChunkSize(exifBytes!); - } - - if (xmpProfile != null) - { - isVp8X = true; - xmpBytes = xmpProfile.Data; - riffSize += MetadataChunkSize(xmpBytes!); - } - - if (iccProfile != null) - { - isVp8X = true; - iccBytes = iccProfile.ToByteArray(); - riffSize += MetadataChunkSize(iccBytes); - } - - if (isVp8X) - { - riffSize += ExtendedFileChunkSize; - } - - this.Finish(); - uint size = (uint)this.NumBytes; - size++; // One byte extra for the VP8L signature. - - // Write RIFF header. + uint size = (uint)this.NumBytes + 1; // One byte extra for the VP8L signature uint pad = size & 1; - riffSize += WebpConstants.TagSize + WebpConstants.ChunkHeaderSize + size + pad; - this.WriteRiffHeader(stream, riffSize); - - // Write VP8X, header if necessary. - if (isVp8X) - { - this.WriteVp8XHeader(stream, exifProfile, xmpProfile, iccProfile, width, height, hasAlpha); - - if (iccBytes != null) - { - this.WriteColorProfile(stream, iccBytes); - } - } // Write magic bytes indicating its a lossless webp. Span scratchBuffer = stackalloc byte[WebpConstants.TagSize]; @@ -201,16 +141,6 @@ internal class Vp8LBitWriter : BitWriterBase { stream.WriteByte(0); } - - if (exifProfile != null) - { - this.WriteMetadataProfile(stream, exifBytes, WebpChunkType.Exif); - } - - if (xmpProfile != null) - { - this.WriteMetadataProfile(stream, xmpBytes, WebpChunkType.Xmp); - } } /// diff --git a/src/ImageSharp/Formats/Webp/Lossless/Vp8LEncoder.cs b/src/ImageSharp/Formats/Webp/Lossless/Vp8LEncoder.cs index d27bfcd956..4d526e7b4b 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/Vp8LEncoder.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/Vp8LEncoder.cs @@ -10,6 +10,7 @@ using SixLabors.ImageSharp.Formats.Webp.BitWriter; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.Metadata.Profiles.Exif; +using SixLabors.ImageSharp.Metadata.Profiles.Icc; using SixLabors.ImageSharp.Metadata.Profiles.Xmp; using SixLabors.ImageSharp.PixelFormats; @@ -265,8 +266,22 @@ internal class Vp8LEncoder : IDisposable // Encode the main image stream. this.EncodeStream(image.Frames.RootFrame); + this.bitWriter.Finish(); + this.bitWriter.WriteTrunksBeforeData( + stream, + (uint)width, + (uint)height, + exifProfile, + xmpProfile, + metadata.IccProfile, + false /*hasAlpha*/, + Span.Empty, + false); + // Write bytes from the bitwriter buffer to the stream. - this.bitWriter.WriteEncodedImageToStream(stream, exifProfile, xmpProfile, metadata.IccProfile, (uint)width, (uint)height, hasAlpha); + this.bitWriter.WriteEncodedImageToStream(stream); + + this.bitWriter.WriteTrunksAfterData(stream, exifProfile, xmpProfile); } /// diff --git a/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoder.cs b/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoder.cs index 56397e66d4..f744827bf3 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoder.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoder.cs @@ -8,7 +8,6 @@ using SixLabors.ImageSharp.Formats.Webp.BitWriter; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.Metadata.Profiles.Exif; -using SixLabors.ImageSharp.Metadata.Profiles.Icc; using SixLabors.ImageSharp.Metadata.Profiles.Xmp; using SixLabors.ImageSharp.PixelFormats;