Skip to content

Commit 24bab64

Browse files
authored
Update README.md: add benchmark numbers (#45)
* Update README.md: add x86-64 benchmark numbers * Add improvements based on testing results * Sort properties in Directory.Build.props * Update README.md
1 parent 45728a2 commit 24bab64

File tree

11 files changed

+84
-51
lines changed

11 files changed

+84
-51
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file.
44

55
The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/).
66

7-
## [0.8.0 - 2024-8-21]
7+
## [0.8.0 - 2024-8-23]
88

99
### Added
1010

CharLSDotNet.sln

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CharLS.Managed.Test", "test
2323
EndProject
2424
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CharLS.Managed.Benchmark", "benchmark\CharLS.Managed.Benchmark.csproj", "{43E730B3-BCBC-40A8-8F32-72FC278300D5}"
2525
EndProject
26-
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{A9E95F06-F2ED-46F9-8AE7-9EBE15768205}"
26+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "samples", "{A9E95F06-F2ED-46F9-8AE7-9EBE15768205}"
2727
EndProject
2828
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Convert", "samples\Convert\Convert.csproj", "{601E8408-2608-403C-B1E6-E78244506CAB}"
2929
EndProject

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
<ChecksumAlgorithm>SHA256</ChecksumAlgorithm> <!-- Use Sha256 for checksums in PDBs (default is SHA1) -->
1717
<AccelerateBuildsInVisualStudio>true</AccelerateBuildsInVisualStudio><!-- Enable faster builds in Visual Studio 2022 17.5 and newer. -->
1818
<GenerateDocumentationFile>True</GenerateDocumentationFile>
19+
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
1920

2021
<!-- Version information -->
2122
<Version>0.8.0</Version>
@@ -27,7 +28,6 @@
2728
<!-- Build to a folder outside the source folders, making it easier to clean. -->
2829
<OutputPath>$(MSBuildThisFileDirectory)build\binaries\$(Configuration)\</OutputPath>
2930
<BaseIntermediateOutputPath>$(MSBuildThisFileDirectory)build\intermediates\$(MSBuildProjectName)\</BaseIntermediateOutputPath>
30-
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
3131

3232
<!-- Static Analysis -->
3333
<AnalysisLevel>latest-All</AnalysisLevel>

README.md

