mirror of https://github.com/SixLabors/ImageSharp
6 changed files with 197 additions and 106 deletions
@ -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; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue