diff --git a/Codecs/Image/Jpeg/JpegImage.cs b/Codecs/Image/Jpeg/JpegImage.cs index c49edacb..f369a9f3 100644 --- a/Codecs/Image/Jpeg/JpegImage.cs +++ b/Codecs/Image/Jpeg/JpegImage.cs @@ -56,7 +56,7 @@ public static JpegImage FromStream(Stream stream) case Jpeg.Markers.StartOfDifferentialProgressiveArithmeticFrame: case Jpeg.Markers.StartOfProgressiveArithmeticFrame: case Jpeg.Markers.StartOfProgressiveHuffmanFrame: - case Jpeg.Markers.HeirarchicalProgression: + case Jpeg.Markers.HeirarchicalProgression: switch (marker.FunctionCode) { case Jpeg.Markers.StartOfDifferentialProgressiveHuffmanFrame: @@ -70,7 +70,7 @@ public static JpegImage FromStream(Stream stream) StartOfFrame tag; - if(marker.FunctionCode == Jpeg.Markers.HeirarchicalProgression) + if (marker.FunctionCode == Jpeg.Markers.HeirarchicalProgression) { tag = new HeirarchicalProgression(marker); } @@ -78,7 +78,7 @@ public static JpegImage FromStream(Stream stream) { tag = new StartOfFrame(marker); } - + int bitDepth = Binary.Clamp(Binary.BitsPerByte, Binary.BitsPerInteger, tag.P); height = tag.Y; width = tag.X; @@ -110,7 +110,7 @@ public static JpegImage FromStream(Stream stream) var mediaComponent = new JpegComponent((byte)quantizationTableNumber, (byte)componentId, bitsPerComponent); mediaComponents[componentIndex] = mediaComponent; - + remains -= frameComponent.Count; } @@ -127,12 +127,12 @@ public static JpegImage FromStream(Stream stream) if (read < dataSegment.Count) dataSegment = dataSegment.Slice(0, read); break; - } + } case Jpeg.Markers.AppFirst: case Jpeg.Markers.AppLast: var app = new App(marker); - if(app.MajorVersion >= 1 && app.MinorVersion >= 2) + if (app.MajorVersion >= 1 && app.MinorVersion >= 2) { var appExtension = new AppExtension(app); thumbnailData = appExtension.ThumbnailData; @@ -185,7 +185,7 @@ public void Save(Stream stream) markerBuffer.Remove(Jpeg.Markers.QuantizationTable); - foreach(var marker in markerBuffer.Values.Where(markerBuffer => Jpeg.Markers.IsApplicationMarker(markerBuffer.FunctionCode))) + foreach (var marker in markerBuffer.Values.Where(markerBuffer => Jpeg.Markers.IsApplicationMarker(markerBuffer.FunctionCode))) { WriteMarker(stream, marker); @@ -222,8 +222,11 @@ public void Save(Stream stream) // Write the image data stream.Write(Data.Array, Data.Offset, Data.Count); - // Write the EOI marker - WriteEmptyMarker(stream, Jpeg.Markers.EndOfInformation); + if (Data[Data.Count - 1] != Jpeg.Markers.EndOfInformation) + { + // Write the EOI marker + WriteEmptyMarker(stream, Jpeg.Markers.EndOfInformation); + } } private void WriteStartOfFrame(byte functionCode, Stream stream) diff --git a/Codecs/Image/Jpeg/JpegUnitTests.cs b/Codecs/Image/Jpeg/JpegUnitTests.cs index 1aa720d1..8f0fdd6d 100644 --- a/Codecs/Image/Jpeg/JpegUnitTests.cs +++ b/Codecs/Image/Jpeg/JpegUnitTests.cs @@ -208,9 +208,10 @@ private static void DumpMarker(Marker marker) } else { - Console.Write(BitConverter.ToString(marker.Data.Array, marker.Data.Offset, Math.Min(16, marker.Data.Count))); + using var slice = marker.Data; + Console.Write(BitConverter.ToString(slice.Array, slice.Offset, Math.Min(16, slice.Count))); } - if (marker.Data.Count > 16) + if (marker.DataLength > 16) Console.WriteLine(" ..."); else Console.WriteLine(); diff --git a/Codecs/Image/Jpeg/Marker.cs b/Codecs/Image/Jpeg/Marker.cs index fa9216c3..b7429818 100644 --- a/Codecs/Image/Jpeg/Marker.cs +++ b/Codecs/Image/Jpeg/Marker.cs @@ -37,6 +37,8 @@ public int Length public int MarkerLength => DataLength + 2; + public int DataOffset => Offset + PrefixBytes + LengthBytes; + public MemorySegment Data => Count > PrefixBytes + LengthBytes ? this.Slice(PrefixBytes + LengthBytes) : Empty; public bool IsEmpty => DataLength == 0; diff --git a/Codecs/Image/Jpeg/Markers/App.cs b/Codecs/Image/Jpeg/Markers/App.cs index 13b38c0b..2a6058f7 100644 --- a/Codecs/Image/Jpeg/Markers/App.cs +++ b/Codecs/Image/Jpeg/Markers/App.cs @@ -11,20 +11,44 @@ public class App : Marker public string Identifier { - get => Encoding.UTF8.GetString(Data.Array, Data.Offset, 5); - set => Encoding.UTF8.GetBytes(value, 0, 5, Data.Array, Data.Offset); + get + { + using var slice = Data; + return Encoding.UTF8.GetString(slice.Array, slice.Offset, 5); + } + set + { + using var slice = Data; + Encoding.UTF8.GetBytes(value, 0, 5, slice.Array, slice.Offset); + } } public byte MajorVersion { - get => Data[6]; - set => Data[6] = value; + get + { + using var slice = Data; + return slice[6]; + } + set + { + using var slice = Data; + slice[6] = value; + } } public byte MinorVersion { - get => Data[7]; - set => Data[7] = value; + get + { + using var slice = Data; + return slice[7]; + } + set + { + using var slice = Data; + slice[7] = value; + } } public Version Version @@ -39,44 +63,93 @@ public Version Version public int DensityUnits { - get => Data[8]; - set => Data[8] = (byte)value; + get + { + using var slice = Data; + return slice[8]; + } + set + { + using var slice = Data; + slice[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); + get + { + using var slice = Data; + return Binary.Read16(slice.Array, slice.Offset + 9, Binary.IsLittleEndian); + } + set + { + using var slice = Data; + Binary.Write16(slice.Array, slice.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); + get + { + using var slice = Data; + return Binary.Read16(slice.Array, slice.Offset + 11, Binary.IsLittleEndian); + } + set + { + using var slice = Data; + Binary.Write16(slice.Array, slice.Offset + 11, Binary.IsLittleEndian, (ushort)value); + } } public int XThumbnail { - get => Data[12]; - set => Data[12] = (byte)value; + get + { + using var slice = Data; + return slice[12]; + } + set + { + using var slice = Data; + slice[12] = (byte)value; + } } public int YThumbnail { - get => Data[13]; - set => Data[13] = (byte)value; + get + { + using var slice = Data; + return slice[13]; + } + set + { + using var slice = Data; + slice[13] = (byte)value; + } } public MemorySegment ThumbnailData { - get => Data.Slice(14); - set => value.CopyTo(Data.Array, Data.Offset + 14); + get + { + using var slice = Data; + return slice.Slice(14); + } + set + { + using var slice = Data; + value.CopyTo(slice); + } } public App(byte functionCode, MemorySegment data) : base(functionCode, Length + data.Count) { - data.CopyTo(Data.Array, Data.Offset + 14); + using var slice = Data; + data.CopyTo(slice); } public App(Marker marker) : base(marker) diff --git a/Codecs/Image/Jpeg/Markers/AppExtension.cs b/Codecs/Image/Jpeg/Markers/AppExtension.cs index 6eda60f3..4bc1900a 100644 --- a/Codecs/Image/Jpeg/Markers/AppExtension.cs +++ b/Codecs/Image/Jpeg/Markers/AppExtension.cs @@ -22,14 +22,14 @@ public AppExtension(MemorySegment data) public string Identifier { - get => Encoding.UTF8.GetString(Data.Array, Data.Offset, 5); - set => Encoding.UTF8.GetBytes(value, 0, 5, Data.Array, Data.Offset); + get => Encoding.UTF8.GetString(Array, DataOffset, 5); + set => Encoding.UTF8.GetBytes(value, 0, 5, Array, DataOffset); } public int ThumbnailFormat { - get => Data[6]; - set => Data[6] = (byte)value; + get => Array[DataOffset + 6]; + set => Array[DataOffset + 6] = (byte)value; } public ThumbnailFormatType ThumbnailFormatType @@ -40,7 +40,7 @@ public ThumbnailFormatType ThumbnailFormatType public MemorySegment ThumbnailData { - get => Data.Slice(DataLength > 0 ? 6 : 0); + get => this.Slice(DataOffset + DataLength > 0 ? Length : 0); set { using var slice = ThumbnailData; diff --git a/Codecs/Image/Jpeg/Markers/Exp.cs b/Codecs/Image/Jpeg/Markers/Exp.cs index d7d096d1..0b4df9bb 100644 --- a/Codecs/Image/Jpeg/Markers/Exp.cs +++ b/Codecs/Image/Jpeg/Markers/Exp.cs @@ -11,12 +11,12 @@ public int Eh { get { - var bitOffset = Binary.BytesToBits(Data.Offset); + var bitOffset = Binary.BytesToBits(DataOffset); return (int)this.ReadBits(bitOffset, Binary.Four, Binary.BitOrder.MostSignificant); } set { - var bitOffset = Binary.BytesToBits(Data.Offset); + var bitOffset = Binary.BytesToBits(DataOffset); this.WriteBits(ref bitOffset, Binary.Four, value, Binary.BitOrder.MostSignificant); } } @@ -25,12 +25,12 @@ public int Ev { get { - var bitOffset = Binary.BytesToBits(Data.Offset) + Binary.Four; + var bitOffset = Binary.BytesToBits(DataOffset) + Binary.Four; return (int)this.ReadBits(bitOffset, Binary.Four, Binary.BitOrder.MostSignificant); } set { - var bitOffset = Binary.BytesToBits(Data.Offset) + Binary.Four; + var bitOffset = Binary.BytesToBits(DataOffset) + Binary.Four; this.WriteBits(ref bitOffset, Binary.Four, value, Binary.BitOrder.MostSignificant); } } diff --git a/Codecs/Image/Jpeg/Markers/NumberOfLines.cs b/Codecs/Image/Jpeg/Markers/NumberOfLines.cs index 350f7625..0216409f 100644 --- a/Codecs/Image/Jpeg/Markers/NumberOfLines.cs +++ b/Codecs/Image/Jpeg/Markers/NumberOfLines.cs @@ -11,8 +11,8 @@ public class NumberOfLines : Marker /// public int Nl { - get => Binary.Read16(Array, Data.Offset + 2, Binary.IsLittleEndian); - set => Binary.Write16(Array, Data.Offset + 2, Binary.IsLittleEndian, (ushort)value); + get => Binary.Read16(Array, DataOffset + 2, Binary.IsLittleEndian); + set => Binary.Write16(Array, DataOffset + 2, Binary.IsLittleEndian, (ushort)value); } public NumberOfLines(byte functionCode, int numberOfLines) diff --git a/Codecs/Image/Jpeg/Markers/StartOfFrame.cs b/Codecs/Image/Jpeg/Markers/StartOfFrame.cs index 2fa653ba..31ca1712 100644 --- a/Codecs/Image/Jpeg/Markers/StartOfFrame.cs +++ b/Codecs/Image/Jpeg/Markers/StartOfFrame.cs @@ -17,8 +17,8 @@ public class StartOfFrame : Marker /// public int P { - get => Data[0]; - set => Data[0] = (byte)value; + get => Array[DataOffset]; + set => Array[DataOffset] = (byte)value; } /// @@ -26,8 +26,8 @@ public int P /// public int Y { - get => Binary.ReadU16(Array, Data.Offset + 1, Binary.IsLittleEndian); - set => Binary.Write16(Array, Data.Offset + 1, Binary.IsLittleEndian, (ushort)value); + get => Binary.ReadU16(Array, DataOffset + 1, Binary.IsLittleEndian); + set => Binary.Write16(Array, DataOffset + 1, Binary.IsLittleEndian, (ushort)value); } /// @@ -35,8 +35,8 @@ public int Y /// public int X { - get => Binary.ReadU16(Array, Data.Offset + 3, Binary.IsLittleEndian); - set => Binary.Write16(Array, Data.Offset + 3, Binary.IsLittleEndian, (ushort)value); + get => Binary.ReadU16(Array, DataOffset + 3, Binary.IsLittleEndian); + set => Binary.Write16(Array, DataOffset + 3, Binary.IsLittleEndian, (ushort)value); } /// @@ -44,8 +44,8 @@ public int X /// public int Nf { - get => Binary.ReadU8(Data.Array, Data.Offset + 5, Binary.IsBigEndian); - set => Binary.Write8(Data.Array, Data.Offset + 5, Binary.IsBigEndian, (byte)value); + get => Binary.ReadU8(Array, DataOffset + 5, Binary.IsBigEndian); + set => Binary.Write8(Array, DataOffset + 5, Binary.IsBigEndian, (byte)value); } /// @@ -58,13 +58,12 @@ public int Nf get { var offset = Length + index * FrameComponent.Length; - using var slice = Data.Slice(offset, FrameComponent.Length); - return new FrameComponent(slice); + return new FrameComponent(this.Slice(DataOffset + offset, FrameComponent.Length)); } set { var offset = Length + index * FrameComponent.Length; - using var slice = Data.Slice(offset, FrameComponent.Length); + using var slice = this.Slice(DataOffset + offset, FrameComponent.Length); value.CopyTo(slice); } } diff --git a/Codecs/Image/Jpeg/Markers/StartOfScan.cs b/Codecs/Image/Jpeg/Markers/StartOfScan.cs index cc091dae..a195236f 100644 --- a/Codecs/Image/Jpeg/Markers/StartOfScan.cs +++ b/Codecs/Image/Jpeg/Markers/StartOfScan.cs @@ -28,8 +28,8 @@ public StartOfScan(MemorySegment data) /// public int Ns { - get => Data[0]; - set => Data[0] = (byte)value; + get => Array[DataOffset]; + set => Array[DataOffset] = (byte)value; } /// @@ -57,13 +57,13 @@ public IEnumerable Components get { var offset = 1 + index * ScanComponentSelectorType.Length; - using var slice = Data.Slice(offset, ScanComponentSelectorType.Length); + using var slice = this.Slice(DataOffset + offset, ScanComponentSelectorType.Length); return new ScanComponentSelectorType(slice); } set { var offset = 1 + index * ScanComponentSelectorType.Length; - using var slice = Data.Slice(offset, ScanComponentSelectorType.Length); + using var slice = this.Slice(DataOffset + offset, ScanComponentSelectorType.Length); value.CopyTo(slice); } } @@ -76,12 +76,12 @@ public int Ss get { var offset = 1 + Ns * ScanComponentSelectorType.Length; - return Data[offset]; + return Array[DataOffset + offset]; } set { var offset = 1 + Ns * ScanComponentSelectorType.Length; - Data[offset] = (byte)value; + Array[DataOffset + offset] = (byte)value; } } @@ -93,12 +93,12 @@ public int Se get { var offset = Ns * ScanComponentSelectorType.Length + 1; - return Data[offset]; + return Array[DataOffset + offset]; } set { var offset = Ns * ScanComponentSelectorType.Length + 1; - Data[offset] = (byte)value; + Array[DataOffset + offset] = (byte)value; } } @@ -110,12 +110,14 @@ public int Ah get { var bitOffset = Binary.BytesToBits(1 + Ns * ScanComponentSelectorType.Length + 1 + 1); - return (int)Binary.ReadBits(Data.Array, ref bitOffset, Binary.Four, Binary.BitOrder.MostSignificant); + using var slice = Data; + return (int)slice.ReadBits(ref bitOffset, Binary.Four, Binary.BitOrder.MostSignificant); } set { var bitOffset = Binary.BytesToBits(1 + Ns * ScanComponentSelectorType.Length + 1 + 1); - Binary.WriteBits(Data.Array, ref bitOffset, Binary.Four, value, Binary.BitOrder.MostSignificant); + using var slice = Data; + slice.WriteBits(ref bitOffset, Binary.Four, value, Binary.BitOrder.MostSignificant); } } @@ -127,12 +129,14 @@ public int Al get { var bitOffset = Binary.BytesToBits(1 + Ns * ScanComponentSelectorType.Length + 1 + 1) + Binary.Four; - return (int)Binary.ReadBits(Data.Array, ref bitOffset, Binary.Four, Binary.BitOrder.MostSignificant); + using var slice = Data; + return (int)slice.ReadBits(ref bitOffset, Binary.Four, Binary.BitOrder.MostSignificant); } set { var bitOffset = Binary.BytesToBits(1 + Ns * ScanComponentSelectorType.Length + 1 + 1) + Binary.Four; - Binary.WriteBits(Data.Array, ref bitOffset, Binary.Four, value, Binary.BitOrder.MostSignificant); + using var slice = Data; + slice.WriteBits(ref bitOffset, Binary.Four, value, Binary.BitOrder.MostSignificant); } } } diff --git a/Codecs/Image/Jpeg/Markers/TextComment.cs b/Codecs/Image/Jpeg/Markers/TextComment.cs index a47c8524..bb00f07c 100644 --- a/Codecs/Image/Jpeg/Markers/TextComment.cs +++ b/Codecs/Image/Jpeg/Markers/TextComment.cs @@ -8,8 +8,8 @@ public class TextComment : Marker { public string Comment { - get => Encoding.UTF8.GetString(Array, Data.Offset, Data.Count); - set => Encoding.UTF8.GetBytes(value, 0, value.Length, Data.Array, Data.Offset); + get => Encoding.UTF8.GetString(Array, DataOffset, DataLength); + set => Encoding.UTF8.GetBytes(value, 0, value.Length, Array, DataOffset); } public TextComment(byte functionCode, string comment)