Browse Source

cleanup + stylecop

pull/97/head
Anton Firszov 9 years ago
parent
commit
ca9b49ed7b
  1. 10
      src/ImageSharp.Formats.Jpeg/Components/Decoder/HuffmanTree.cs
  2. 166
      src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegBlockProcessor.cs
  3. 15
      src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.ComputationData.cs
  4. 18
      src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.DataPointers.cs
  5. 75
      src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.cs
  6. 19
      src/ImageSharp.Formats.Jpeg/JpegDecoderCore.cs

10
src/ImageSharp.Formats.Jpeg/Components/Decoder/HuffmanTree.cs

@ -12,6 +12,16 @@ namespace ImageSharp.Formats.Jpg
/// </summary>
internal struct HuffmanTree : IDisposable
{
/// <summary>
/// The index of the AC table row
/// </summary>
public const int AcTableIndex = 1;
/// <summary>
/// The index of the DC table row
/// </summary>
public const int DcTableIndex = 0;
/// <summary>
/// The maximum (inclusive) number of codes in a Huffman tree.
/// </summary>

166
src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegBlockProcessor.cs

@ -0,0 +1,166 @@
// <copyright file="JpegBlockProcessor.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Formats.Jpg
{
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
/// <summary>
/// Encapsulates the implementation of processing "raw" <see cref="DecodedBlockArray"/>-s into Jpeg image channels.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct JpegBlockProcessor
{
/// <summary>
/// The <see cref="ComputationData"/>
/// </summary>
private ComputationData data;
/// <summary>
/// Pointers to elements of <see cref="data"/>
/// </summary>
private DataPointers pointers;
/// <summary>
/// The component index.
/// </summary>
private int componentIndex;
/// <summary>
/// Initialize the <see cref="JpegBlockProcessor"/> instance on the stack.
/// </summary>
/// <param name="processor">The <see cref="JpegBlockProcessor"/> instance</param>
/// <param name="componentIndex">The current component index</param>
public static void Init(JpegBlockProcessor* processor, int componentIndex)
{
processor->componentIndex = componentIndex;
processor->data = ComputationData.Create();
processor->pointers = new DataPointers(&processor->data);
}
/// <summary>
/// Dequantize, perform the inverse DCT and store the blocks to the into the corresponding <see cref="JpegPixelArea"/> instances.
/// </summary>
/// <param name="decoder">The <see cref="JpegDecoderCore"/> instance</param>
public void ProcessAllBlocks(JpegDecoderCore decoder)
{
DecodedBlockArray blockArray = decoder.DecodedBlocks[this.componentIndex];
for (int i = 0; i < blockArray.Count; i++)
{
this.ProcessBlockColors(decoder, ref blockArray.Buffer[i]);
}
}
/// <summary>
/// Dequantize, perform the inverse DCT and store decodedBlock.Block to the into the corresponding <see cref="JpegPixelArea"/> instance.
/// </summary>
/// <param name="decoder">The <see cref="JpegDecoderCore"/></param>
/// <param name="decodedBlock">The <see cref="DecodedBlock"/></param>
private void ProcessBlockColors(JpegDecoderCore decoder, ref DecodedBlock decodedBlock)
{
this.data.Block = decodedBlock.Block;
int qtIndex = decoder.ComponentArray[this.componentIndex].Selector;
this.data.QuantiazationTable = decoder.QuantizationTables[qtIndex];
Block8x8F* b = this.pointers.Block;
Block8x8F.UnZig(b, this.pointers.QuantiazationTable, this.pointers.Unzig);
DCT.TransformIDCT(ref *b, ref *this.pointers.Temp1, ref *this.pointers.Temp2);
var destChannel = decoder.GetDestinationChannel(this.componentIndex);
var destArea = destChannel.GetOffsetedSubAreaForBlock(decodedBlock.Bx, decodedBlock.By);
destArea.LoadColorsFrom(this.pointers.Temp1, this.pointers.Temp2);
}
/// <summary>
/// Holds the "large" data blocks needed for computations.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct ComputationData
{
/// <summary>
/// Temporal block 1 to store intermediate and/or final computation results
/// </summary>
public Block8x8F Block;
/// <summary>
/// Temporal block 1 to store intermediate and/or final computation results
/// </summary>
public Block8x8F Temp1;
/// <summary>
/// Temporal block 2 to store intermediate and/or final computation results
/// </summary>
public Block8x8F Temp2;
/// <summary>
/// The quantization table as <see cref="Block8x8F"/>
/// </summary>
public Block8x8F QuantiazationTable;
/// <summary>
/// The jpeg unzig data
/// </summary>
public UnzigData Unzig;
/// <summary>
/// Creates and initializes a new <see cref="ComputationData"/> instance
/// </summary>
/// <returns>The <see cref="ComputationData"/></returns>
public static ComputationData Create()
{
ComputationData data = default(ComputationData);
data.Unzig = UnzigData.Create();
return data;
}
}
/// <summary>
/// Contains pointers to the memory regions of <see cref="ComputationData"/> so they can be easily passed around to pointer based utility methods of <see cref="Block8x8F"/>
/// </summary>
public struct DataPointers
{
/// <summary>
/// Pointer to <see cref="DecodedBlock.Block"/>
/// </summary>
public Block8x8F* Block;
/// <summary>
/// Pointer to <see cref="ComputationData.Temp1"/>
/// </summary>
public Block8x8F* Temp1;
/// <summary>
/// Pointer to <see cref="ComputationData.Temp2"/>
/// </summary>
public Block8x8F* Temp2;
/// <summary>
/// Pointer to <see cref="ComputationData.QuantiazationTable"/>
/// </summary>
public Block8x8F* QuantiazationTable;
/// <summary>
/// Pointer to <see cref="ComputationData.Unzig"/> as int*
/// </summary>
public int* Unzig;
/// <summary>
/// Initializes a new instance of the <see cref="DataPointers" /> struct.
/// </summary>
/// <param name="dataPtr">Pointer to <see cref="ComputationData"/></param>
internal DataPointers(ComputationData* dataPtr)
{
this.Block = &dataPtr->Block;
this.Temp1 = &dataPtr->Temp1;
this.Temp2 = &dataPtr->Temp2;
this.QuantiazationTable = &dataPtr->QuantiazationTable;
this.Unzig = dataPtr->Unzig.Data;
}
}
}
}

15
src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.ComputationData.cs

@ -23,21 +23,6 @@ namespace ImageSharp.Formats.Jpg
/// </summary>
public Block8x8F Block;
/// <summary>
/// Temporal block 1 to store intermediate and/or final computation results
/// </summary>
public Block8x8F Temp1;
/// <summary>
/// Temporal block 2 to store intermediate and/or final computation results
/// </summary>
public Block8x8F Temp2;
/// <summary>
/// The quantization table as <see cref="Block8x8F"/>
/// </summary>
public Block8x8F QuantiazationTable;
/// <summary>
/// The jpeg unzig data
/// </summary>

18
src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.DataPointers.cs

@ -20,21 +20,6 @@ namespace ImageSharp.Formats.Jpg
/// </summary>
public Block8x8F* Block;
/// <summary>
/// Pointer to <see cref="ComputationData.Temp1"/>
/// </summary>
public Block8x8F* Temp1;
/// <summary>
/// Pointer to <see cref="ComputationData.Temp2"/>
/// </summary>
public Block8x8F* Temp2;
/// <summary>
/// Pointer to <see cref="ComputationData.QuantiazationTable"/>
/// </summary>
public Block8x8F* QuantiazationTable;
/// <summary>
/// Pointer to <see cref="ComputationData.Unzig"/> as int*
/// </summary>
@ -57,9 +42,6 @@ namespace ImageSharp.Formats.Jpg
public DataPointers(ComputationData* basePtr)
{
this.Block = &basePtr->Block;
this.Temp1 = &basePtr->Temp1;
this.Temp2 = &basePtr->Temp2;
this.QuantiazationTable = &basePtr->QuantiazationTable;
this.Unzig = basePtr->Unzig.Data;
this.ComponentScan = (ComponentScan*)basePtr->ScanData;
this.Dc = basePtr->Dc;

75
src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.cs

@ -7,10 +7,11 @@ namespace ImageSharp.Formats.Jpg
{
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
/// <summary>
/// Encapsulates the impementation of Jpeg SOS decoder. See JpegScanDecoder.md!
/// TODO: Split JpegScanDecoder: 1. JpegScanDecoder for Huffman-decoding (<see cref="DecodeBlocks"/>) 2. JpegBlockProcessor for processing (<see cref="ProcessBlockColors"/>)
/// Encapsulates the impementation of Jpeg SOS Huffman decoding. See JpegScanDecoder.md!
///
/// <see cref="zigStart"/> and <see cref="zigEnd"/> are the spectral selection bounds.
/// <see cref="ah"/> and <see cref="al"/> are the successive approximation high and low values.
/// The spec calls these values Ss, Se, Ah and Al.
@ -26,17 +27,21 @@ namespace ImageSharp.Formats.Jpg
/// significant bit.
/// For baseline JPEGs, these parameters are hard-coded to 0/63/0/0.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal unsafe partial struct JpegScanDecoder
{
// The JpegScanDecoder members should be ordered in a way that results in optimal memory layout.
#pragma warning disable SA1202 // ElementsMustBeOrderedByAccess
/// <summary>
/// The AC table index
/// The <see cref="ComputationData"/> buffer
/// </summary>
public const int AcTableIndex = 1;
private ComputationData data;
/// <summary>
/// The DC table index
/// Pointers to elements of <see cref="data"/>
/// </summary>
public const int DcTableIndex = 0;
private DataPointers pointers;
/// <summary>
/// The current component index
@ -88,16 +93,6 @@ namespace ImageSharp.Formats.Jpg
/// </summary>
private int eobRun;
/// <summary>
/// Pointers to elements of <see cref="data"/>
/// </summary>
private DataPointers pointers;
/// <summary>
/// The <see cref="ComputationData"/> buffer
/// </summary>
private ComputationData data;
/// <summary>
/// Initializes a default-constructed <see cref="JpegScanDecoder"/> instance for reading data from <see cref="JpegDecoderCore"/>-s stream.
/// </summary>
@ -105,30 +100,10 @@ namespace ImageSharp.Formats.Jpg
/// <param name="decoder">The <see cref="JpegDecoderCore"/> instance</param>
/// <param name="remaining">The remaining bytes in the segment block.</param>
public static void InitStreamReading(JpegScanDecoder* p, JpegDecoderCore decoder, int remaining)
{
Init(p);
p->InitStreamReadingImpl(decoder, remaining);
}
/// <summary>
/// Initializes a default-constructed <see cref="JpegScanDecoder"/> instance, filling the data and setting the pointers.
/// </summary>
/// <param name="p">Pointer to <see cref="JpegScanDecoder"/> on the stack</param>
public static void Init(JpegScanDecoder* p)
{
p->data = ComputationData.Create();
p->pointers = new DataPointers(&p->data);
}
/// <summary>
/// Loads the data from the given <see cref="DecodedBlock"/> into the block.
/// </summary>
/// <param name="memento">The <see cref="DecodedBlock"/></param>
public void LoadMemento(ref DecodedBlock memento)
{
this.bx = memento.Bx;
this.by = memento.By;
this.data.Block = memento.Block;
p->InitStreamReadingImpl(decoder, remaining);
}
/// <summary>
@ -251,26 +226,6 @@ namespace ImageSharp.Formats.Jpg
}
}
/// <summary>
/// Dequantize, perform the inverse DCT and store the block to the into the corresponding <see cref="JpegPixelArea"/> instances.
/// </summary>
/// <param name="decoder">The <see cref="JpegDecoderCore"/> instance</param>
public void ProcessBlockColors(JpegDecoderCore decoder)
{
int qtIndex = decoder.ComponentArray[this.ComponentIndex].Selector;
this.data.QuantiazationTable = decoder.QuantizationTables[qtIndex];
Block8x8F* b = this.pointers.Block;
Block8x8F.UnZig(b, this.pointers.QuantiazationTable, this.pointers.Unzig);
DCT.TransformIDCT(ref *b, ref *this.pointers.Temp1, ref *this.pointers.Temp2);
var destChannel = decoder.GetDestinationChannel(this.ComponentIndex);
var destArea = destChannel.GetOffsetedSubAreaForBlock(this.bx, this.by);
destArea.LoadColorsFrom(this.pointers.Temp1, this.pointers.Temp2);
}
private void ResetDc()
{
Unsafe.InitBlock(this.pointers.Dc, default(byte), sizeof(int) * JpegDecoderCore.MaxComponents);
@ -351,8 +306,7 @@ namespace ImageSharp.Formats.Jpg
private void DecodeBlock(JpegDecoderCore decoder, int scanIndex)
{
var b = this.pointers.Block;
DecoderErrorCode errorCode;
int huffmannIdx = (AcTableIndex * HuffmanTree.ThRowSize) + this.pointers.ComponentScan[scanIndex].AcTableSelector;
int huffmannIdx = (HuffmanTree.AcTableIndex * HuffmanTree.ThRowSize) + this.pointers.ComponentScan[scanIndex].AcTableSelector;
if (this.ah != 0)
{
this.Refine(ref decoder.InputProcessor, ref decoder.HuffmanTrees[huffmannIdx], 1 << this.al);
@ -360,13 +314,14 @@ namespace ImageSharp.Formats.Jpg
else
{
int zig = this.zigStart;
DecoderErrorCode errorCode;
if (zig == 0)
{
zig++;
// Decode the DC coefficient, as specified in section F.2.2.1.
int value;
int huffmanIndex = (DcTableIndex * HuffmanTree.ThRowSize) + this.pointers.ComponentScan[scanIndex].DcTableSelector;
int huffmanIndex = (HuffmanTree.DcTableIndex * HuffmanTree.ThRowSize) + this.pointers.ComponentScan[scanIndex].DcTableSelector;
errorCode = decoder.InputProcessor.DecodeHuffmanUnsafe(
ref decoder.HuffmanTrees[huffmanIndex],
out value);

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

@ -102,9 +102,9 @@ namespace ImageSharp.Formats
/// <summary>
/// Gets the array of <see cref="DecodedBlockArray"/>-s storing the "raw" frequency-domain decoded blocks.
/// We need to apply IDCT and unzigging to transform them into color-space blocks.
/// We need to apply IDCT, dequantiazition and unzigging to transform them into color-space blocks.
/// This is done by <see cref="ProcessBlocksIntoJpegImageChannels{TColor}"/>.
/// When <see cref="IsProgressive"/>==true, we are touching these blocks each time we process a Scan.
/// When <see cref="IsProgressive"/>==true, we are touching these blocks multiple times - each time we process a Scan.
/// </summary>
public DecodedBlockArray[] DecodedBlocks { get; }
@ -463,7 +463,7 @@ namespace ImageSharp.Formats
/// <summary>
/// Process the blocks in <see cref="DecodedBlocks"/> into Jpeg image channels (<see cref="YCbCrImage"/> and <see cref="JpegPixelArea"/>)
/// <see cref="DecodedBlocks"/> are in a "raw" frequency-domain form. We need to apply IDCT and unzigging to transform them into color-space blocks.
/// <see cref="DecodedBlocks"/> are in a "raw" frequency-domain form. We need to apply IDCT, dequantization and unzigging to transform them into color-space blocks.
/// We can copy these blocks into <see cref="JpegPixelArea"/>-s afterwards.
/// </summary>
/// <typeparam name="TColor">The pixel type</typeparam>
@ -475,16 +475,9 @@ namespace ImageSharp.Formats
this.ComponentCount,
componentIndex =>
{
JpegScanDecoder scanDecoder = default(JpegScanDecoder);
JpegScanDecoder.Init(&scanDecoder);
scanDecoder.ComponentIndex = componentIndex;
DecodedBlockArray blockArray = this.DecodedBlocks[componentIndex];
for (int i = 0; i < blockArray.Count; i++)
{
scanDecoder.LoadMemento(ref blockArray.Buffer[i]);
scanDecoder.ProcessBlockColors(this);
}
JpegBlockProcessor processor = default(JpegBlockProcessor);
JpegBlockProcessor.Init(&processor, componentIndex);
processor.ProcessAllBlocks(this);
});
}

Loading…
Cancel
Save