Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable all JpegLSDecoderTest unit tests #30

Merged
merged 1 commit into from
Aug 14, 2024
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
1 change: 1 addition & 0 deletions CharLSDotNet.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=CheckNamespace/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ParameterOnlyUsedForPreconditionCheck_002ELocal/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=FF/@EntryIndexedValue">FF</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HP/@EntryIndexedValue">HP</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=LS/@EntryIndexedValue">LS</s:String>
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ This project is considered work in progress and NOT ready for general use. The f
* [X] Encode 16 bit images, interleave mode: sample
* [X] Encode\Decode 16 bit images HP color transformation
* [X] Encode\Decode 4 component images
* [ ] Support for SPIFF Header
* [X] Support for SPIFF Header
* [ ] General code clean-up
* [ ] Good code coverage
* [ ] Performance tuning
Expand Down
12 changes: 11 additions & 1 deletion src/ErrorCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,20 @@ public enum ErrorCode
RestartMarkerNotFound = 26,

/// <summary>
/// TODO
/// This error is returned when an event handler threw an exception.
/// </summary>
CallbackFailed = 27,

/// <summary>
/// This error is returned when the End of Image (EOI) marker could not be found.
/// </summary>
EndOfImageMarkerNotFound = 28,

/// <summary>
/// This error is returned when the SPIFF header is invalid.
/// </summary>
InvalidSpiffHeader = 29,

