Skip to content

Commit

Permalink
Rebase and update to .NET SDK 9.0
Browse files Browse the repository at this point in the history
  • Loading branch information
vbaderks committed Dec 31, 2024
1 parent d2aba3f commit 84322f9
Show file tree
Hide file tree
Showing 12 changed files with 104 additions and 59 deletions.
3 changes: 2 additions & 1 deletion benchmark/CharLS.Managed.Benchmark.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<!--
CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
CA1515: types can be made internal (Benchmark framework requires public types).
-->
<NoWarn>$(NoWarn),1591</NoWarn>
<NoWarn>$(NoWarn),1591,CA1515</NoWarn>
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion benchmark/PortableAnymapFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public override string ReadLine()
byte b = (byte)current;
bytes.Add(b);
}
return Encoding.ASCII.GetString(bytes.ToArray());
return Encoding.ASCII.GetString([.. bytes]);
}

// Read works differently than the `Read()` method of a
Expand Down
1 change: 1 addition & 0 deletions exclusion.dic
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ opto
palletised
glimit
Golomb
Errval
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"sdk": {
"version": "8.0.400",
"version": "9.0.100",
"rollForward": "latestFeature",
"allowPrerelease": false
}
Expand Down
2 changes: 1 addition & 1 deletion src/JpegLSDecoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ public void Decode(Span<byte> destination, int stride = AutoCalculateStride)
{
int scanStride = CheckStrideAndDestinationLength(destination.Length, stride);
_scanDecoder = new ScanDecoder(_reader.ScanFrameInfo, _reader.GetValidatedPresetCodingParameters(), _reader.GetCodingParameters());
int bytesRead = _scanDecoder.DecodeScan(_reader.RemainingSource(), destination, scanStride);
int bytesRead = _scanDecoder.DecodeScan(_reader.RemainingSource(), destination, scanStride, _reader.Widths, _reader.Heights);
_reader.AdvancePosition(bytesRead);

component += _reader.ScanComponentCount;
Expand Down
14 changes: 1 addition & 13 deletions src/JpegLSEncoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ public sealed class JpegLSEncoder

private JpegStreamWriter _writer;
private ScanEncoder _scanEncoder;
private FrameInfo _frameInfo;
private int _nearLossless;
private InterleaveMode _interleaveMode;
private ColorTransformation _colorTransformation;
Expand Down Expand Up @@ -93,18 +92,7 @@ private enum State
/// <value>
/// The frame information of the image.
/// </value>
/// <exception cref="ArgumentException">Thrown when the passed FrameInfo is invalid.</exception>
/// <exception cref="ArgumentNullException">Thrown when the passed FrameInfo instance is null.</exception>
public FrameInfo FrameInfo
{
get => _frameInfo;

set
{
ArgumentNullException.ThrowIfNull(value);
_frameInfo = value;
}
}
public FrameInfo FrameInfo { get; set; }

/// <summary>
/// Gets or sets the near lossless parameter to be used to encode the JPEG-LS stream.
Expand Down
26 changes: 26 additions & 0 deletions src/JpegStreamReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ internal struct JpegStreamReader
private int _verticalSamplingMax = 1;
private bool _dnlMarkerExpected;
private bool _componentWithMappingTableExists;
private int[]? _widths;
private int[]? _heights;

public JpegStreamReader()
: this(null!)
Expand Down Expand Up @@ -99,6 +101,10 @@ internal readonly uint MaximumSampleValue
}
}

internal readonly int[] Widths => _widths!;

internal readonly int[] Heights => _heights!;

private readonly int SegmentBytesToRead => _segmentStartPosition + _segmentDataSize - Position;

internal readonly int GetMappingTableId(int componentIndex)
Expand Down Expand Up @@ -494,9 +500,29 @@ private void ReadStartOfFrameSegment()
SkipByte(); // Tqi = Quantization table destination selector (reserved for JPEG-LS, should be set to 0)
}

ComputeWidths();
ComputeHeights();
_state = State.ScanSection;
}

private void ComputeWidths()
{
_widths = new int[_componentCount];
for (int i = 0; i < _componentCount; i++)
{
_widths[i] = GetScanWidth(i);
}
}

