diff --git a/Codecs/Image/Jpeg/Classes/ThumbnailFormat.cs b/Codecs/Image/Jpeg/Classes/ThumbnailFormat.cs new file mode 100644 index 00000000..c4063f14 --- /dev/null +++ b/Codecs/Image/Jpeg/Classes/ThumbnailFormat.cs @@ -0,0 +1,10 @@ +namespace Codec.Jpeg.Classes; + +public enum ThumbnailFormatType : int +{ + Jpeg = 10, + Palette = 11, + RGB = 13, + YCbCr = 21, + CieLab = 22 +} diff --git a/Codecs/Image/Jpeg/JpegImage.cs b/Codecs/Image/Jpeg/JpegImage.cs index 77426298..49e87ce6 100644 --- a/Codecs/Image/Jpeg/JpegImage.cs +++ b/Codecs/Image/Jpeg/JpegImage.cs @@ -117,6 +117,22 @@ public static JpegImage FromStream(Stream stream) } case Jpeg.Markers.AppFirst: case Jpeg.Markers.AppLast: + var app = new App(marker); + + if(app.MajorVersion >= 1 && app.MinorVersion >= 2) + { + var appExtension = new AppExtension(app); + var thumbnailData = appExtension.ThumbnailData; + dataSegment = thumbnailData; + } + else + { + var thumbnailData = app.ThumbnailData; + dataSegment = thumbnailData; + imageFormat = ImageFormat.RGB(8); + width = app.XThumbnail; + height = app.YThumbnail; + } break; default: diff --git a/Codecs/Image/Jpeg/Markers/App.cs b/Codecs/Image/Jpeg/Markers/App.cs new file mode 100644 index 00000000..13b38c0b --- /dev/null +++ b/Codecs/Image/Jpeg/Markers/App.cs @@ -0,0 +1,85 @@ +using Media.Codec.Jpeg; +using Media.Common; +using System; +using System.Text; + +namespace Codec.Jpeg.Markers; + +public class App : Marker +{ + public new const int Length = 14; + + public string Identifier + { + get => Encoding.UTF8.GetString(Data.Array, Data.Offset, 5); + set => Encoding.UTF8.GetBytes(value, 0, 5, Data.Array, Data.Offset); + } + + public byte MajorVersion + { + get => Data[6]; + set => Data[6] = value; + } + + public byte MinorVersion + { + get => Data[7]; + set => Data[7] = value; + } + + public Version Version + { + get => new Version(MajorVersion, MinorVersion); + set + { + MajorVersion = (byte)value.Major; + MinorVersion = (byte)value.Minor; + } + } + + public int DensityUnits + { + get => Data[8]; + set => Data[8] = (byte)value; + } + + public int XDensity + { + get => Binary.Read16(Data.Array, Data.Offset + 9, Binary.IsLittleEndian); + set => Binary.Write16(Data.Array, Data.Offset + 9, Binary.IsLittleEndian, (ushort)value); + } + + public int YDensity + { + get => Binary.Read16(Data.Array, Data.Offset + 11, Binary.IsLittleEndian); + set => Binary.Write16(Data.Array, Data.Offset + 11, Binary.IsLittleEndian, (ushort)value); + } + + public int XThumbnail + { + get => Data[12]; + set => Data[12] = (byte)value; + } + + public int YThumbnail + { + get => Data[13]; + set => Data[13] = (byte)value; + } + + public MemorySegment ThumbnailData + { + get => Data.Slice(14); + set => value.CopyTo(Data.Array, Data.Offset + 14); + } + + public App(byte functionCode, MemorySegment data) + : base(functionCode, Length + data.Count) + { + data.CopyTo(Data.Array, Data.Offset + 14); + } + + public App(Marker marker) : base(marker) + { + } +} diff --git a/Codecs/Image/Jpeg/Markers/AppExtension.cs b/Codecs/Image/Jpeg/Markers/AppExtension.cs new file mode 100644 index 00000000..799681fa --- /dev/null +++ b/Codecs/Image/Jpeg/Markers/AppExtension.cs @@ -0,0 +1,50 @@ +using Codec.Jpeg.Classes; +using Media.Codec.Jpeg; +using Media.Common; +using System.Text; + +namespace Codec.Jpeg.Markers; + +internal class AppExtension : Marker +{ + public new const int Length = 6; + + public AppExtension(byte functionCode, MemorySegment data) + : base(functionCode, Length + data.Count) + { + data.CopyTo(ThumbnailData); + } + + public AppExtension(MemorySegment data) + : base(data) + { + } + + public string Identifier + { + get => Encoding.UTF8.GetString(Data.Array, Data.Offset, 5); + set => Encoding.UTF8.GetBytes(value, 0, 5, Data.Array, Data.Offset); + } + + public int ThumbnailFormat + { + get => Data[6]; + set => Data[6] = (byte)value; + } + + public ThumbnailFormatType ThumbnailFormatType + { + get => (ThumbnailFormatType)ThumbnailFormat; + set => ThumbnailFormat = (int)value; + } + + public MemorySegment ThumbnailData + { + get => Data.Slice(DataSize > 0 ? 6 : 0); + set + { + using var slice = ThumbnailData; + value.CopyTo(slice); + } + } +}