Skip to content

Commit

Permalink
More jpeg work.
Browse files Browse the repository at this point in the history
  • Loading branch information
juliusfriedman committed Oct 22, 2024
1 parent dfe26fe commit a98c717
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 36 deletions.
15 changes: 15 additions & 0 deletions Codecs/Image/Jpeg/Classes/FrameComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,18 @@ public class FrameComponent : MemorySegment
/// </summary>
public const int Length = 3;

/// <summary>
/// Ci
/// </summary>
public int ComponentIdentifier
{
get => Array[Offset];
set => Array[Offset] = (byte)value;
}

/// <summary>
/// Hi
/// </summary>
public int HorizontalSamplingFactor
{
get
Expand All @@ -28,6 +35,9 @@ public int HorizontalSamplingFactor
}
}

/// <summary>
/// Vi
/// </summary>
public int VerticalSamplingFactor
{
get
Expand All @@ -41,11 +51,16 @@ public int VerticalSamplingFactor
this.WriteBits(bitoffset, Binary.Four, value, Binary.BitOrder.MostSignificant);
}
}

/// <summary>
/// Tqi
/// </summary>
public int QuantizationTableDestinationSelector
{
get => Count > 3 ? Array[Offset + 3] : 0;
set => Array[Offset + 3] = (byte)value;
}

public FrameComponent(MemorySegment other)
: base(other)
{
Expand Down
34 changes: 31 additions & 3 deletions Codecs/Image/Jpeg/JpegComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,40 @@ namespace Codec.Jpeg;

public class JpegComponent : MediaComponent
{
public readonly byte QuantizationTableNumber;
/// <summary>
/// Quantization table destination selector
/// </summary>
public byte Tqi;

/// <summary>
/// DC Entropy encoding table destination selector
/// </summary>
public byte Tdj;

/// <summary>
/// AC Entropy coding table desintation selector.
/// </summary>
public byte Taj;

/// <summary>
/// Not yet useful.
/// </summary>
public byte Reserved;

/// <summary>
///
/// </summary>
/// <param name="quantizationTableNumber"></param>
/// <param name="id"></param>
/// <param name="size"></param>
public JpegComponent(byte quantizationTableNumber, byte id, int size)
: base(id, size)
=> QuantizationTableNumber = quantizationTableNumber;
=> Tqi = quantizationTableNumber;

/// <summary>
///
/// </summary>
/// <returns></returns>
public override int GetHashCode()
=> System.HashCode.Combine(base.GetHashCode(), QuantizationTableNumber);
=> System.HashCode.Combine(base.GetHashCode(), Tqi, Tdj, Taj);
}
49 changes: 31 additions & 18 deletions Codecs/Image/Jpeg/JpegImage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public static JpegImage FromStream(Stream stream)
MemorySegment dataSegment = default;
MemorySegment thumbnailData = default;
bool progressive = false;
ConcurrentThesaurus<byte, Marker> markers = new ConcurrentThesaurus<byte, Marker>();
ConcurrentThesaurus<byte, Marker> markers = new ConcurrentThesaurus<byte, Marker>();
foreach (var marker in JpegCodec.ReadMarkers(stream))
{
//Handle the marker to decode.
Expand Down Expand Up @@ -91,7 +91,7 @@ public static JpegImage FromStream(Stream stream)
if (bitsPerComponent == 0)
bitsPerComponent = Binary.BitsPerByte;

MediaComponent[] mediaComponents = new MediaComponent[numberOfComponents];
JpegComponent[] mediaComponents = new JpegComponent[numberOfComponents];
int[] widths = new int[numberOfComponents];
int[] heights = new int[numberOfComponents];

Expand All @@ -118,9 +118,21 @@ public static JpegImage FromStream(Stream stream)
imageFormat = new ImageFormat(Binary.ByteOrder.Little, DataLayout.Planar, mediaComponents);
imageFormat.HorizontalSamplingFactors = widths;
imageFormat.VerticalSamplingFactors = heights;
tag.Dispose();
tag = null;
continue;
case Jpeg.Markers.StartOfScan:
{
using var sos = new StartOfScan(marker);

for(int ns = sos.Ns, i = 0; i < ns; ++i)
{
using var scanComponentSelector = sos[i];
var jpegComponent = imageFormat.GetComponentById(scanComponentSelector.Csj) as JpegComponent ?? imageFormat.Components[i] as JpegComponent;
jpegComponent.Tdj = scanComponentSelector.Tdj;
jpegComponent.Taj = scanComponentSelector.Taj;
}

var dataSegmentSize = CalculateSize(imageFormat, width, height);
dataSegment = new MemorySegment(Math.Abs(dataSegmentSize));
var read = stream.Read(dataSegment.Array, dataSegment.Offset, dataSegment.Count);
Expand All @@ -130,21 +142,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);
thumbnailData = appExtension.ThumbnailData;
using var app = new App(marker);

if (app.MajorVersion >= 1 && app.MinorVersion >= 2)
{
using var appExtension = new AppExtension(app);
thumbnailData = appExtension.ThumbnailData;
}
else
{
thumbnailData = app.ThumbnailData;
imageFormat = ImageFormat.RGB(8);
width = app.XThumbnail;
height = app.YThumbnail;
}
}
else
{
thumbnailData = app.ThumbnailData;
imageFormat = ImageFormat.RGB(8);
width = app.XThumbnail;
height = app.YThumbnail;
}

goto default;
case Jpeg.Markers.StartOfInformation:
case Jpeg.Markers.EndOfInformation:
Expand Down Expand Up @@ -242,7 +255,7 @@ private void WriteStartOfFrame(byte functionCode, Stream stream)

if (imageComponent is JpegComponent jpegComponent)
{
var frameComponent = new FrameComponent(jpegComponent.Id, ImageFormat.HorizontalSamplingFactors[i], ImageFormat.VerticalSamplingFactors[i], jpegComponent.QuantizationTableNumber);
var frameComponent = new FrameComponent(jpegComponent.Id, ImageFormat.HorizontalSamplingFactors[i], ImageFormat.VerticalSamplingFactors[i], jpegComponent.Tqi);
sof[i] = frameComponent;
}
else
Expand Down Expand Up @@ -272,8 +285,8 @@ private void WriteStartOfScan(Stream stream)
{
var componentSelector = new ScanComponentSelector();
componentSelector.Csj = jpegComponent.Id;
componentSelector.Tdj = jpegComponent.Id;
componentSelector.Taj = jpegComponent.Id;
componentSelector.Tdj = jpegComponent.Tdj;
componentSelector.Taj = jpegComponent.Taj;
sos[i] = componentSelector;
}
else
Expand Down
25 changes: 10 additions & 15 deletions Codecs/Image/Jpeg/Markers/StartOfScan.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,8 @@ public IEnumerable<ScanComponentSelector> Components
}
set
{
var offset = 1 + index * ScanComponentSelector.Length;
using var slice = this.Slice(DataOffset + offset, ScanComponentSelector.Length);
value.CopyTo(slice);
var offset = DataOffset + 1 + index * ScanComponentSelector.Length;
value.CopyTo(Array, offset);
}
}

