Browse Source

First working prototype, not optimized

Only works for 444
pull/2076/head
Dmitry Pentin 4 years ago
parent
commit
017919abb8
  1. 60
      src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConversion/JpegComponentPostProcessor8.cs

60
src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConversion/JpegComponentPostProcessor8.cs

@ -31,6 +31,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
/// </summary>
private readonly IRawJpegData rawJpeg;
private readonly float dcDequantizer;
/// <summary>
/// Initializes a new instance of the <see cref="JpegComponentPostProcessor8"/> class.
/// </summary>
@ -41,6 +43,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
this.frame = frame;
this.dcDequantizer = this.rawJpeg.QuantizationTables[this.component.QuantizationTableIndex][0];
this.component = component;
this.rawJpeg = rawJpeg;
this.blockAreaSize = this.component.SubSamplingDivisors * blockSize;
@ -67,19 +71,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
float maximumValue = this.frame.MaxColorChannelValue;
int destAreaStride = this.ColorBuffer.Width;
int blocksRowsPerStep = this.component.SamplingFactors.Height;
int yBlockStart = spectralStep * blocksRowsPerStep;
Size subSamplingDivisors = this.component.SubSamplingDivisors;
Block8x8F dequantTable = this.rawJpeg.QuantizationTables[this.component.QuantizationTableIndex];
Block8x8F workspaceBlock = default;
return;
for (int y = 0; y < blocksRowsPerStep; y++)
{
int yBuffer = y * this.blockAreaSize.Height;
@ -89,27 +84,40 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
for (int xBlock = 0; xBlock < spectralBuffer.Width; xBlock++)
{
// Integer to float
workspaceBlock.LoadFrom(ref blockRow[xBlock]);
// get DC - averaged 8x8 pixel value
float DC = blockRow[xBlock][0];
// Dequantize
workspaceBlock.MultiplyInPlace(ref dequantTable);
// dequantization
DC *= this.dcDequantizer;
// Convert from spectral to color
FastFloatingPointDCT.TransformIDCT(ref workspaceBlock);
// Normalize & round
DC = (float)Math.Round(Numerics.Clamp(DC + MathF.Ceiling(maximumValue / 2), 0, maximumValue));
// To conform better to libjpeg we actually NEED TO loose precision here.
// This is because they store blocks as Int16 between all the operations.
// To be "more accurate", we need to emulate this by rounding!
workspaceBlock.NormalizeColorsAndRoundInPlace(maximumValue);
// Write to color buffer acording to sampling factors
// Save to the intermediate buffer
int xColorBufferStart = xBlock * this.blockAreaSize.Width;
workspaceBlock.ScaledCopyTo(
ref colorBufferRow[xColorBufferStart],
destAreaStride,
subSamplingDivisors.Width,
subSamplingDivisors.Height);
colorBufferRow[xColorBufferStart] = DC;
//// Integer to float
//workspaceBlock.LoadFrom(ref blockRow[xBlock]);
//// Dequantize
//workspaceBlock.MultiplyInPlace(ref dequantTable);
//// Convert from spectral to color
//FastFloatingPointDCT.TransformIDCT(ref workspaceBlock);
//// To conform better to libjpeg we actually NEED TO loose precision here.
//// This is because they store blocks as Int16 between all the operations.
//// To be "more accurate", we need to emulate this by rounding!
//workspaceBlock.NormalizeColorsAndRoundInPlace(maximumValue);
//// Write to color buffer acording to sampling factors
//int xColorBufferStart = xBlock * this.blockAreaSize.Width;
//workspaceBlock.ScaledCopyTo(
// ref colorBufferRow[xColorBufferStart],
// destAreaStride,
// subSamplingDivisors.Width,
// subSamplingDivisors.Height);
}
}
}

Loading…
Cancel
Save