/// <summary>
/// The argument for the width parameter is outside the range [1, 2147483647].
/// </summary>
Expand Down
96 changes: 70 additions & 26 deletions src/JpegLSDecoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace CharLS.Managed;
public sealed class JpegLSDecoder
{
private FrameInfo? _frameInfo;
private readonly JpegStreamReader _reader = new();
private readonly JpegStreamReader _reader;

private enum State
{
Expand All @@ -25,26 +25,37 @@ private enum State

private State _state = State.Initial;

/// <summary>
/// Occurs when a comment (COM segment) is read.
/// </summary>
public event EventHandler<CommentEventArgs>? Comment
{
add { _reader.Comment += value; }
remove { _reader.Comment -= value; }
}

/// <summary>
/// Initializes a new instance of the <see cref="JpegLSDecoder"/> class.
/// </summary>
public JpegLSDecoder()
{
_reader = new JpegStreamReader(this);
}

/// <summary>
/// Initializes a new instance of the <see cref="JpegLSDecoder"/> class.
/// </summary>
/// <param name="source">The buffer containing the encoded data.</param>
/// <param name="readHeader">When true the header from the JPEG-LS stream is parsed.</param>
/// <param name="readHeader">When true the header from the JPEG-LS stream is read parsed.</param>
/// <param name="tryReadSpiffHeader">When true the SPIFF header from the JPEG-LS stream is read and parsed.</param>
/// <exception cref="InvalidDataException">Thrown when the JPEG-LS stream is not valid.</exception>
public JpegLSDecoder(ReadOnlyMemory<byte> source, bool readHeader = true)
public JpegLSDecoder(ReadOnlyMemory<byte> source, bool readHeader = true, bool tryReadSpiffHeader = true)
: this()
{
Source = source;
if (readHeader)
{
ReadHeader();
ReadHeader(tryReadSpiffHeader);
}
}

Expand Down Expand Up @@ -86,7 +97,7 @@ public ReadOnlyMemory<byte> Source
/// <value>
/// The frame information of the parsed JPEG-LS image.
/// </value>
/// <exception cref="InvalidOperationException">Thrown when this property is used before <see cref="ReadHeader()"/>.</exception>
/// <exception cref="InvalidOperationException">Thrown when this property is used before <see cref="ReadHeader(bool)"/>.</exception>
public FrameInfo FrameInfo => _reader.FrameInfo ?? throw new InvalidOperationException("Incorrect state. ReadHeader has not called.");

/// <summary>
Expand All @@ -98,7 +109,7 @@ public ReadOnlyMemory<byte> Source
/// <value>
/// The near lossless parameter. A value of 0 means that the image is lossless encoded.
/// </value>
/// <exception cref="InvalidOperationException">Thrown when this property is used before <see cref="ReadHeader()"/>.</exception>
/// <exception cref="InvalidOperationException">Thrown when this property is used before <see cref="ReadHeader(bool)"/>.</exception>
public int NearLossless
{
get
Expand All @@ -115,7 +126,7 @@ public int NearLossless
/// Property should be obtained after calling <see cref="ReadHeader"/>".
/// </remarks>
/// <returns>The result of the operation: success or a failure code.</returns>
/// <exception cref="InvalidOperationException">Thrown when this property is used before <see cref="ReadHeader()"/>.</exception>
/// <exception cref="InvalidOperationException">Thrown when this property is used before <see cref="ReadHeader(bool)"/>.</exception>
public InterleaveMode InterleaveMode
{
get
Expand All @@ -131,7 +142,7 @@ public InterleaveMode InterleaveMode
/// <value>
/// The preset coding parameters.
/// </value>
/// <exception cref="InvalidOperationException">Thrown when this property is used before <see cref="ReadHeader()"/>.</exception>
/// <exception cref="InvalidOperationException">Thrown when this property is used before <see cref="ReadHeader(bool)"/>.</exception>
public JpegLSPresetCodingParameters PresetCodingParameters
{
get
Expand All @@ -158,7 +169,7 @@ public ColorTransformation ColorTransformation
/// <param name="stride">The stride to use; byte count to the next pixel row. Pass 0 for the default.</param>
/// <returns>The size of the destination buffer in bytes.</returns>
/// <exception cref="OverflowException">When the required destination size doesn't fit in an int.</exception>
/// <exception cref="InvalidOperationException">Thrown when this method is called before <see cref="ReadHeader()"/>.</exception>
/// <exception cref="InvalidOperationException">Thrown when this method is called before <see cref="ReadHeader(bool)"/>.</exception>
public int GetDestinationSize(int stride = 0)
{
if (_state < State.HeaderRead)
Expand All @@ -185,22 +196,63 @@ public int GetDestinationSize(int stride = 0)
}
}

/// <summary>
/// Reads the SPIFF (Still Picture Interchange File Format) header.
/// </summary>
/// <param name="spiffHeader">The header or null when no valid header was found.</param>
/// <returns>true if a SPIFF header was present and could be read.</returns>
/// <exception cref="InvalidDataException">Thrown when the JPEG-LS stream is not valid.</exception>
public bool TryReadSpiffHeader(out SpiffHeader? spiffHeader)
{
ThrowHelper.ThrowInvalidOperationIfFalse(_state == State.SourceSet);
_reader.ReadHeader(true);

spiffHeader = _reader.SpiffHeader;
if (spiffHeader == null)
{
_state = State.SpiffHeaderNotFound;
return false;
}

_state = State.SpiffHeaderRead;
return true;
}

/// <summary>
/// Validates a SPIFF header with the FrameInfo.
/// </summary>
/// <param name="spiffHeader">Reference to a SPIFF header that will be validated.</param>
/// <exception cref="InvalidDataException">Thrown when the SPIFF header is not valid.</exception>
public void ValidateSpiffHeader(SpiffHeader spiffHeader)
{
ThrowHelper.ThrowInvalidOperationIfFalse(_state >= State.HeaderRead);
if (!spiffHeader.IsValid(FrameInfo))
ThrowHelper.ThrowInvalidDataException(ErrorCode.InvalidSpiffHeader);
}

/// <summary>
/// Reads the header of the JPEG-LS stream.
/// After calling this method, the informational properties can be obtained.
/// </summary>
/// <exception cref="InvalidDataException">Thrown when the JPEG-LS stream is not valid.</exception>
public void ReadHeader()
public void ReadHeader(bool tryReadSpiffHeader = true)
{
CheckOperation(_state == State.SourceSet);

_reader.ReadHeader();
_state = State.HeaderRead;
ThrowHelper.ThrowInvalidOperationIfFalse(_state is >= State.SourceSet and < State.HeaderRead);

if (_reader.SpiffHeader != null && _reader.SpiffHeader.IsValid(FrameInfo))
if (_state != State.SpiffHeaderNotFound)
{
SpiffHeader = _reader.SpiffHeader;
_reader.ReadHeader(tryReadSpiffHeader);
if (_reader.SpiffHeader != null)
{
_reader.ReadHeader(false);
if (_reader.SpiffHeader.IsValid(FrameInfo))
{
SpiffHeader = _reader.SpiffHeader;
}
}
}

_state = State.HeaderRead;
}

/// <summary>
Expand All @@ -210,7 +262,7 @@ public void ReadHeader()
/// <returns>A byte array with the decoded JPEG-LS data.</returns>
/// <exception cref="InvalidDataException">Thrown when the JPEG-LS stream is not valid.</exception>
/// <exception cref="ObjectDisposedException">Thrown when the instance is used after being disposed.</exception>
/// <exception cref="InvalidOperationException">Thrown when this method is called before <see cref="ReadHeader()"/>.</exception>
/// <exception cref="InvalidOperationException">Thrown when this method is called before <see cref="ReadHeader(bool)"/>.</exception>
public byte[] Decode(int stride = 0)
{
var destination = new byte[GetDestinationSize()];
Expand Down Expand Up @@ -267,22 +319,14 @@ public void Decode(Span<byte> destination, int stride = 0)
_state = State.Completed;
}

private static void CheckOperation(bool expression)
{
if (!expression)
{
throw new InvalidOperationException("JPEG-LS Decoder in the incorrect state.");
}
}

private void CheckHeaderRead()
{
ThrowHelper.ThrowInvalidOperationIfFalse(_state >= State.HeaderRead);
}

private int CalculateMinimumStride()
{
int componentsInPlaneCount =
int componentsInPlaneCount =
_reader.InterleaveMode == InterleaveMode.None
? 1
: FrameInfo.ComponentCount;
Expand Down
Loading