Expand Down Expand Up @@ -109,15 +108,13 @@ public int Ah
{
get
{
var bitOffset = Binary.BytesToBits(1 + Ns * ScanComponentSelector.Length + 1 + 1);
using var slice = Data;
return (int)slice.ReadBits(ref bitOffset, Binary.Four, Binary.BitOrder.MostSignificant);
var bitOffset = Binary.BytesToBits(DataOffset + 1 + Ns * ScanComponentSelector.Length + 1 + 1);
return (int)this.ReadBits(ref bitOffset, Binary.Four, Binary.BitOrder.MostSignificant);
}
set
{
var bitOffset = Binary.BytesToBits(1 + Ns * ScanComponentSelector.Length + 1 + 1);
using var slice = Data;
slice.WriteBits(ref bitOffset, Binary.Four, value, Binary.BitOrder.MostSignificant);
var bitOffset = Binary.BytesToBits(DataOffset + 1 + Ns * ScanComponentSelector.Length + 1 + 1);
this.WriteBits(ref bitOffset, Binary.Four, value, Binary.BitOrder.MostSignificant);
}
}

Expand All @@ -128,15 +125,13 @@ public int Al
{
get
{
var bitOffset = Binary.BytesToBits(1 + Ns * ScanComponentSelector.Length + 1 + 1) + Binary.Four;
using var slice = Data;
return (int)slice.ReadBits(ref bitOffset, Binary.Four, Binary.BitOrder.MostSignificant);
var bitOffset = Binary.BytesToBits(DataOffset + 1 + Ns * ScanComponentSelector.Length + 1 + 1) + Binary.Four;
return (int)this.ReadBits(ref bitOffset, Binary.Four, Binary.BitOrder.MostSignificant);
}
set
{
var bitOffset = Binary.BytesToBits(1 + Ns * ScanComponentSelector.Length + 1 + 1) + Binary.Four;
using var slice = Data;
slice.WriteBits(ref bitOffset, Binary.Four, value, Binary.BitOrder.MostSignificant);
var bitOffset = Binary.BytesToBits(DataOffset + 1 + Ns * ScanComponentSelector.Length + 1 + 1) + Binary.Four;
this.WriteBits(ref bitOffset, Binary.Four, value, Binary.BitOrder.MostSignificant);
}
}
}

0 comments on commit a98c717

Please sign in to comment.