Browse Source

Fixed invalid non-interleaved single component jpeg scan parsing

pull/1979/head
Dmitry Pentin 5 years ago
parent
commit
ca9c45e601
  1. 61
      src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanDecoder.cs

61
src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanDecoder.cs

@ -148,11 +148,16 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
private void ParseBaselineData() private void ParseBaselineData()
{ {
if (this.componentsCount == this.frame.ComponentCount) if (this.componentsCount != 1)
{ {
this.ParseBaselineDataInterleaved(); this.ParseBaselineDataInterleaved();
this.spectralConverter.CommitConversion(); this.spectralConverter.CommitConversion();
} }
else if (this.frame.ComponentCount == 1)
{
this.ParseBaselineDataSingleComponent();
this.spectralConverter.CommitConversion();
}
else else
{ {
this.ParseBaselineDataNonInterleaved(); this.ParseBaselineDataNonInterleaved();
@ -161,7 +166,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
private void ParseBaselineDataInterleaved() private void ParseBaselineDataInterleaved()
{ {
// Interleaved
int mcu = 0; int mcu = 0;
int mcusPerColumn = this.frame.McusPerColumn; int mcusPerColumn = this.frame.McusPerColumn;
int mcusPerLine = this.frame.McusPerLine; int mcusPerLine = this.frame.McusPerLine;
@ -198,7 +202,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
{ {
if (buffer.NoData) if (buffer.NoData)
{ {
// It is very likely that some spectral data was decoded before we encountered EOI marker // It is very likely that some spectral data was decoded before we've encountered 'end of scan'
// so we need to decode what's left and return (or maybe throw?) // so we need to decode what's left and return (or maybe throw?)
this.spectralConverter.ConvertStrideBaseline(); this.spectralConverter.ConvertStrideBaseline();
return; return;
@ -221,9 +225,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
this.HandleRestart(); this.HandleRestart();
} }
// convert from spectral to actual pixels via given converter // Convert from spectral to actual pixels via given converter
this.spectralConverter.ConvertStrideBaseline(); this.spectralConverter.ConvertStrideBaseline();
} }
// Stride conversion must be sealed for stride conversion approach
this.spectralConverter.CommitConversion();
} }
private void ParseBaselineDataNonInterleaved() private void ParseBaselineDataNonInterleaved()
@ -261,6 +268,52 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
} }
} }
private void ParseBaselineDataSingleComponent()
{
JpegComponent component = this.frame.Components[0];
int mcuLines = this.frame.McusPerColumn;
int w = component.WidthInBlocks;
int h = component.SamplingFactors.Height;
ref HuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DCHuffmanTableId];
ref HuffmanTable acHuffmanTable = ref this.acHuffmanTables[component.ACHuffmanTableId];
ref HuffmanScanBuffer buffer = ref this.scanBuffer;
for (int i = 0; i < mcuLines; i++)
{
this.cancellationToken.ThrowIfCancellationRequested();
// decode from binary to spectral
for (int j = 0; j < h; j++)
{
Span<Block8x8> blockSpan = component.SpectralBlocks.DangerousGetRowSpan(j);
ref Block8x8 blockRef = ref MemoryMarshal.GetReference(blockSpan);
for (int k = 0; k < w; k++)
{
if (buffer.NoData)
{
// It is very likely that some spectral data was decoded before we've encountered 'end of scan'
// so we need to decode what's left and return (or maybe throw?)
this.spectralConverter.ConvertStrideBaseline();
return;
}
this.DecodeBlockBaseline(
component,
ref Unsafe.Add(ref blockRef, k),
ref dcHuffmanTable,
ref acHuffmanTable);
this.HandleRestart();
}
}
// Convert from spectral to actual pixels via given converter
this.spectralConverter.ConvertStrideBaseline();
}
}
private void CheckProgressiveData() private void CheckProgressiveData()
{ {
// Validate successive scan parameters. // Validate successive scan parameters.

Loading…
Cancel
Save