private void ComputeHeights()
{
_heights = new int[_componentCount];
for (int i = 0; i < _componentCount; i++)
{
_heights[i] = GetScanHeight(i);
}
}

private void ReadApplicationDataSegment(JpegMarkerCode markerCode)
{
RaiseApplicationDataEvent(markerCode);
Expand Down
47 changes: 25 additions & 22 deletions src/ScanDecoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ internal ScanDecoder(FrameInfo frameInfo, JpegLSPresetCodingParameters presetCod

private readonly int PixelStride => FrameInfo.Width + 2;

internal int DecodeScan(ReadOnlyMemory<byte> source, Span<byte> destination, int stride)
internal int DecodeScan(ReadOnlyMemory<byte> source, Span<byte> destination, int stride, Span<int> widths, Span<int> heights)
{
Initialize(source);

Expand All @@ -61,11 +61,11 @@ internal int DecodeScan(ReadOnlyMemory<byte> source, Span<byte> destination, int

if (FrameInfo.BitsPerSample <= 8)
{
DecodeLines8Bit(destination, stride);
DecodeLines8Bit(destination, stride, widths, heights);
}
else
{
DecodeLines16Bit(destination, stride);
DecodeLines16Bit(destination, stride, widths);
}

EndScan();
Expand Down Expand Up @@ -352,7 +352,7 @@ private bool FillReadCacheOptimistic()
return true;
}

private void DecodeLines8Bit(Span<byte> destination, int stride)
private void DecodeLines8Bit(Span<byte> destination, int stride, Span<int> widths, Span<int> heights)
{
switch (CodingParameters.InterleaveMode)
{
Expand All @@ -361,7 +361,7 @@ private void DecodeLines8Bit(Span<byte> destination, int stride)
break;

case InterleaveMode.Line:
DecodeLines8BitInterleaveModeLine(destination, stride);
DecodeLines8BitInterleaveModeLine(destination, stride, widths, heights);
break;

case InterleaveMode.Sample:
Expand All @@ -382,7 +382,7 @@ private void DecodeLines8Bit(Span<byte> destination, int stride)
}
}

private void DecodeLines16Bit(Span<byte> destination, int stride)
private void DecodeLines16Bit(Span<byte> destination, int stride, Span<int> widths)
{
switch (CodingParameters.InterleaveMode)
{
Expand All @@ -391,7 +391,7 @@ private void DecodeLines16Bit(Span<byte> destination, int stride)
break;

case InterleaveMode.Line:
DecodeLines16BitInterleaveModeLine(destination, stride);
DecodeLines16BitInterleaveModeLine(destination, stride, widths);
break;

case InterleaveMode.Sample:
Expand Down Expand Up @@ -438,7 +438,7 @@ private void DecodeLines8BitInterleaveModeNone(Span<byte> destination, int strid
previousLine[FrameInfo.Width + 1] = previousLine[FrameInfo.Width];
currentLine[0] = previousLine[1];

DecodeSampleLine(previousLine, currentLine);
DecodeSampleLine(previousLine, currentLine, FrameInfo.Width);

CopyLineBufferToDestinationInterleaveNone(currentLine[1..], destination, FrameInfo.Width);

Expand Down Expand Up @@ -489,7 +489,7 @@ private void DecodeLines16BitInterleaveModeNone(Span<byte> destination, int stri
previousLine[FrameInfo.Width + 1] = previousLine[FrameInfo.Width];
currentLine[0] = previousLine[1];

DecodeSampleLine(previousLine, currentLine);
DecodeSampleLine(previousLine, currentLine, FrameInfo.Width);

CopyLineBufferToDestinationInterleaveNone(currentLine[1..], destination, FrameInfo.Width);

Expand All @@ -515,7 +515,7 @@ private void DecodeLines16BitInterleaveModeNone(Span<byte> destination, int stri
}
}

private void DecodeLines8BitInterleaveModeLine(Span<byte> destination, int stride)
private void DecodeLines8BitInterleaveModeLine(Span<byte> destination, int stride, Span<int> widths, Span<int> heights)
{
int pixelStride = FrameInfo.Width + 2;
int componentCount = FrameInfo.ComponentCount;
Expand Down Expand Up @@ -544,10 +544,13 @@ private void DecodeLines8BitInterleaveModeLine(Span<byte> destination, int strid
_scanCodec.RunIndex = runIndex[component];

// Initialize edge pixels used for prediction
previousLine[FrameInfo.Width + 1] = previousLine[FrameInfo.Width];
previousLine[widths[component] + 1] = previousLine[widths[component]];
currentLine[0] = previousLine[1];

DecodeSampleLine(previousLine, currentLine);
if (line + mcu < heights[component])
{
DecodeSampleLine(previousLine, currentLine, widths[component]);
}

runIndex[component] = _scanCodec.RunIndex;
currentLine = currentLine[pixelStride..];
Expand Down Expand Up @@ -580,7 +583,7 @@ private void DecodeLines8BitInterleaveModeLine(Span<byte> destination, int strid
}
}

private void DecodeLines16BitInterleaveModeLine(Span<byte> destination, int stride)
private void DecodeLines16BitInterleaveModeLine(Span<byte> destination, int stride, Span<int> widths)
{
int pixelStride = FrameInfo.Width + 2;
int componentCount = FrameInfo.ComponentCount;
Expand Down Expand Up @@ -612,7 +615,7 @@ private void DecodeLines16BitInterleaveModeLine(Span<byte> destination, int stri
previousLine[FrameInfo.Width + 1] = previousLine[FrameInfo.Width];
currentLine[0] = previousLine[1];

DecodeSampleLine(previousLine, currentLine);
DecodeSampleLine(previousLine, currentLine, widths[component]);

runIndex[component] = _scanCodec.RunIndex;
currentLine = currentLine[pixelStride..];
Expand Down Expand Up @@ -957,13 +960,13 @@ private readonly int QuantizeGradient(int di)
return _scanCodec.QuantizationLut[(_scanCodec.QuantizationLut.Length / 2) + di];
}

private void DecodeSampleLine(Span<byte> previousLine, Span<byte> currentLine)
private void DecodeSampleLine(Span<byte> previousLine, Span<byte> currentLine, int width)
{
int index = 1;
int rb = previousLine[0];
int rd = previousLine[index];

while (index <= FrameInfo.Width)
while (index <= width)
{
int ra = currentLine[index - 1];
int rc = rb;
Expand All @@ -974,7 +977,7 @@ private void DecodeSampleLine(Span<byte> previousLine, Span<byte> currentLine)
QuantizeGradient(rd - rb), QuantizeGradient(rb - rc), QuantizeGradient(rc - ra));
if (qs == 0)
{
index += DecodeRunMode(index, previousLine, currentLine);
index += DecodeRunMode(index, previousLine, currentLine, width);
rb = previousLine[index - 1];
rd = previousLine[index];
}
Expand All @@ -986,13 +989,13 @@ private void DecodeSampleLine(Span<byte> previousLine, Span<byte> currentLine)
}
}

private void DecodeSampleLine(Span<ushort> previousLine, Span<ushort> currentLine)
private void DecodeSampleLine(Span<ushort> previousLine, Span<ushort> currentLine, int width)
{
int index = 1;
int rb = previousLine[0];
int rd = previousLine[index];

while (index <= FrameInfo.Width)
while (index <= width)
{
int ra = currentLine[index - 1];
int rc = rb;
Expand Down Expand Up @@ -1236,14 +1239,14 @@ private int DecodeRegular(int qs, int predicted)
return Traits.ComputeReconstructedSample(correctedPrediction, errorValue);
}

private int DecodeRunMode(int startIndex, Span<byte> previousLine, Span<byte> currentLine)
private int DecodeRunMode(int startIndex, Span<byte> previousLine, Span<byte> currentLine, int width)
{
var ra = currentLine[startIndex - 1];

int runLength = DecodeRunPixels(ra, currentLine[startIndex..], FrameInfo.Width - (startIndex - 1));
int runLength = DecodeRunPixels(ra, currentLine[startIndex..], width - (startIndex - 1));
int endIndex = startIndex + runLength;

if (endIndex - 1 == FrameInfo.Width)
if (endIndex - 1 == width)
return endIndex - startIndex;

// Run interruption
Expand Down
6 changes: 6 additions & 0 deletions test/CharLS.Managed.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@
<None Update="conformance\t8nde3.jls">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="conformance\t8sse0.jls">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="conformance\t8sse3.jls">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="conformance\t16e0.jls">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Expand Down
20 changes: 20 additions & 0 deletions test/ComplianceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,26 @@ public void DecodeEncodeColor8BitInterleaveSampleNearLossless3()
DecodeEncodeFile("conformance/t8c2e3.jls", "conformance/test8.ppm");
}

////[Fact]
////public void DecodeEncodeColor8BitInterleaveLineLosslessSubSampled()
////{
//// // ISO 14495-1: official test image 7
//// //DecodeEncodeFile("conformance/t8sse0.jls", "conformance/test8.ppm");

//// var encodedSource = Util.ReadFile("conformance/t8sse0.jls");

//// JpegLSDecoder decoder = new(encodedSource);

//// var destination = new byte[decoder.GetDestinationSize()];
//// decoder.Decode(destination);

//// //JpegLSDecoder decoder = new(encodedSource);

//// //var referenceFile = Util.ReadAnymapReferenceFile(rawFilename, decoder.GetInterleaveMode(), decoder.FrameInfo);

//// //Util.TestCompliance(encodedSource, referenceFile.ImageData, checkEncode);
////}

[Fact]
public void DecodeEncodeColor8BitInterleaveNoneLosslessNonDefault()
{
Expand Down
38 changes: 19 additions & 19 deletions test/EncodeTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -439,31 +439,31 @@ public void EncodeSubSamplingInterleaveNone()
CheckOutput(component2, destination[(2 * 2 * 2)..], decoder, 1, 2 * 1);
}

[Fact]
public void EncodeSubSamplingInterleaveLine()
{
JpegLSEncoder encoder = new() { FrameInfo = new FrameInfo(2, 2, 8, 3), InterleaveMode = InterleaveMode.None };
////[Fact]
////public void EncodeSubSamplingInterleaveLine()
////{
//// JpegLSEncoder encoder = new() { FrameInfo = new FrameInfo(2, 2, 8, 3), InterleaveMode = InterleaveMode.None };

Memory<byte> encodedData = new byte[encoder.EstimatedDestinationSize];
encoder.Destination = encodedData;
//// Memory<byte> encodedData = new byte[encoder.EstimatedDestinationSize];
//// encoder.Destination = encodedData;

byte[] components = [24, 25, 26, 23, 0, 0, 22, 0, 0, 21, 0, 0];
//// byte[] components = [24, 25, 26, 23, 0, 0, 22, 0, 0, 21, 0, 0];

encoder.SetSamplingFactor(0, 2, 2);
encoder.SetSamplingFactor(1, 1, 1);
encoder.SetSamplingFactor(2, 1, 1);
encoder.InterleaveMode = InterleaveMode.Line;
encoder.Encode(components);
//// encoder.SetSamplingFactor(0, 2, 2);
//// encoder.SetSamplingFactor(1, 1, 1);
//// encoder.SetSamplingFactor(2, 1, 1);
//// encoder.InterleaveMode = InterleaveMode.Line;
//// encoder.Encode(components);

JpegLSDecoder decoder = new() { Source = encoder.EncodedData };
decoder.ReadHeader();
//// JpegLSDecoder decoder = new() { Source = encoder.EncodedData };
//// decoder.ReadHeader();

Span<byte> destination = new byte[decoder.GetDestinationSize()];
decoder.Decode(destination);
//// Span<byte> destination = new byte[decoder.GetDestinationSize()];
//// decoder.Decode(destination);

//CheckOutput(component0, destination, decoder, 1, 2 * 2);
//CheckOutput(component1And2, destination[(2 * 2)..], decoder, 1, 1 * 2);
}
//// //CheckOutput(component0, destination, decoder, 1, 2 * 2);
//// //CheckOutput(component1And2, destination[(2 * 2)..], decoder, 1, 1 * 2);
////}

[Fact]
public void EncodeSubSamplingInterleaveSample()
Expand Down
2 changes: 1 addition & 1 deletion test/PortableAnymapFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ public override string ReadLine()
byte b = (byte)current;
bytes.Add(b);
}
return Encoding.ASCII.GetString(bytes.ToArray());
return Encoding.ASCII.GetString([.. bytes]);
}

// Read works differently than the `Read()` method of a
Expand Down

0 comments on commit 84322f9

Please sign in to comment.