Lines changed: 61 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,41 +5,65 @@
55
[![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://github.com/team-charls/charls-dotnet/blob/main/LICENSE.md)
66
[![Build and Test](https://github.com/team-charls/charls-dotnet/actions/workflows/dotnet.yml/badge.svg)](https://github.com/team-charls/charls-dotnet/actions/workflows/dotnet.yml)
77
[![Coverage Status](https://coveralls.io/repos/github/team-charls/charls-dotnet/badge.svg)](https://coveralls.io/github/team-charls/charls-dotnet)
8+
[![NuGet](https://img.shields.io/nuget/v/CharLS.Managed.svg)](https://www.nuget.org/packages/CharLS.Managed)
89

910
CharLS .NET is a C# JPEG-LS library implementation.
1011
JPEG-LS (ISO-14495-1) is a lossless/near-lossless compression standard for continuous-tone images.
1112

12-
## IMPORTANT : WORK IN PROGRESS
13-
14-
This project is considered work in progress and NOT ready for general use. The following functionality is planned / implemented:
15-
16-
* [X] Decode 8 bit images, interleave mode: none
17-
* [X] Decode 8 bit images, interleave mode: line
18-
* [X] Decode 8 bit images, interleave mode: sample
19-
* [X] Decode 8 bit images, nearLossless != 0. interleave mode: none, line, sample
20-
* [X] Decode 16 bit images, interleave mode: none
21-
* [X] Decode 16 bit images, interleave mode: line
22-
* [X] Decode 16 bit images, interleave mode: sample
23-
* [X] Encode 8 bit images, interleave mode: none
24-
* [X] Encode 8 bit images, interleave mode: line
25-
* [X] Encode 8 bit images, interleave mode: sample
26-
* [X] Encode\Decode 8 bit images HP color transformation
27-
* [X] Encode 16 bit images, interleave mode: none
28-
* [X] Encode 16 bit images, interleave mode: line
29-
* [X] Encode 16 bit images, interleave mode: sample
30-
* [X] Encode\Decode 16 bit images HP color transformation
31-
* [X] Encode\Decode 4 component images
32-
* [X] Support for SPIFF Header
33-
* [ ] General code clean-up
34-
* [ ] Good code coverage
35-
* [ ] Performance tuning
36-
* [ ] Release NuGet package
37-
3813
## Features
3914

4015
* .NET 8.0 class library.
4116
* Support for the .NET platforms: Windows, Linux and macOS.
4217

18+
## Performance
19+
20+
A couple of benchmarks have been executed to assist to decide which codec to use.
21+
The following codecs were measured:
22+
23+
|Codec |Version|Release date|Description|
24+
|------------ |-------|------------|----------------------------------------------|
25+
|CharLS.Managed| 0.8.0 |2024-08-23 |C# implementation |
26+
|CharLS.Native | 3.2.0 |2023-09-24 |C# wrapper around C++ implementation |
27+
|cscharls | 0.1.1 |2017-04-24 |C# implementation |
28+
|charls-js | 2.1.1 |2021-10-07 |WebAssembly implementation based on C++ source|
29+
30+
and the following test images were used:
31+
32+
|Image name |Width |Height|Bits per sample|Components|Description |
33+
|------------ |------:|-----:|--------------:|---------:|--------------------------|
34+
|Tulips | 512| 512| 8| 1|Monochrome image of tulips|
35+
|MG1 | 3064| 4664| 12| 1|Monochrome medical image |
36+
|Delta E | 3072| 2048| 8| 3|Artificial RGB image |
37+
38+
The benchmarks were performed on 2 hardware platforms: x86 and ARM64.
39+
The column 'NEAR' defines the allowed error, 0 means lossless encoding.
40+
The column 'ILV' defines the interleave mode used to encode the image.
41+
42+
### x86-64 Platform
43+
44+
Characteristics of the test environment: AMD Ryzen 9 5950X, .NET 8.0.8 (X64 RyuJIT AVX2)
45+
WebAssembly engine: Chrome V8 12.8.374.21
46+
47+
|Operation |NEAR|ILV |CharLS.Managed|CharLS.Native|cscharls |charls-js|
48+
|---------------|---:|------|-------------:|------------:|--------:|--------:|
49+
|Decode Tulips | 0|None | 5.0 ms| 3.6 ms| 10.4 ms| 5.6 ms|
50+
|Decode MG1 | 0|None | 292.3 ms| 205.0 ms| 676.3 ms| 335.2 ms|
51+
|Decode Delta E | 0|Sample| 80.0 ms| 89.4 ms| -| 89.5 ms|
52+
|Encode Tulips | 0|None | 7.1 ms| 4.7 ms| 11.8 ms| -|
53+
|Encode MG1 | 0|None | 404.3 ms| 256.3 ms| 695.8 ms| -|
54+
55+
## Arm64 Platform
56+
57+
Characteristics of the test environment: Snapdragon Compute Platform, .NET 8.0.8 (Arm64 RyuJIT AdvSIMD)
58+
WebAssembly engine: Chrome V8 12.8.374.21
59+
60+
|Operation |NEAR|ILV |CharLS.Managed|CharLS.Native|cscharls |charls-js|
61+
|---------------|---:|------|-------------:|------------:|--------:|--------:|
62+
|Decode Tulips | 0|None | 7.2 ms| 4.7 ms| 14.3 ms| 10.5 ms|
63+
|Decode MG1 | 0|None | 431.7 ms| 261.8 ms|1019.4 ms| 542.1 ms|
64+
|Encode Tulips | 0|None | 9.6 ms| 5.5 ms| 15.7 ms| -|
65+
|Encode MG1 | 0|None | 564.0 ms| 318.6 ms|1017.2 ms| -|
66+
4367
## How to use
4468

4569
CharLS.Managed can be added to your C# project using the dotnet command line or the NuGet Package Manager in Visual Studio.
@@ -62,12 +86,16 @@ A sample application is included in the GitHub repository that demonstrates how
6286
git clone https://github.com/team-charls/charls-dotnet.git
6387
```
6488

65-
* Use the .NET 8.0 CLI or Visual Studio 2022 (v17.10 or newer) to build the solution file CharLSDotNet.sln. For example: `dotnet build && dotnet test && dotnet publish` to build the nuget package.
89+
* Use the .NET 8.0 CLI or Visual Studio 2022 (v17.11 or newer) to build the solution file CharLSDotNet.sln.
90+
For example: `dotnet build && dotnet test && dotnet publish` to build the NuGet package.
91+
Building can be done on all supported .NET SDK platforms: Windows, Linux or macOS
6692

67-
### Building Windows DLLs and code signing all components
93+
### Code signing the assembly and the NuGet package
6894

69-
Building the NuGet package with signed Windows DLLs can only be done on the Window platform with Visual Studio 2022 or with Build tools for Visual Studio 2022.
70-
To support code signing with a code signing certificate, stored on a smart card, a Windows command file is available: `create-signed-nuget-package.cmd`.
95+
Building the NuGet package with a signed assembly DLL and NuGet package can only be done
96+
on the Window platform with Visual Studio 2022 or with Build tools for Visual Studio 2022.
97+
To support code signing with a code signing certificate, stored on a smart card, a
98+
Windows command file is available: `create-signed-nuget-package.cmd`.
7199
Instructions:
72100

73101
* Open a Visual Studio Developer Command Prompt
@@ -76,8 +104,9 @@ Instructions:
76104
* Execute the command `create-signed-nuget-package.cmd certificate-thumb-print time-stamp-url`
77105
The certificate thumbprint and time stamp URL arguments are depending on the used code signing certificate.
78106

79-
All DLLs and the NuGet package itself will be signed.
107+
All assembly DLLs and the NuGet package itself will be signed.
80108

81109
## About the JPEG-LS image compression standard
82110

83-
More information about JPEG-LS can be found in the [README](https://github.com/team-charls/charls/blob/master/README.md) from the C++ CharLS project.
111+
More information about JPEG-LS can be found in the [README](https://github.com/team-charls/charls/blob/master/README.md)
112+
from the C++ CharLS project.

src/ErrorCode.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ public enum ErrorCode
246246
InvalidArgumentColorTransformation = 109,
247247

248248
/// <summary>
249-
/// The argument for the size parameter is outside the valid range.
249+
/// The size of a buffer parameter is outside the valid range.
250250
/// </summary>
251251
InvalidArgumentSize = 110,
252252

src/JpegLSDecoder.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -362,15 +362,16 @@ public void Decode(Span<byte> destination, int stride = AutoCalculateStride)
362362
}
363363
else
364364
{
365-
if (stride < minimumStride)
366-
throw new ArgumentException("stride < minimumStride", nameof(stride));
365+
ThrowHelper.ThrowArgumentExceptionIfFalse(stride >= minimumStride, nameof(stride), ErrorCode.InvalidArgumentStride);
367366
}
368367

369368
// Compute the layout of the destination buffer.
370369
int bytesPerPlane = FrameInfo.Width * FrameInfo.Height * BitToByteCount(FrameInfo.BitsPerSample);
371370
int planeCount = _reader.InterleaveMode == InterleaveMode.None ? FrameInfo.ComponentCount : 1;
372371
int minimumDestinationSize = (bytesPerPlane * planeCount) - (stride - minimumStride);
373372

373+
ThrowHelper.ThrowArgumentExceptionIfFalse(destination.Length >= minimumDestinationSize, nameof(destination), ErrorCode.InvalidArgumentSize);
374+
374375
if (destination.Length < minimumDestinationSize)
375376
throw new ArgumentException("destination buffer too small", nameof(destination));
376377

src/JpegLSEncoder.cs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,28 +42,31 @@ public JpegLSEncoder()
4242
/// <param name="height">The height of the image to encode.</param>
4343
/// <param name="bitsPerSample">The bits per sample of the image to encode.</param>
4444
/// <param name="componentCount">The component count of the image to encode.</param>
45-
/// <param name="allocateDestination">Flag to control if destination buffer should be allocated or not.</param>
46-
/// <param name="extraBytes">Number of extra destination bytes. Comments and tables are not included in the estimate.</param>
45+
/// <param name="interleaveMode">The interleave mode of the image to encode (default None).</param>
46+
/// <param name="allocateDestination">Flag to control if destination buffer should be allocated or not (default true).</param>
47+
/// <param name="extraBytes">Number of extra destination bytes. Comments and tables are not included in the standard estimate (default 0).</param>
4748
/// <exception cref="ArgumentOutOfRangeException">Thrown when one of the arguments is invalid.</exception>
4849
/// <exception cref="OutOfMemoryException">Thrown when memory allocation for the destination buffer fails.</exception>
49-
public JpegLSEncoder(int width, int height, int bitsPerSample, int componentCount, bool allocateDestination = true, int extraBytes = 0)
50-
: this(new FrameInfo(width, height, bitsPerSample, componentCount), allocateDestination, extraBytes)
50+
public JpegLSEncoder(int width, int height, int bitsPerSample, int componentCount, InterleaveMode interleaveMode = InterleaveMode.None, bool allocateDestination = true, int extraBytes = 0)
51+
: this(new FrameInfo(width, height, bitsPerSample, componentCount), interleaveMode, allocateDestination, extraBytes)
5152
{
5253
}
5354

5455
/// <summary>
5556
/// Initializes a new instance of the <see cref="JpegLSEncoder"/> class.
5657
/// </summary>
5758
/// <param name="frameInfo">The frameInfo of the image to encode.</param>
58-
/// <param name="allocateDestination">Flag to control if destination buffer should be allocated or not.</param>
59-
/// <param name="extraBytes">Number of extra destination bytes. Comments and tables are not included in the estimate.</param>
59+
/// <param name="interleaveMode">The interleave mode of the image to encode (default None).</param>
60+
/// <param name="allocateDestination">Flag to control if destination buffer should be allocated or not (default true).</param>
61+
/// <param name="extraBytes">Number of extra destination bytes. Comments and tables are not included in the standard estimate (default 0).</param>
6062
/// <exception cref="ArgumentOutOfRangeException">Thrown when one of the arguments is invalid.</exception>
6163
/// <exception cref="OutOfMemoryException">Thrown when memory allocation for the destination buffer fails.</exception>
62-
public JpegLSEncoder(FrameInfo frameInfo, bool allocateDestination = true, int extraBytes = 0)
64+
public JpegLSEncoder(FrameInfo frameInfo, InterleaveMode interleaveMode = InterleaveMode.None, bool allocateDestination = true, int extraBytes = 0)
6365
{
6466
ArgumentOutOfRangeException.ThrowIfNegative(extraBytes);
6567

6668
FrameInfo = frameInfo;
69+
InterleaveMode = interleaveMode;
6770

6871
if (allocateDestination)
6972
{
@@ -489,7 +492,7 @@ public void CreateAbbreviatedFormat()
489492
/// </summary>
490493
/// <param name="source">Source pixel data that needs to be encoded.</param>
491494
/// <param name="frameInfo">Frame info object that describes the pixel data.</param>
492-
/// <param name="interleaveMode">Defines how the the pixel data should be encoded.</param>
495+
/// <param name="interleaveMode">Defines how the pixel data should be encoded.</param>
493496
/// <param name="encodingOptions">Defines several options how to encode the pixel data.</param>
494497
/// <param name="stride">The stride to use; byte count to the next pixel row. Pass 0 (AutoCalculateStride) for the default.</param>
495498
public static Memory<byte> Encode(

src/ThrowHelper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ private static string GetErrorMessage(ErrorCode errorCode)
144144
ErrorCode.InvalidArgumentNearLossless => "The near lossless argument is outside the range [0, min(255, MAXVAL/2)]",
145145
ErrorCode.InvalidArgumentPresetCodingParameters => "The argument for the JPEG-LS preset coding parameters is not valid",
146146
ErrorCode.InvalidArgumentColorTransformation => "The argument for the color component is not (None, Hp1, Hp2, Hp3) or invalid in combination with component count",
147-
ErrorCode.InvalidArgumentSize => "The passed size is outside the valid range",
147+
ErrorCode.InvalidArgumentSize => "The passed size of a buffer is outside the valid range",
148148
ErrorCode.InvalidArgumentStride => "The stride argument does not match with the frame info and buffer size",
149149
ErrorCode.InvalidArgumentEncodingOptions => "The encoding options argument has an invalid value",
150150
_ => string.Empty

src/nuget-release-notes.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
1.1.0-alpha.1
2-
- Initial release
1+
0.8.0
2+
- Initial release.

test/JpegLSDecoderTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ static void EventHandler(object? sender, CommentEventArgs e)
444444
[Fact]
445445
public void ApplicationDataHandlerReceivesApplicationDataBytes()
446446
{
447-
JpegLSEncoder encoder = new(1, 1, 8, 1, true, 100);
447+
JpegLSEncoder encoder = new(1, 1, 8, 1, InterleaveMode.None, true, 100);
448448

449449
var applicationData1 = new byte[] { 1, 2, 3, 4 };
450450
encoder.WriteApplicationData(12, applicationData1);

0 commit comments

Comments
 (0)