Browse Source

Added comments to DQT marker parser, DQT exceptions now provide better info messages

pull/1706/head
Dmitry Pentin 5 years ago
parent
commit
1d781da193
  1. 2
      src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs
  2. 45
      src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
  3. 5
      src/ImageSharp/Formats/Jpeg/JpegThrowHelper.cs

2
src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs

@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
if (quantizationTableIndex > 3) if (quantizationTableIndex > 3)
{ {
JpegThrowHelper.ThrowBadQuantizationTable(); JpegThrowHelper.ThrowBadQuantizationTableIndex(quantizationTableIndex);
} }
this.QuantizationTableIndex = quantizationTableIndex; this.QuantizationTableIndex = quantizationTableIndex;

45
src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs

@ -755,26 +755,29 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
{ {
while (remaining > 0) while (remaining > 0)
{ {
bool done = false; // 1 byte: quantization table spec
remaining--; // bit 0..3: table index (0..3)
// bit 4..7: table precision (0 = 8 bit, 1 = 16 bit)
int quantizationTableSpec = stream.ReadByte(); int quantizationTableSpec = stream.ReadByte();
int tableIndex = quantizationTableSpec & 15; int tableIndex = quantizationTableSpec & 15;
int tablePrecision = quantizationTableSpec >> 4;
// Max index. 4 Tables max. // Validate:
if (tableIndex > 3) if (tableIndex > 3)
{ {
JpegThrowHelper.ThrowBadQuantizationTable(); JpegThrowHelper.ThrowBadQuantizationTableIndex(tableIndex);
} }
switch (quantizationTableSpec >> 4) remaining--;
switch (tablePrecision)
{ {
// 8 bit values
case 0: case 0:
{ {
// 8 bit values // Validate: 8 bit table needs exactly 64 bytes
if (remaining < 64) if (remaining < 64)
{ {
done = true; JpegThrowHelper.ThrowBadMarker(nameof(JpegConstants.Markers.DQT), remaining);
break;
} }
stream.Read(this.temp, 0, 64); stream.Read(this.temp, 0, 64);
@ -785,16 +788,17 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
{ {
table[j] = this.temp[j]; table[j] = this.temp[j];
} }
break;
} }
break; // 16 bit values
case 1: case 1:
{ {
// 16 bit values // Validate: 16 bit table needs exactly 128 bytes
if (remaining < 128) if (remaining < 128)
{ {
done = true; JpegThrowHelper.ThrowBadMarker(nameof(JpegConstants.Markers.DQT), remaining);
break;
} }
stream.Read(this.temp, 0, 128); stream.Read(this.temp, 0, 128);
@ -805,26 +809,17 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
{ {
table[j] = (this.temp[2 * j] << 8) | this.temp[(2 * j) + 1]; table[j] = (this.temp[2 * j] << 8) | this.temp[(2 * j) + 1];
} }
}
break; break;
}
// Unknown precision - error
default: default:
{ {
JpegThrowHelper.ThrowBadQuantizationTable(); JpegThrowHelper.ThrowBadQuantizationTablePrecision(tablePrecision);
break; break;
} }
} }
if (done)
{
break;
}
}
if (remaining != 0)
{
JpegThrowHelper.ThrowBadMarker(nameof(JpegConstants.Markers.DQT), remaining);
} }
this.Metadata.GetFormatMetadata(JpegFormat.Instance).Quality = QualityEvaluator.EstimateQuality(this.QuantizationTables); this.Metadata.GetFormatMetadata(JpegFormat.Instance).Quality = QualityEvaluator.EstimateQuality(this.QuantizationTables);

5
src/ImageSharp/Formats/Jpeg/JpegThrowHelper.cs

@ -36,7 +36,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
public static void ThrowBadMarker(string marker, int length) => throw new InvalidImageContentException($"Marker {marker} has bad length {length}."); public static void ThrowBadMarker(string marker, int length) => throw new InvalidImageContentException($"Marker {marker} has bad length {length}.");
[MethodImpl(InliningOptions.ColdPath)] [MethodImpl(InliningOptions.ColdPath)]
public static void ThrowBadQuantizationTable() => throw new InvalidImageContentException("Bad Quantization Table index."); public static void ThrowBadQuantizationTableIndex(int index) => throw new InvalidImageContentException($"Bad Quantization Table index {index}.");
[MethodImpl(InliningOptions.ColdPath)]
public static void ThrowBadQuantizationTablePrecision(int precision) => throw new InvalidImageContentException($"Unknown Quantization Table precision {precision}.");
[MethodImpl(InliningOptions.ColdPath)] [MethodImpl(InliningOptions.ColdPath)]
public static void ThrowBadSampling() => throw new InvalidImageContentException("Bad sampling factor."); public static void ThrowBadSampling() => throw new InvalidImageContentException("Bad sampling factor.");

Loading…
Cancel
Save