Skip to content

Commit

Permalink
Merge pull request #2420 from SixLabors/fix-encodedAlphaData-leak
Browse files Browse the repository at this point in the history
Backport WebP fix to 2.1
  • Loading branch information
JimBobSquarePants committed Mar 28, 2023
2 parents f53c78d + b5326e6 commit 93fdd3b
Showing 1 changed file with 54 additions and 46 deletions.
100 changes: 54 additions & 46 deletions src/ImageSharp/Formats/Webp/Lossy/Vp8Encoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -329,60 +329,68 @@ public void Encode<TPixel>(Image<TPixel> image, Stream stream)
bool alphaCompressionSucceeded = false;
using var alphaEncoder = new AlphaEncoder();
Span<byte> alphaData = Span<byte>.Empty;
if (hasAlpha)
IMemoryOwner<byte> encodedAlphaData = null;
try
{
// TODO: This can potentially run in an separate task.
IMemoryOwner<byte> encodedAlphaData = alphaEncoder.EncodeAlpha(image, this.configuration, this.memoryAllocator, this.alphaCompression, out alphaDataSize);
alphaData = encodedAlphaData.GetSpan();
if (alphaDataSize < pixelCount)
if (hasAlpha)
{
// Only use compressed data, if the compressed data is actually smaller then the uncompressed data.
alphaCompressionSucceeded = true;
// TODO: This can potentially run in an separate task.
encodedAlphaData = alphaEncoder.EncodeAlpha(image, this.configuration, this.memoryAllocator, this.alphaCompression, out alphaDataSize);
alphaData = encodedAlphaData.GetSpan();
if (alphaDataSize < pixelCount)
{
// Only use compressed data, if the compressed data is actually smaller then the uncompressed data.
alphaCompressionSucceeded = true;
}
}
}

// Stats-collection loop.
this.StatLoop(width, height, yStride, uvStride);
it.Init();
it.InitFilter();
var info = new Vp8ModeScore();
var residual = new Vp8Residual();
do
{
bool dontUseSkip = !this.Proba.UseSkipProba;
info.Clear();
it.Import(y, u, v, yStride, uvStride, width, height, false);

// Warning! order is important: first call VP8Decimate() and
// *then* decide how to code the skip decision if there's one.
if (!this.Decimate(it, ref info, this.rdOptLevel) || dontUseSkip)
{
this.CodeResiduals(it, info, residual);
}
else
// Stats-collection loop.
this.StatLoop(width, height, yStride, uvStride);
it.Init();
it.InitFilter();
var info = new Vp8ModeScore();
var residual = new Vp8Residual();
do
{
it.ResetAfterSkip();
bool dontUseSkip = !this.Proba.UseSkipProba;
info.Clear();
it.Import(y, u, v, yStride, uvStride, width, height, false);

// Warning! order is important: first call VP8Decimate() and
// *then* decide how to code the skip decision if there's one.
if (!this.Decimate(it, ref info, this.rdOptLevel) || dontUseSkip)
{
this.CodeResiduals(it, info, residual);
}
else
{
it.ResetAfterSkip();
}

it.SaveBoundary();
}
while (it.Next());

it.SaveBoundary();
// Store filter stats.
this.AdjustFilterStrength();

// Write bytes from the bitwriter buffer to the stream.
ImageMetadata metadata = image.Metadata;
metadata.SyncProfiles();
this.bitWriter.WriteEncodedImageToStream(
stream,
metadata.ExifProfile,
metadata.XmpProfile,
(uint)width,
(uint)height,
hasAlpha,
alphaData.Slice(0, alphaDataSize),
this.alphaCompression && alphaCompressionSucceeded);
}
finally
{
encodedAlphaData?.Dispose();
}
while (it.Next());

// Store filter stats.
this.AdjustFilterStrength();

// Write bytes from the bitwriter buffer to the stream.
ImageMetadata metadata = image.Metadata;
metadata.SyncProfiles();
this.bitWriter.WriteEncodedImageToStream(
stream,
metadata.ExifProfile,
metadata.XmpProfile,
(uint)width,
(uint)height,
hasAlpha,
alphaData,
this.alphaCompression && alphaCompressionSucceeded);
}

/// <inheritdoc/>
Expand Down

0 comments on commit 93fdd3b

Please sign in to comment.