Browse Source

Added SOF data precision comments, decoupled precision value from decoder core

pull/1702/head
Dmitry Pentin 5 years ago
parent
commit
9067c64b30
  1. 7
      src/ImageSharp/Formats/Jpeg/Components/Decoder/IRawJpegData.cs
  2. 6
      src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs
  3. 13
      src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponentPostProcessor.cs
  4. 2
      src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs
  5. 18
      src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs

7
src/ImageSharp/Formats/Jpeg/Components/Decoder/IRawJpegData.cs

@ -26,11 +26,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
/// </summary> /// </summary>
JpegColorSpace ColorSpace { get; } JpegColorSpace ColorSpace { get; }
/// <summary>
/// Gets the number of bits used for precision.
/// </summary>
int Precision { get; }
/// <summary> /// <summary>
/// Gets the components. /// Gets the components.
/// </summary> /// </summary>
@ -41,4 +36,4 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
/// </summary> /// </summary>
Block8x8F[] QuantizationTables { get; } Block8x8F[] QuantizationTables { get; }
} }
} }

6
src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs

@ -38,11 +38,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
/// </summary> /// </summary>
private Size subSamplingDivisors; private Size subSamplingDivisors;
/// <summary>
/// Defines the maximum value derived from the bitdepth.
/// </summary>
private readonly int maximumValue;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="JpegBlockPostProcessor"/> struct. /// Initializes a new instance of the <see cref="JpegBlockPostProcessor"/> struct.
/// </summary> /// </summary>
@ -53,7 +48,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
int qtIndex = component.QuantizationTableIndex; int qtIndex = component.QuantizationTableIndex;
this.DequantiazationTable = ZigZag.CreateDequantizationTable(ref decoder.QuantizationTables[qtIndex]); this.DequantiazationTable = ZigZag.CreateDequantizationTable(ref decoder.QuantizationTables[qtIndex]);
this.subSamplingDivisors = component.SubSamplingDivisors; this.subSamplingDivisors = component.SubSamplingDivisors;
this.maximumValue = (int)MathF.Pow(2, decoder.Precision) - 1;
this.SourceBlock = default; this.SourceBlock = default;
this.WorkspaceBlock1 = default; this.WorkspaceBlock1 = default;

13
src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponentPostProcessor.cs

@ -21,11 +21,18 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
/// </summary> /// </summary>
private readonly Size blockAreaSize; private readonly Size blockAreaSize;
/// <summary>
/// Jpeg frame instance containing required decoding metadata.
/// </summary>
private readonly JpegFrame frame;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="JpegComponentPostProcessor"/> class. /// Initializes a new instance of the <see cref="JpegComponentPostProcessor"/> class.
/// </summary> /// </summary>
public JpegComponentPostProcessor(MemoryAllocator memoryAllocator, IRawJpegData rawJpeg, Size postProcessorBufferSize, IJpegComponent component) public JpegComponentPostProcessor(MemoryAllocator memoryAllocator, JpegFrame frame, IRawJpegData rawJpeg, Size postProcessorBufferSize, IJpegComponent component)
{ {
this.frame = frame;
this.Component = component; this.Component = component;
this.RawJpeg = rawJpeg; this.RawJpeg = rawJpeg;
this.blockAreaSize = this.Component.SubSamplingDivisors * 8; this.blockAreaSize = this.Component.SubSamplingDivisors * 8;
@ -70,7 +77,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
Buffer2D<Block8x8> spectralBuffer = this.Component.SpectralBlocks; Buffer2D<Block8x8> spectralBuffer = this.Component.SpectralBlocks;
var blockPp = new JpegBlockPostProcessor(this.RawJpeg, this.Component); var blockPp = new JpegBlockPostProcessor(this.RawJpeg, this.Component);
float maximumValue = MathF.Pow(2, this.RawJpeg.Precision) - 1;
// TODO: this is a constant value for ALL components
float maximumValue = MathF.Pow(2, this.frame.Precision) - 1;
int destAreaStride = this.ColorBuffer.Width; int destAreaStride = this.ColorBuffer.Width;

2
src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs

@ -78,7 +78,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
this.componentProcessors = new JpegComponentPostProcessor[frame.Components.Length]; this.componentProcessors = new JpegComponentPostProcessor[frame.Components.Length];
for (int i = 0; i < this.componentProcessors.Length; i++) for (int i = 0; i < this.componentProcessors.Length; i++)
{ {
this.componentProcessors[i] = new JpegComponentPostProcessor(allocator, jpegData, postProcessorBufferSize, frame.Components[i]); this.componentProcessors[i] = new JpegComponentPostProcessor(allocator, frame, jpegData, postProcessorBufferSize, frame.Components[i]);
} }
// single 'stride' rgba32 buffer for conversion between spectral and TPixel // single 'stride' rgba32 buffer for conversion between spectral and TPixel

18
src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs

@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
/// <summary> /// <summary>
/// The only supported precision /// The only supported precision
/// </summary> /// </summary>
private readonly int[] supportedPrecisions = { 8, 12 }; private readonly byte[] supportedPrecisions = { 8, 12 };
/// <summary> /// <summary>
/// The buffer used to temporarily store bytes read from the stream. /// The buffer used to temporarily store bytes read from the stream.
@ -148,9 +148,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
/// <inheritdoc/> /// <inheritdoc/>
public JpegColorSpace ColorSpace { get; private set; } public JpegColorSpace ColorSpace { get; private set; }
/// <inheritdoc/>
public int Precision { get; private set; }
/// <summary> /// <summary>
/// Gets the components. /// Gets the components.
/// </summary> /// </summary>
@ -825,23 +822,24 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
JpegThrowHelper.ThrowInvalidImageContentException("Multiple SOF markers. Only single frame jpegs supported."); JpegThrowHelper.ThrowInvalidImageContentException("Multiple SOF markers. Only single frame jpegs supported.");
} }
// Read initial marker definitions. // Read initial marker definitions
const int length = 6; const int length = 6;
stream.Read(this.temp, 0, length); stream.Read(this.temp, 0, length);
// We only support 8-bit and 12-bit precision. // 1 byte: Bits/sample precision
if (Array.IndexOf(this.supportedPrecisions, this.temp[0]) == -1) byte precision = this.temp[0];
// Validity check: only 8-bit and 12-bit precisions are supported
if (Array.IndexOf(this.supportedPrecisions, precision) == -1)
{ {
JpegThrowHelper.ThrowInvalidImageContentException("Only 8-Bit and 12-Bit precision supported."); JpegThrowHelper.ThrowInvalidImageContentException("Only 8-Bit and 12-Bit precision supported.");
} }
this.Precision = this.temp[0];
this.Frame = new JpegFrame this.Frame = new JpegFrame
{ {
Extended = frameMarker.Marker == JpegConstants.Markers.SOF1, Extended = frameMarker.Marker == JpegConstants.Markers.SOF1,
Progressive = frameMarker.Marker == JpegConstants.Markers.SOF2, Progressive = frameMarker.Marker == JpegConstants.Markers.SOF2,
Precision = this.temp[0], Precision = precision,
PixelHeight = (this.temp[1] << 8) | this.temp[2], PixelHeight = (this.temp[1] << 8) | this.temp[2],
PixelWidth = (this.temp[3] << 8) | this.temp[4], PixelWidth = (this.temp[3] << 8) | this.temp[4],
ComponentCount = this.temp[5] ComponentCount = this.temp[5]

Loading…
Cancel
Save