Browse Source

Paragraph 9.6: Dequantization Indices

pull/1552/head
Brian Popow 6 years ago
parent
commit
795617bdcf
  1. 4
      src/ImageSharp/Formats/WebP/AlphaDecoder.cs
  2. 48
      src/ImageSharp/Formats/WebP/WebPConstants.cs
  3. 68
      src/ImageSharp/Formats/WebP/WebPDecoderCore.cs

4
src/ImageSharp/Formats/WebP/AlphaDecoder.cs

@ -1,8 +1,10 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using SixLabors.ImageSharp.Formats.WebP.Filters;
namespace SixLabors.ImageSharp.Formats.WebP
{
internal ref struct AlphaDecoder

48
src/ImageSharp/Formats/WebP/WebPConstants.cs

@ -70,7 +70,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
public const int MaxColorCacheBits = 11;
/// <summary>
/// The maximum number of allowed transforms in a bitstream.
/// The maximum number of allowed transforms in a VP8L bitstream.
/// </summary>
public const int MaxNumberOfTransforms = 4;
@ -104,5 +104,51 @@ namespace SixLabors.ImageSharp.Formats.WebP
NumLiteralCodes, NumLiteralCodes, NumLiteralCodes,
NumDistanceCodes
};
// VP8 constants
public const int NumMbSegments = 4;
public const int MaxNumPartitions = 8;
// Paragraph 14.1
public static readonly int[] DcTable =
{
4, 5, 6, 7, 8, 9, 10, 10,
11, 12, 13, 14, 15, 16, 17, 17,
18, 19, 20, 20, 21, 21, 22, 22,
23, 23, 24, 25, 25, 26, 27, 28,
29, 30, 31, 32, 33, 34, 35, 36,
37, 37, 38, 39, 40, 41, 42, 43,
44, 45, 46, 46, 47, 48, 49, 50,
51, 52, 53, 54, 55, 56, 57, 58,
59, 60, 61, 62, 63, 64, 65, 66,
67, 68, 69, 70, 71, 72, 73, 74,
75, 76, 76, 77, 78, 79, 80, 81,
82, 83, 84, 85, 86, 87, 88, 89,
91, 93, 95, 96, 98, 100, 101, 102,
104, 106, 108, 110, 112, 114, 116, 118,
122, 124, 126, 128, 130, 132, 134, 136,
138, 140, 143, 145, 148, 151, 154, 157
};
public static readonly int[] AcTable =
{
4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27,
28, 29, 30, 31, 32, 33, 34, 35,
36, 37, 38, 39, 40, 41, 42, 43,
44, 45, 46, 47, 48, 49, 50, 51,
52, 53, 54, 55, 56, 57, 58, 60,
62, 64, 66, 68, 70, 72, 74, 76,
78, 80, 82, 84, 86, 88, 90, 92,
94, 96, 98, 100, 102, 104, 106, 108,
110, 112, 114, 116, 119, 122, 125, 128,
131, 134, 137, 140, 143, 146, 149, 152,
155, 158, 161, 164, 167, 170, 173, 177,
181, 185, 189, 193, 197, 201, 205, 209,
213, 217, 221, 225, 229, 234, 239, 245,
249, 254, 259, 264, 269, 274, 279, 284
};
}
}

68
src/ImageSharp/Formats/WebP/WebPDecoderCore.cs

