Skip to content

Commit

Permalink
Merge pull request #1979 from br3aker/dp/jpeg-grayscale-fix
Browse files Browse the repository at this point in the history
Fixed decoding grayscale jpegs with exotic sampling factors
  • Loading branch information
JimBobSquarePants authored Feb 6, 2022
2 parents e5c40dc + 4fd6a29 commit 6d434ea
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -148,11 +148,16 @@ public void InjectFrameData(JpegFrame frame, IRawJpegData jpegData)

private void ParseBaselineData()
{
if (this.componentsCount == this.frame.ComponentCount)
if (this.componentsCount != 1)
{
this.ParseBaselineDataInterleaved();
this.spectralConverter.CommitConversion();
}
else if (this.frame.ComponentCount == 1)
{
this.ParseBaselineDataSingleComponent();
this.spectralConverter.CommitConversion();
}
else
{
this.ParseBaselineDataNonInterleaved();
Expand All @@ -161,7 +166,6 @@ private void ParseBaselineData()

private void ParseBaselineDataInterleaved()
{
// Interleaved
int mcu = 0;
int mcusPerColumn = this.frame.McusPerColumn;
int mcusPerLine = this.frame.McusPerLine;
Expand Down Expand Up @@ -198,7 +202,7 @@ private void ParseBaselineDataInterleaved()
{
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?)
this.spectralConverter.ConvertStrideBaseline();
return;
Expand All @@ -221,9 +225,12 @@ ref Unsafe.Add(ref blockRef, blockCol),
this.HandleRestart();
}

// convert from spectral to actual pixels via given converter
// Convert from spectral to actual pixels via given converter
this.spectralConverter.ConvertStrideBaseline();
}

// Stride conversion must be sealed for stride conversion approach
this.spectralConverter.CommitConversion();
}

private void ParseBaselineDataNonInterleaved()
Expand Down Expand Up @@ -261,6 +268,52 @@ ref Unsafe.Add(ref blockRef, i),
}
}

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()
{
// Validate successive scan parameters.
Expand Down
3 changes: 3 additions & 0 deletions tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ public partial class JpegDecoderTests

// High depth images
TestImages.Jpeg.Baseline.Testorig12bit,

// Grayscale jpeg with 2x2 sampling factors (not a usual thing to encounter in the wild)
TestImages.Jpeg.Baseline.GrayscaleSampling2x2,
};

public static string[] ProgressiveTestJpegs =
Expand Down
1 change: 1 addition & 0 deletions tests/ImageSharp.Tests/TestImages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ public static class Bad
public const string Winter444_Interleaved = "Jpg/baseline/winter444_interleaved.jpg";
public const string Metadata = "Jpg/baseline/Metadata-test-file.jpg";
public const string ExtendedXmp = "Jpg/baseline/extended-xmp.jpg";
public const string GrayscaleSampling2x2 = "Jpg/baseline/grayscale_sampling22.jpg";

public static readonly string[] All =
{
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions tests/Images/Input/Jpg/baseline/grayscale_sampling22.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 6d434ea

Please sign in to comment.