Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.