Skip to content

Commit a7fd681

Browse files
committed
Rebase and update to .NET SDK 9.0
1 parent f54bab1 commit a7fd681

File tree

8 files changed

+99
-43
lines changed

8 files changed

+99
-43
lines changed

benchmark/CharLS.Managed.Benchmark.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
1515
<!--
1616
CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
17-
CA1515: Consider making public types internal
17+
CA1515: types can be made internal (Benchmark framework requires public types).
1818
-->
1919
<NoWarn>$(NoWarn),1591,CA1515</NoWarn>
2020
</PropertyGroup>

exclusion.dic

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ opto
1010
palletised
1111
glimit
1212
Golomb
13+
Errval

src/JpegLSDecoder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ public void Decode(Span<byte> destination, int stride = AutoCalculateStride)
375375
{
376376
int scanStride = CheckStrideAndDestinationLength(destination.Length, stride);
377377
_scanDecoder = new ScanDecoder(_reader.ScanFrameInfo, _reader.GetValidatedPresetCodingParameters(), _reader.GetCodingParameters());
378-
int bytesRead = _scanDecoder.DecodeScan(_reader.RemainingSource(), destination, scanStride);
378+
int bytesRead = _scanDecoder.DecodeScan(_reader.RemainingSource(), destination, scanStride, _reader.Widths, _reader.Heights);
379379
_reader.AdvancePosition(bytesRead);
380380

381381
component += _reader.ScanComponentCount;

src/JpegStreamReader.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ internal struct JpegStreamReader
3030
private int _verticalSamplingMax = 1;
3131
private bool _dnlMarkerExpected;
3232
private bool _componentWithMappingTableExists;
33+
private int[]? _widths;
34+
private int[]? _heights;
3335

3436
public JpegStreamReader()
3537
: this(null!)
@@ -99,6 +101,10 @@ internal readonly uint MaximumSampleValue
99101
}
100102
}
101103

104+
internal readonly int[] Widths => _widths!;
105+
106+
internal readonly int[] Heights => _heights!;
107+
102108
private readonly int SegmentBytesToRead => _segmentStartPosition + _segmentDataSize - Position;
103109

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

503+
ComputeWidths();
504+
ComputeHeights();
497505
_state = State.ScanSection;
498506
}
499507