@ -374,6 +374,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
// Paragraph 9.3: Parse the segment header.
var vp8SegmentHeader = new Vp8SegmentHeader();
vp8SegmentHeader.UseSegment = bitReader.ReadBool();
bool hasValue = false;
if (vp8SegmentHeader.UseSegment)
{
vp8SegmentHeader.UpdateMap = bitReader.ReadBool();
@ -383,14 +384,14 @@ namespace SixLabors.ImageSharp.Formats.WebP
vp8SegmentHeader.Delta = bitReader.ReadBool();
for (int i = 0; i < vp8SegmentHeader.Quantizer.Length; i++)
{
bool hasValue = bitReader.ReadBool();
hasValue = bitReader.ReadBool();
uint quantizeValue = hasValue ? bitReader.ReadValue(7) : 0;
vp8SegmentHeader.Quantizer[i] = (byte)quantizeValue;
}
for (int i = 0; i < vp8SegmentHeader.FilterStrength.Length; i++)
{
bool hasValue = bitReader.ReadBool();
hasValue = bitReader.ReadBool();
uint filterStrengthValue = hasValue ? bitReader.ReadValue(6) : 0;
vp8SegmentHeader.FilterStrength[i] = (byte)filterStrengthValue;
}
@ -419,7 +420,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
{
for (int i = 0; i < vp8FilterHeader.RefLfDelta.Length; i++)
{
bool hasValue = bitReader.ReadBool();
hasValue = bitReader.ReadBool();
if (hasValue)
{
vp8FilterHeader.RefLfDelta[i] = bitReader.ReadSignedValue(6);
@ -428,7 +429,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
for (int i = 0; i < vp8FilterHeader.ModeLfDelta.Length; i++)
{
bool hasValue = bitReader.ReadBool();
hasValue = bitReader.ReadBool();
if (hasValue)
{
vp8FilterHeader.ModeLfDelta[i] = bitReader.ReadSignedValue(6);
@ -442,7 +443,61 @@ namespace SixLabors.ImageSharp.Formats.WebP
int lastPart = numPartsMinusOne;
// TODO: check if we have enough data available here, throw exception if not
// Paragraph 9.6: Dequantization Indices
int baseQ0 = (int)bitReader.ReadValue(7);
hasValue = bitReader.ReadBool();
int dqy1Dc = hasValue ? bitReader.ReadSignedValue(4) : 0;
hasValue = bitReader.ReadBool();
int dqy2Dc = hasValue ? bitReader.ReadSignedValue(4) : 0;
hasValue = bitReader.ReadBool();
int dqy2Ac = hasValue ? bitReader.ReadSignedValue(4) : 0;
hasValue = bitReader.ReadBool();
int dquvDc = hasValue ? bitReader.ReadSignedValue(4) : 0;
hasValue = bitReader.ReadBool();
int dquvAc = hasValue ? bitReader.ReadSignedValue(4) : 0;
for (int i = 0; i < WebPConstants.NumMbSegments; ++i)
{
int q;
if (vp8SegmentHeader.UseSegment)
{
q = vp8SegmentHeader.Quantizer[i];
if (!vp8SegmentHeader.Delta)
{
q += baseQ0;
}
}
else
{
if (i > 0)
{
// dec->dqm_[i] = dec->dqm_[0];
continue;
}
else
{
q = baseQ0;
}
}
var m = new Vp8QuantMatrix();
m.Y1Mat[0] = WebPConstants.DcTable[this.Clip(q + dqy1Dc, 127)];
m.Y1Mat[1] = WebPConstants.AcTable[this.Clip(q + 0, 127)];
m.Y2Mat[0] = WebPConstants.DcTable[this.Clip(q + dqy2Dc, 127)] * 2;
// For all x in [0..284], x*155/100 is bitwise equal to (x*101581) >> 16.
// The smallest precision for that is '(x*6349) >> 12' but 16 is a good word size.
m.Y2Mat[1] = (WebPConstants.AcTable[this.Clip(q + dqy2Ac, 127)] * 101581) >> 16;
if (m.Y2Mat[1] < 8)
{
m.Y2Mat[1] = 8;
}
m.UVMat[0] = WebPConstants.DcTable[this.Clip(q + dquvDc, 117)];
m.UVMat[1] = WebPConstants.AcTable[this.Clip(q + dquvAc, 127)];
// For dithering strength evaluation.
m.UvQuant = q + dquvAc;
}
return new WebPImageInfo()
{
@ -578,5 +633,10 @@ namespace SixLabors.ImageSharp.Formats.WebP
throw new ImageFormatException("Invalid WebP data.");
}
private int Clip(int v, int M)
{
return v < 0 ? 0 : v > M ? M : v;
}
}
}

Loading…
Cancel
Save