Browse Source

Merge pull request #1288 from stevetemple/webp-dev

Added Clone and Resize to Vp8LBitWriter
pull/1552/head
Brian Popow 6 years ago
committed by GitHub
parent
commit
d1e3997a02
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 53
      src/ImageSharp/Formats/WebP/BitWriter/Vp8LBitWriter.cs
  2. 17
      src/ImageSharp/Formats/WebP/Lossless/Vp8LEncoder.cs

53
src/ImageSharp/Formats/WebP/BitWriter/Vp8LBitWriter.cs

@ -45,14 +45,24 @@ namespace SixLabors.ImageSharp.Formats.WebP.BitWriter
private int end;
private bool error;
public Vp8LBitWriter(int expectedSize)
{
this.buffer = new byte[expectedSize];
this.end = this.buffer.Length;
}
/// <summary>
/// Initializes a new instance of the <see cref="Vp8LBitWriter"/> class.
/// Used internally for cloning
/// </summary>
private Vp8LBitWriter(byte[] buffer, ulong bits, int used, int cur)
{
this.buffer = buffer;
this.bits = bits;
this.used = used;
this.cur = cur;
}
/// <summary>
/// This function writes bits into bytes in increasing addresses (little endian),
/// and within a byte least-significant-bit first. This function can write up to 32 bits in one go.
@ -90,6 +100,13 @@ namespace SixLabors.ImageSharp.Formats.WebP.BitWriter
return this.cur + ((this.used + 7) >> 3);
}
public Vp8LBitWriter Clone()
{
byte[] clonedBuffer = new byte[this.buffer.Length];
Buffer.BlockCopy(this.buffer, 0, clonedBuffer, 0, this.cur);
return new Vp8LBitWriter(clonedBuffer, this.bits, this.used, this.cur);
}
/// <summary>
/// Internal function for PutBits flushing 32 bits from the written state.
/// </summary>
@ -99,11 +116,7 @@ namespace SixLabors.ImageSharp.Formats.WebP.BitWriter
if (this.cur + WriterBytes > this.end)
{
var extraSize = (this.end - this.cur) + MinExtraSize;
if (!this.BitWriterResize(extraSize))
{
this.error = true;
return;
}
this.BitWriterResize(extraSize);
}
BinaryPrimitives.WriteUInt64LittleEndian(this.buffer.AsSpan(this.cur), this.bits);
@ -112,10 +125,30 @@ namespace SixLabors.ImageSharp.Formats.WebP.BitWriter
this.used -= WriterBits;
}
private bool BitWriterResize(int extraSize)
private void BitWriterResize(int extraSize)
{
// TODO: resize buffer
return true;
int maxBytes = this.end + this.buffer.Length;
int sizeRequired = this.cur + extraSize;
if (maxBytes > 0 && sizeRequired < maxBytes)
{
return;
}
int newSize = (3 * maxBytes) >> 1;
if (newSize < sizeRequired)
{
newSize = sizeRequired;
}
// make new size multiple of 1k
newSize = ((newSize >> 10) + 1) << 10;
if (this.cur > 0)
{
Array.Resize(ref this.buffer, newSize);
}
this.end = this.buffer.Length;
}
}
}

17
src/ImageSharp/Formats/WebP/Lossless/Vp8LEncoder.cs

@ -318,8 +318,11 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
// Calculate backward references from ARGB image.
BackwardReferenceEncoder.HashChainFill(hashChain, bgra, quality, width, height);
// TODO: BitWriterInit(&bw_best, 0)
// BitWriterClone(bw, &bw_best))
Vp8LBitWriter bitWriterBest = null;
if (lz77sTypesToTrySize > 1)
{
bitWriterBest = this.bitWriter.Clone();
}
for (int lz77sIdx = 0; lz77sIdx < lz77sTypesToTrySize; lz77sIdx++)
{
@ -329,6 +332,8 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
// two as a temporary for later usage.
Vp8LBackwardRefs refsTmp = refsArray[refsBest.Equals(refsArray[0]) ? 1 : 0];
// TODO: this.bitWriter.Reset();
var tmpHisto = new Vp8LHistogram(cacheBits);
var histogramImage = new List<Vp8LHistogram>(histogramImageXySize);
for (int i = 0; i < histogramImageXySize; i++)
@ -414,7 +419,15 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
this.StoreImageToBitMask(width, histogramBits, refsBest, histogramSymbols, huffmanCodes);
// TODO: Keep track of the smallest image so far.
if (bitWriterBest != null && this.bitWriter.NumBytes() < bitWriterBest.NumBytes())
{
// TODO : This was done in the reference by swapping references, this will be slower
bitWriterBest = this.bitWriter.Clone();
}
}
this.bitWriter = bitWriterBest;
}
/// <summary>

Loading…
Cancel
Save