508+
private void ComputeWidths()
509+
{
510+
_widths = new int[_componentCount];
511+
for (int i = 0; i < _componentCount; i++)
512+
{
513+
_widths[i] = GetScanWidth(i);
514+
}
515+
}
516+
517+
private void ComputeHeights()
518+
{
519+
_heights = new int[_componentCount];
520+
for (int i = 0; i < _componentCount; i++)
521+
{
522+
_heights[i] = GetScanHeight(i);
523+
}
524+
}
525+
500526
private void ReadApplicationDataSegment(JpegMarkerCode markerCode)
501527
{
502528
RaiseApplicationDataEvent(markerCode);

src/ScanDecoder.cs

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ internal ScanDecoder(FrameInfo frameInfo, JpegLSPresetCodingParameters presetCod
5252

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

55-
internal int DecodeScan(ReadOnlyMemory<byte> source, Span<byte> destination, int stride)
55+
internal int DecodeScan(ReadOnlyMemory<byte> source, Span<byte> destination, int stride, Span<int> widths, Span<int> heights)
5656
{
5757
Initialize(source);
5858

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

6262
if (FrameInfo.BitsPerSample <= 8)
6363
{
64-
DecodeLines8Bit(destination, stride);
64+
DecodeLines8Bit(destination, stride, widths, heights);
6565
}
6666
else
6767
{
68-
DecodeLines16Bit(destination, stride);
68+
DecodeLines16Bit(destination, stride, widths);
6969
}
7070

7171
EndScan();
@@ -352,7 +352,7 @@ private bool FillReadCacheOptimistic()
352352
return true;
353353
}
354354

355-
private void DecodeLines8Bit(Span<byte> destination, int stride)
355+
private void DecodeLines8Bit(Span<byte> destination, int stride, Span<int> widths, Span<int> heights)
356356
{
357357
switch (CodingParameters.InterleaveMode)
358358
{
@@ -361,7 +361,7 @@ private void DecodeLines8Bit(Span<byte> destination, int stride)
361361
break;
362362

363363
case InterleaveMode.Line:
364-
DecodeLines8BitInterleaveModeLine(destination, stride);
364+
DecodeLines8BitInterleaveModeLine(destination, stride, widths, heights);
365365
break;
366366

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

385-
private void DecodeLines16Bit(Span<byte> destination, int stride)
385+
private void DecodeLines16Bit(Span<byte> destination, int stride, Span<int> widths)
386386
{
387387
switch (CodingParameters.InterleaveMode)
388388
{
@@ -391,7 +391,7 @@ private void DecodeLines16Bit(Span<byte> destination, int stride)
391391
break;
392392

393393
case InterleaveMode.Line:
394-
DecodeLines16BitInterleaveModeLine(destination, stride);
394+
DecodeLines16BitInterleaveModeLine(destination, stride, widths);
395395
break;
396396

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

441-
DecodeSampleLine(previousLine, currentLine);
441+
DecodeSampleLine(previousLine, currentLine, FrameInfo.Width);
442442

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

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

492-
DecodeSampleLine(previousLine, currentLine);
492+
DecodeSampleLine(previousLine, currentLine, FrameInfo.Width);
493493

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

@@ -515,7 +515,7 @@ private void DecodeLines16BitInterleaveModeNone(Span<byte> destination, int stri
515515
}
516516
}
517517

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

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

550-
DecodeSampleLine(previousLine, currentLine);
550+
if (line + mcu < heights[component])
551+
{
552+
DecodeSampleLine(previousLine, currentLine, widths[component]);
553+
}
551554

552555
runIndex[component] = _scanCodec.RunIndex;
553556
currentLine = currentLine[pixelStride..];
@@ -580,7 +583,7 @@ private void DecodeLines8BitInterleaveModeLine(Span<byte> destination, int strid
580583
}
581584
}
582585

583-
private void DecodeLines16BitInterleaveModeLine(Span<byte> destination, int stride)
586+
private void DecodeLines16BitInterleaveModeLine(Span<byte> destination, int stride, Span<int> widths)
584587
{
585588
int pixelStride = FrameInfo.Width + 2;
586589
int componentCount = FrameInfo.ComponentCount;
@@ -612,7 +615,7 @@ private void DecodeLines16BitInterleaveModeLine(Span<byte> destination, int stri
612615
previousLine[FrameInfo.Width + 1] = previousLine[FrameInfo.Width];
613616
currentLine[0] = previousLine[1];
614617

615-
DecodeSampleLine(previousLine, currentLine);
618+
DecodeSampleLine(previousLine, currentLine, widths[component]);
616619

617620
runIndex[component] = _scanCodec.RunIndex;
618621
currentLine = currentLine[pixelStride..];
@@ -957,13 +960,13 @@ private readonly int QuantizeGradient(int di)
957960
return _scanCodec.QuantizationLut[(_scanCodec.QuantizationLut.Length / 2) + di];
958961
}
959962

960-
private void DecodeSampleLine(Span<byte> previousLine, Span<byte> currentLine)
963+
private void DecodeSampleLine(Span<byte> previousLine, Span<byte> currentLine, int width)
961964
{
962965
int index = 1;
963966
int rb = previousLine[0];
964967
int rd = previousLine[index];
965968

966-
while (index <= FrameInfo.Width)
969+
while (index <= width)
967970
{
968971
int ra = currentLine[index - 1];
969972
int rc = rb;
@@ -974,7 +977,7 @@ private void DecodeSampleLine(Span<byte> previousLine, Span<byte> currentLine)
974977
QuantizeGradient(rd - rb), QuantizeGradient(rb - rc), QuantizeGradient(rc - ra));
975978
if (qs == 0)
976979
{
977-
index += DecodeRunMode(index, previousLine, currentLine);
980+
index += DecodeRunMode(index, previousLine, currentLine, width);
978981
rb = previousLine[index - 1];
979982
rd = previousLine[index];
980983
}
@@ -986,13 +989,13 @@ private void DecodeSampleLine(Span<byte> previousLine, Span<byte> currentLine)
986989
}
987990
}
988991

989-
private void DecodeSampleLine(Span<ushort> previousLine, Span<ushort> currentLine)
992+
private void DecodeSampleLine(Span<ushort> previousLine, Span<ushort> currentLine, int width)
990993
{
991994
int index = 1;
992995
int rb = previousLine[0];
993996
int rd = previousLine[index];
994997

995-
while (index <= FrameInfo.Width)
998+
while (index <= width)
996999
{
9971000
int ra = currentLine[index - 1];
9981001
int rc = rb;
@@ -1236,14 +1239,14 @@ private int DecodeRegular(int qs, int predicted)
12361239
return Traits.ComputeReconstructedSample(correctedPrediction, errorValue);
12371240
}
12381241

1239-
private int DecodeRunMode(int startIndex, Span<byte> previousLine, Span<byte> currentLine)
1242+
private int DecodeRunMode(int startIndex, Span<byte> previousLine, Span<byte> currentLine, int width)
12401243
{
12411244
var ra = currentLine[startIndex - 1];
12421245

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

1246-
if (endIndex - 1 == FrameInfo.Width)
1249+
if (endIndex - 1 == width)
12471250
return endIndex - startIndex;
12481251

12491252
// Run interruption

test/CharLS.Managed.Test.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@
6363
<None Update="conformance\t8nde3.jls">
6464
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
6565
</None>
66+
<None Update="conformance\t8sse0.jls">
67+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
68+
</None>
69+
<None Update="conformance\t8sse3.jls">
70+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
71+
</None>
6672
<None Update="conformance\t16e0.jls">
6773
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
6874
</None>

test/ComplianceTest.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,26 @@ public void DecodeEncodeColor8BitInterleaveSampleNearLossless3()
4747
DecodeEncodeFile("conformance/t8c2e3.jls", "conformance/test8.ppm");
4848
}
4949

50+
////[Fact]
51+
////public void DecodeEncodeColor8BitInterleaveLineLosslessSubSampled()
52+
////{
53+
//// // ISO 14495-1: official test image 7
54+
//// //DecodeEncodeFile("conformance/t8sse0.jls", "conformance/test8.ppm");
55+
56+
//// var encodedSource = Util.ReadFile("conformance/t8sse0.jls");
57+
58+
//// JpegLSDecoder decoder = new(encodedSource);
59+
60+
//// var destination = new byte[decoder.GetDestinationSize()];
61+
//// decoder.Decode(destination);
62+
63+
//// //JpegLSDecoder decoder = new(encodedSource);
64+
65+
//// //var referenceFile = Util.ReadAnymapReferenceFile(rawFilename, decoder.GetInterleaveMode(), decoder.FrameInfo);
66+
67+
//// //Util.TestCompliance(encodedSource, referenceFile.ImageData, checkEncode);
68+
////}
69+
5070
[Fact]
5171
public void DecodeEncodeColor8BitInterleaveNoneLosslessNonDefault()
5272
{

test/EncodeTest.cs

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -439,31 +439,31 @@ public void EncodeSubSamplingInterleaveNone()
439439
CheckOutput(component2, destination[(2 * 2 * 2)..], decoder, 1, 2 * 1);
440440
}
441441

442-
[Fact]
443-
public void EncodeSubSamplingInterleaveLine()
444-
{
445-
JpegLSEncoder encoder = new() { FrameInfo = new FrameInfo(2, 2, 8, 3), InterleaveMode = InterleaveMode.None };
442+
////[Fact]
443+
////public void EncodeSubSamplingInterleaveLine()
444+
////{
445+
//// JpegLSEncoder encoder = new() { FrameInfo = new FrameInfo(2, 2, 8, 3), InterleaveMode = InterleaveMode.None };
446446

447-
Memory<byte> encodedData = new byte[encoder.EstimatedDestinationSize];
448-
encoder.Destination = encodedData;
447+
//// Memory<byte> encodedData = new byte[encoder.EstimatedDestinationSize];
448+
//// encoder.Destination = encodedData;
449449

450-
byte[] components = [24, 25, 26, 23, 0, 0, 22, 0, 0, 21, 0, 0];
450+
//// byte[] components = [24, 25, 26, 23, 0, 0, 22, 0, 0, 21, 0, 0];
451451

452-
encoder.SetSamplingFactor(0, 2, 2);
453-
encoder.SetSamplingFactor(1, 1, 1);
454-
encoder.SetSamplingFactor(2, 1, 1);
455-
encoder.InterleaveMode = InterleaveMode.Line;
456-
encoder.Encode(components);
452+
//// encoder.SetSamplingFactor(0, 2, 2);
453+
//// encoder.SetSamplingFactor(1, 1, 1);
454+
//// encoder.SetSamplingFactor(2, 1, 1);
455+
//// encoder.InterleaveMode = InterleaveMode.Line;
456+
//// encoder.Encode(components);
457457

458-
JpegLSDecoder decoder = new() { Source = encoder.EncodedData };
459-
decoder.ReadHeader();
458+
//// JpegLSDecoder decoder = new() { Source = encoder.EncodedData };
459+
//// decoder.ReadHeader();
460460

461-
Span<byte> destination = new byte[decoder.GetDestinationSize()];
462-
decoder.Decode(destination);
461+
//// Span<byte> destination = new byte[decoder.GetDestinationSize()];
462+
//// decoder.Decode(destination);
463463

464-
//CheckOutput(component0, destination, decoder, 1, 2 * 2);
465-
//CheckOutput(component1And2, destination[(2 * 2)..], decoder, 1, 1 * 2);
466-
}
464+
//// //CheckOutput(component0, destination, decoder, 1, 2 * 2);
465+
//// //CheckOutput(component1And2, destination[(2 * 2)..], decoder, 1, 1 * 2);
466+
////}
467467

468468
[Fact]
469469
public void EncodeSubSamplingInterleaveSample()

0 commit comments

Comments
 (0)