Browse Source

move some methods from LosslessDecoder to base class

Implementing WebPLossyDecoder.DecodeAlphaData these methods are called from there containing the same code than in the lossless decoder,
so we move them to an abstract base class.
(not sure if it's a good idea to move the BitReader itself as well, so passing it as a parameter for now)
pull/1552/head
Peter Amrehn 6 years ago
parent
commit
2fb000ae6e
  1. 86
      src/ImageSharp/Formats/WebP/WebPDecoderBase.cs
  2. 76
      src/ImageSharp/Formats/WebP/WebPLosslessDecoder.cs
  3. 2
      src/ImageSharp/Formats/WebP/WebPLossyDecoder.cs

86
src/ImageSharp/Formats/WebP/WebPDecoderBase.cs

@ -0,0 +1,86 @@
// // Copyright (c) Six Labors and contributors.
// // Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Formats.WebP
{
abstract class WebPDecoderBase
{
protected HTreeGroup[] GetHTreeGroupForPos(Vp8LMetadata metadata, int x, int y)
{
uint metaIndex = this.GetMetaIndex(metadata.HuffmanImage, metadata.HuffmanXSize, metadata.HuffmanSubSampleBits, x, y);
return metadata.HTreeGroups.AsSpan((int)metaIndex).ToArray();
}
private uint GetMetaIndex(IMemoryOwner<uint> huffmanImage, int xSize, int bits, int x, int y)
{
if (bits is 0)
{
return 0;
}
Span<uint> huffmanImageSpan = huffmanImage.GetSpan();
return huffmanImageSpan[(xSize * (y >> bits)) + (x >> bits)];
}
// TODO: copied from WebPLosslessDecoder
protected int GetCopyDistance(int distanceSymbol, Vp8LBitReader bitReader)
{
if (distanceSymbol < 4)
{
return distanceSymbol + 1;
}
int extraBits = (distanceSymbol - 2) >> 1;
int offset = (2 + (distanceSymbol & 1)) << extraBits;
return (int)(offset + bitReader.ReadBits(extraBits) + 1);
}
// TODO: copied from WebPLosslessDecoder
protected int GetCopyLength(int lengthSymbol, Vp8LBitReader bitReader)
{
// Length and distance prefixes are encoded the same way.
return this.GetCopyDistance(lengthSymbol, bitReader);
}
// TODO: copied from LosslessDecoder
protected static readonly int[] KCodeToPlane =
{
0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a,
0x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a,
0x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b,
0x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03,
0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c,
0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e,
0x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b,
0x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f,
0x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b,
0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41,
0x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f,
0x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x70
};
protected static readonly int CodeToPlaneCodes = KCodeToPlane.Length;
protected int PlaneCodeToDistance(int xSize, int planeCode)
{
if (planeCode > CodeToPlaneCodes)
{
return planeCode - CodeToPlaneCodes;
}
int distCode = KCodeToPlane[planeCode - 1];
int yOffset = distCode >> 4;
int xOffset = 8 - (distCode & 0xf);
int dist = (yOffset * xSize) + xOffset;
// dist < 1 can happen if xSize is very small.
return (dist >= 1) ? dist : 1;
}
}
}

76
src/ImageSharp/Formats/WebP/WebPLosslessDecoder.cs

@ -19,7 +19,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
/// The lossless specification can be found here:
/// https://developers.google.com/speed/webp/docs/webp_lossless_bitstream_specification
/// </remarks>
internal sealed class WebPLosslessDecoder
internal sealed class WebPLosslessDecoder : WebPDecoderBase
{
private readonly Vp8LBitReader bitReader;
@ -50,24 +50,6 @@ namespace SixLabors.ImageSharp.Formats.WebP
private static readonly byte[] KCodeLengthCodeOrder = { 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
private static readonly int NumCodeLengthCodes = KCodeLengthCodeOrder.Length;
private static readonly int[] KCodeToPlane =
{
0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a,
0x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a,
0x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b,
0x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03,
0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c,
0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e,
0x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b,
0x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f,
0x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b,
0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41,
0x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f,
0x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x70
};
private static readonly int CodeToPlaneCodes = KCodeToPlane.Length;
private static readonly byte[] KLiteralMap =
{
0, 1, 1, 1, 0
@ -289,10 +271,10 @@ namespace SixLabors.ImageSharp.Formats.WebP
{
// Backward reference is used.
int lengthSym = code - WebPConstants.NumLiteralCodes;
int length = this.GetCopyLength(lengthSym);
int length = this.GetCopyLength(lengthSym, this.bitReader);
uint distSymbol = this.ReadSymbol(hTreeGroup[0].HTrees[HuffIndex.Dist]);
this.bitReader.FillBitWindow();
int distCode = this.GetCopyDistance((int)distSymbol);
int distCode = this.GetCopyDistance((int)distSymbol, this.bitReader);
int dist = this.PlaneCodeToDistance(width, distCode);
if (this.bitReader.IsEndOfStream())
{
@ -767,41 +749,6 @@ namespace SixLabors.ImageSharp.Formats.WebP
}
}
private int GetCopyDistance(int distanceSymbol)
{
if (distanceSymbol < 4)
{
return distanceSymbol + 1;
}
int extraBits = (distanceSymbol - 2) >> 1;
int offset = (2 + (distanceSymbol & 1)) << extraBits;
return (int)(offset + this.bitReader.ReadBits(extraBits) + 1);
}
private int GetCopyLength(int lengthSymbol)
{
// Length and distance prefixes are encoded the same way.
return this.GetCopyDistance(lengthSymbol);
}
private int PlaneCodeToDistance(int xSize, int planeCode)
{
if (planeCode > CodeToPlaneCodes)
{
return planeCode - CodeToPlaneCodes;
}
int distCode = KCodeToPlane[planeCode - 1];
int yOffset = distCode >> 4;
int xOffset = 8 - (distCode & 0xf);
int dist = (yOffset * xSize) + xOffset;
// dist < 1 can happen if xSize is very small.
return (dist >= 1) ? dist : 1;
}
private void BuildPackedTable(HTreeGroup hTreeGroup)
{
for (uint code = 0; code < HuffmanUtils.HuffmanPackedTableSize; ++code)
@ -832,22 +779,5 @@ namespace SixLabors.ImageSharp.Formats.WebP
huff.Value |= hCode.Value << shift;
return hCode.BitsUsed;
}
private uint GetMetaIndex(IMemoryOwner<uint> huffmanImage, int xSize, int bits, int x, int y)
{
if (bits is 0)
{
return 0;
}
Span<uint> huffmanImageSpan = huffmanImage.GetSpan();
return huffmanImageSpan[(xSize * (y >> bits)) + (x >> bits)];
}
private HTreeGroup[] GetHTreeGroupForPos(Vp8LMetadata metadata, int x, int y)
{
uint metaIndex = this.GetMetaIndex(metadata.HuffmanImage, metadata.HuffmanXSize, metadata.HuffmanSubSampleBits, x, y);
return metadata.HTreeGroups.AsSpan((int)metaIndex).ToArray();
}
}
}

2
src/ImageSharp/Formats/WebP/WebPLossyDecoder.cs

@ -10,7 +10,7 @@ using SixLabors.Memory;
namespace SixLabors.ImageSharp.Formats.WebP
{
internal sealed class WebPLossyDecoder
internal sealed class WebPLossyDecoder : WebPDecoderBase
{
private readonly Configuration configuration;

Loading…
Cancel
Save