From 4904f325fa27c59518afe87ddba8a17d44c5db41 Mon Sep 17 00:00:00 2001 From: Ynse Hoornenborg Date: Mon, 10 Jan 2022 06:29:38 +0100 Subject: [PATCH] Use memory allocator for all text chunks --- src/ImageSharp/Formats/Png/PngEncoderCore.cs | 69 +++++++++++++------- 1 file changed, 47 insertions(+), 22 deletions(-) diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index da6878051..c443c0fcf 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -739,21 +739,33 @@ namespace SixLabors.ImageSharp.Formats.Png byte[] translatedKeyword = PngConstants.TranslatedEncoding.GetBytes(textData.TranslatedKeyword); byte[] languageTag = PngConstants.LanguageEncoding.GetBytes(textData.LanguageTag); - Span outputBytes = new byte[keywordBytes.Length + textBytes.Length + - translatedKeyword.Length + languageTag.Length + 5]; - keywordBytes.CopyTo(outputBytes); - if (textData.Value.Length > this.options.TextCompressionThreshold) + int payloadLength = keywordBytes.Length + textBytes.Length + translatedKeyword.Length + languageTag.Length + 5; + using (IMemoryOwner owner = this.memoryAllocator.Allocate(payloadLength)) { - // Indicate that the text is compressed. - outputBytes[keywordBytes.Length + 1] = 1; - } + Span outputBytes = owner.GetSpan(); + keywordBytes.CopyTo(outputBytes); + int bytesWritten = keywordBytes.Length; + outputBytes[bytesWritten++] = 0; + if (textData.Value.Length > this.options.TextCompressionThreshold) + { + // Indicate that the text is compressed. + outputBytes[bytesWritten++] = 1; + } + else + { + outputBytes[bytesWritten++] = 0; + } - int keywordStart = keywordBytes.Length + 3; - languageTag.CopyTo(outputBytes.Slice(keywordStart)); - int translatedKeywordStart = keywordStart + languageTag.Length + 1; - translatedKeyword.CopyTo(outputBytes.Slice(translatedKeywordStart)); - textBytes.CopyTo(outputBytes.Slice(translatedKeywordStart + translatedKeyword.Length + 1)); - this.WriteChunk(stream, PngChunkType.InternationalText, outputBytes.ToArray()); + outputBytes[bytesWritten++] = 0; + languageTag.CopyTo(outputBytes.Slice(bytesWritten)); + bytesWritten += languageTag.Length; + outputBytes[bytesWritten++] = 0; + translatedKeyword.CopyTo(outputBytes.Slice(bytesWritten)); + bytesWritten += translatedKeyword.Length; + outputBytes[bytesWritten++] = 0; + textBytes.CopyTo(outputBytes.Slice(bytesWritten)); + this.WriteChunk(stream, PngChunkType.InternationalText, outputBytes); + } } else { @@ -762,19 +774,32 @@ namespace SixLabors.ImageSharp.Formats.Png // Write zTXt chunk. byte[] compressedData = this.GetCompressedTextBytes(PngConstants.Encoding.GetBytes(textData.Value)); - Span outputBytes = new byte[textData.Keyword.Length + compressedData.Length + 2]; - PngConstants.Encoding.GetBytes(textData.Keyword).CopyTo(outputBytes); - compressedData.CopyTo(outputBytes.Slice(textData.Keyword.Length + 2)); - this.WriteChunk(stream, PngChunkType.CompressedText, outputBytes.ToArray()); + int payloadLength = textData.Keyword.Length + compressedData.Length + 2; + using (IMemoryOwner owner = this.memoryAllocator.Allocate(payloadLength)) + { + Span outputBytes = owner.GetSpan(); + PngConstants.Encoding.GetBytes(textData.Keyword).CopyTo(outputBytes); + int bytesWritten = textData.Keyword.Length; + outputBytes[bytesWritten++] = 0; + outputBytes[bytesWritten++] = 0; + compressedData.CopyTo(outputBytes.Slice(bytesWritten)); + this.WriteChunk(stream, PngChunkType.CompressedText, outputBytes.ToArray()); + } } else { // Write tEXt chunk. - Span outputBytes = new byte[textData.Keyword.Length + textData.Value.Length + 1]; - PngConstants.Encoding.GetBytes(textData.Keyword).CopyTo(outputBytes); - PngConstants.Encoding.GetBytes(textData.Value) - .CopyTo(outputBytes.Slice(textData.Keyword.Length + 1)); - this.WriteChunk(stream, PngChunkType.Text, outputBytes.ToArray()); + int payloadLength = textData.Keyword.Length + textData.Value.Length + 1; + using (IMemoryOwner owner = this.memoryAllocator.Allocate(payloadLength)) + { + Span outputBytes = owner.GetSpan(); + PngConstants.Encoding.GetBytes(textData.Keyword).CopyTo(outputBytes); + int bytesWritten = textData.Keyword.Length; + outputBytes[bytesWritten++] = 0; + PngConstants.Encoding.GetBytes(textData.Value) + .CopyTo(outputBytes.Slice(bytesWritten)); + this.WriteChunk(stream, PngChunkType.Text, outputBytes.ToArray()); + } } } }