throw new ArgumentException("path is empty.", nameof(inputFilePath));
}
- if (CheckHeader(inputFilePath) == false)
+ if (CheckHeaders(inputFilePath) == false)
{
throw new FileFormatException("The file has an invalid header.");
}
throw new ArgumentException("buffer is empty.", nameof(inputBuffer));
}
- if (CheckHeader(inputBuffer) == false)
+ if (CheckHeaders(inputBuffer) == false)
{
throw new FileFormatException("buffer has an invalid header.");
}
return DecodeAsync();
}
- private bool CheckHeader(byte[] input)
+ private bool CheckHeaders(byte[] inputBuffer)
{
- if (input.Length < Header.Length)
+ foreach (var header in Headers)
{
- return false;
- }
+ var inputBufferHeader = new byte[header.Id.Length];
+ Buffer.BlockCopy(inputBuffer, header.Offset, inputBufferHeader, 0, header.Id.Length);
- for (int i = 0; i < Header.Length; ++i)
- {
- if (input[i] != Header[i])
+ if (CheckHeader(inputBufferHeader, header.Id))
{
- return false;
+ return true;
}
}
- return true;
+ return false;
}
- private bool CheckHeader(string inputFile)
+ private bool CheckHeaders(string inputFile)
{
using (var fs = File.OpenRead(inputFile))
{
- byte[] fileHeader = new byte[Header.Length];
+ foreach (var header in Headers)
+ {
+ fs.Position = header.Offset;
+
+ byte[] fileHeader = new byte[header.Id.Length];
+ if (fs.Read(fileHeader, 0, fileHeader.Length) < header.Id.Length)
+ {
+ continue;
+ }
+
+ if (CheckHeader(fileHeader, header.Id))
+ {
+ return true;
+ }
+ }
- if (fs.Read(fileHeader, HeaderOffset, fileHeader.Length) < Header.Length)
+ return false;
+ }
+ }
+
+ private bool CheckHeader(byte[] input, byte[] header)
+ {
+ if (input.Length < header.Length)
+ {
+ return false;
+ }
+
+ for (int i = 0; i < header.Length; ++i)
+ {
+ if (input[i] != header[i])
{
return false;
}
- return CheckHeader(fileHeader);
}
+
+ return true;
}
private IEnumerable<BitmapFrame> RunDecoding()
{
if (_colorSpace.HasValue)
{
- NativeDecoder.SetColorspace(Handle, _colorSpace.Value.ToImageColorSpace()).ThrowIfFailed("Failed to set color space");
+ NativeDecoder.SetColorspace(Handle, _colorSpace.Value.ToImageColorSpace()).
+ ThrowIfFailed("Failed to set color space");
}
}
- internal abstract byte[] Header { get; }
-
- internal abstract int HeaderOffset { get; }
+ internal abstract (byte[] Id, int Offset)[] Headers { get; }
#region IDisposable Support
private bool _disposed = false;
/// <summary>
/// Releases the unmanaged resources used by the ImageDecoder.
/// </summary>
- /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
+ /// <param name="disposing">
+ /// true to release both managed and unmanaged resources; false to release only unmanaged resources.
+ /// </param>
/// <since_tizen> 4 </since_tizen>
protected virtual void Dispose(bool disposing)
{
/// <summary>
/// Initializes a new instance of the <see cref="BmpDecoder"/> class.
/// </summary>
- /// <remarks><see cref="ImageDecoder.InputFormat"/> will be the <see cref="ImageFormat.Bmp"/>.</remarks>
+ /// <remarks>
+ /// <see cref="ImageDecoder.InputFormat"/> will be the <see cref="ImageFormat.Bmp"/>.
+ /// </remarks>
/// <since_tizen> 4 </since_tizen>
public BmpDecoder() : base(ImageFormat.Bmp)
{
}
- internal override byte[] Header => _header;
-
- internal override int HeaderOffset => 0;
+ internal override (byte[], int)[] Headers => new (byte[], int)[] { (_header, 0) };
}
/// <summary>
/// <summary>
/// Initializes a new instance of the <see cref="PngDecoder"/> class.
/// </summary>
- /// <remarks><see cref="ImageDecoder.InputFormat"/> will be the <see cref="ImageFormat.Png"/>.</remarks>
+ /// <remarks>
+ /// <see cref="ImageDecoder.InputFormat"/> will be the <see cref="ImageFormat.Png"/>.
+ /// </remarks>
/// <since_tizen> 4 </since_tizen>
public PngDecoder() : base(ImageFormat.Png)
{
}
- internal override byte[] Header => _header;
-
- internal override int HeaderOffset => 0;
+ internal override (byte[], int)[] Headers => new (byte[], int)[] { (_header, 0) };
}
/// <summary>
/// <summary>
/// Initializes a new instance of the <see cref="JpegDecoder"/> class.
/// </summary>
- /// <remarks><see cref="ImageDecoder.InputFormat"/> will be the <see cref="ImageFormat.Jpeg"/>.</remarks>
+ /// <remarks>
+ /// <see cref="ImageDecoder.InputFormat"/> will be the <see cref="ImageFormat.Jpeg"/>.
+ /// </remarks>
/// <since_tizen> 4 </since_tizen>
public JpegDecoder() : base(ImageFormat.Jpeg)
{
{
base.Initialize(handle);
- NativeDecoder.SetJpegDownscale(handle, Downscale).ThrowIfFailed("Failed to set downscale for decoding");
+ NativeDecoder.SetJpegDownscale(handle, Downscale).
+ ThrowIfFailed("Failed to set downscale for decoding");
}
- internal override byte[] Header => _header;
-
- internal override int HeaderOffset => 0;
+ internal override (byte[], int)[] Headers => new (byte[], int)[] { (_header, 0) };
}
/// <summary>
/// <summary>
/// Initializes a new instance of the <see cref="GifDecoder"/> class.
/// </summary>
- /// <remarks><see cref="ImageDecoder.InputFormat"/> will be the <see cref="ImageFormat.Gif"/>.</remarks>
+ /// <remarks>
+ /// <see cref="ImageDecoder.InputFormat"/> will be the <see cref="ImageFormat.Gif"/>.
+ /// </remarks>
/// <since_tizen> 4 </since_tizen>
public GifDecoder() : base(ImageFormat.Gif)
{
}
- internal override byte[] Header => _header;
-
- internal override int HeaderOffset => 0;
+ internal override (byte[], int)[] Headers => new (byte[], int)[] { (_header, 0) };
}
/// <summary>
/// <summary>
/// Initializes a new instance of the <see cref="WebPDecoder"/> class.
/// </summary>
- /// <remarks><see cref="ImageDecoder.InputFormat"/> will be the <see cref="ImageFormat.WebP"/>.</remarks>
+ /// <remarks>
+ /// <see cref="ImageDecoder.InputFormat"/> will be the <see cref="ImageFormat.WebP"/>.
+ /// </remarks>
/// <since_tizen> 8 </since_tizen>
public WebPDecoder() : base(ImageFormat.WebP)
{
}
- internal override byte[] Header => _header;
-
- internal override int HeaderOffset => 8;
+ internal override (byte[], int)[] Headers => new (byte[], int)[] { (_header, 8) };
}
/// <summary>
/// <summary>
/// Initializes a new instance of the <see cref="HeifDecoder"/> class.
/// </summary>
- /// <remarks><see cref="ImageDecoder.InputFormat"/> will be the <see cref="ImageFormat.Heif"/>.</remarks>
+ /// <remarks>
+ /// <see cref="ImageDecoder.InputFormat"/> will be the <see cref="ImageFormat.Heif"/>.
+ /// </remarks>
/// <since_tizen> 9 </since_tizen>
public HeifDecoder() : base(ImageFormat.Heif)
{
}
- internal override byte[] Header => _header;
+ internal override (byte[], int)[] Headers => new (byte[], int)[] { (_header, 4) };
+ }
+
+ /// <summary>
+ /// Provides the ability to decode the JPEG (Joint Photographic Experts Group) XL encoded images.
+ /// </summary>
+ /// <since_tizen> 10 </since_tizen>
+ public class JpegXlDecoder : ImageDecoder
+ {
+ private static readonly byte[] _headerJpegXl = { (byte)'J', (byte)'X', (byte)'L' };
+ private static readonly byte[] _headerJpegXlCodeStream = { 0xFF, 0x0A };
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="JpegXlDecoder"/> class.
+ /// </summary>
+ /// <remarks>
+ /// <see cref="ImageDecoder.InputFormat"/> will be the <see cref="ImageFormat.JpegXl"/>.
+ /// </remarks>
+ /// <since_tizen> 10 </since_tizen>
+ public JpegXlDecoder() : base(ImageFormat.JpegXl)
+ {
+ }
- internal override int HeaderOffset => 4;
+ internal override (byte[], int)[] Headers =>
+ new (byte[], int)[] { (_headerJpegXl, 4), (_headerJpegXlCodeStream, 0) };
}
}
/// The property determining whether the WebP compression is lossless or lossy.<br/>
/// The default is false(lossy).</value>
/// <since_tizen> 8 </since_tizen>
- public bool Lossless { get; set; }
+ public bool Lossless { get; set; } = false;
internal override void Configure(ImageEncoderHandle handle)
{
- NativeEncoder.SetWebPLossless(handle, Lossless).
+ NativeEncoder.SetLossless(handle, Lossless).
ThrowIfFailed("Failed to configure encoder; Lossless");
}
}
+ /// <summary>
+ /// Provides the ability to encode the JPEG(Joint Photographic Experts Group) XL format images.
+ /// </summary>
+ /// <since_tizen> 10 </since_tizen>
+ public class JpegXlEncoder : ImageEncoder
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="JpegXlEncoder"/> class.
+ /// </summary>
+ /// <remarks><see cref="ImageEncoder.OutputFormat"/> will be the <see cref="ImageFormat.JpegXl"/>.</remarks>
+ /// <since_tizen> 10 </since_tizen>
+ public JpegXlEncoder() :
+ base(ImageFormat.JpegXl)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="JpegXlEncoder"/> class for lossless or lossy compression.
+ /// </summary>
+ /// <remarks><see cref="ImageEncoder.OutputFormat"/> will be the <see cref="ImageFormat.JpegXl"/>.</remarks>
+ /// <param name="lossless">
+ /// The flag determining whether the compression is lossless or lossy: true for lossless, false for lossy.<br/>
+ /// The default value is false.
+ /// </param>
+ /// <since_tizen> 10 </since_tizen>
+ public JpegXlEncoder(bool lossless) :
+ base(ImageFormat.JpegXl)
+ {
+ Lossless = lossless;
+ }
+
+ /// <summary>
+ /// Gets or sets the lossless or lossy JpegXl compression.
+ /// </summary>
+ /// <value>
+ /// The property determining whether the JpegXl compression is lossless or lossy.<br/>
+ /// The default is false(lossy).</value>
+ /// <since_tizen> 10 </since_tizen>
+ public bool Lossless { get; set; } = false;
+
+ internal override void Configure(ImageEncoderHandle handle)
+ {
+ NativeEncoder.SetLossless(handle, Lossless).
+ ThrowIfFailed($"Failed to configure encoder; Lossless={Lossless}");
+ }
+ }
}