Browse Source

Minor cleanup of jpeg encoder

pull/20/head
James Jackson-South 10 years ago
parent
commit
ec0316c54c
  1. 3
      Settings.StyleCop
  2. 115
      src/ImageSharp/Formats/Jpg/JpegEncoderCore.cs

3
Settings.StyleCop

@ -21,6 +21,9 @@
<Value>scanline</Value>
<Value>scanlines</Value>
<Value>png's</Value>
<Value>codeword</Value>
<Value>unscaled</Value>
<Value>zig-zag</Value>
</CollectionProperty>
</GlobalSettings>
<Analyzers>

115
src/ImageSharp/Formats/Jpg/JpegEncoderCore.cs

@ -2,14 +2,18 @@
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Formats
{
using System;
using System.IO;
/// <summary>
/// Image encoder for writing an image to a stream as a jpeg.
/// </summary>
internal class JpegEncoderCore
{
private const int NQuantIndex = 2;
/// <summary>
/// Maps from the zig-zag ordering to the natural ordering. For example,
/// unzig[3] is the column and row of the fourth element in zig-zag order. The
@ -23,12 +27,10 @@ namespace ImageSharp.Formats
39, 46, 53, 60, 61, 54, 47, 55, 62, 63,
};
private const int NQuantIndex = 2;
/// <summary>
/// Counts the number of bits needed to hold an integer.
/// </summary>
private readonly byte[] bitCount =
private readonly byte[] bitCountLut =
{
0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
@ -143,48 +145,6 @@ namespace ImageSharp.Formats
})
};
/// <summary>
/// A compiled look-up table representation of a huffmanSpec.
/// Each value maps to a uint32 of which the 8 most significant bits hold the
/// codeword size in bits and the 24 least significant bits hold the codeword.
/// The maximum codeword size is 16 bits.
/// </summary>
private class HuffmanLut
{
public readonly uint[] Values;
public HuffmanLut(HuffmanSpec s)
{
int maxValue = 0;
foreach (var v in s.Values)
{
if (v > maxValue)
{
maxValue = v;
}
}
this.Values = new uint[maxValue + 1];
int code = 0;
int k = 0;
for (int i = 0; i < s.Count.Length; i++)
{
int nBits = (i + 1) << 24;
for (int j = 0; j < s.Count[i]; j++)
{
this.Values[s.Values[k]] = (uint)(nBits | code);
code++;
k++;
}
code <<= 1;
}
}
}
// w is the writer to write to. err is the first error encountered during
// writing. All attempted writes after the first error become no-ops.
private Stream outputStream;
@ -220,10 +180,10 @@ namespace ImageSharp.Formats
/// <summary>
/// Writes the given byte to the stream.
/// </summary>
/// <param name="b"></param>
/// <param name="b">The byte to write.</param>
private void WriteByte(byte b)
{
var data = new byte[1];
byte[] data = new byte[1];
data[0] = b;
this.outputStream.Write(data, 0, 1);
}
@ -286,11 +246,11 @@ namespace ImageSharp.Formats
uint bt;
if (a < 0x100)
{
bt = this.bitCount[a];
bt = this.bitCountLut[a];
}
else
{
bt = 8 + (uint)this.bitCount[a >> 8];
bt = 8 + (uint)this.bitCountLut[a >> 8];
}
this.EmitHuff(index, (int)((uint)(runLength << 4) | bt));
@ -318,7 +278,7 @@ namespace ImageSharp.Formats
this.EmitHuffRLE((HuffIndex)((2 * (int)index) + 0), 0, dc - prevDC);
// Emit the AC components.
var h = (HuffIndex)((2 * (int)index) + 1);
HuffIndex h = (HuffIndex)((2 * (int)index) + 1);
int runLength = 0;
for (int zig = 1; zig < Block.BlockSize; zig++)
@ -715,7 +675,7 @@ namespace ImageSharp.Formats
specs = new[] { this.theHuffmanSpec[0], this.theHuffmanSpec[1] };
}
foreach (var s in specs)
foreach (HuffmanSpec s in specs)
{
markerlen += 1 + 16 + s.Values.Length;
}
@ -734,7 +694,7 @@ namespace ImageSharp.Formats
/// <summary>
/// Writes the StartOfScan marker.
/// </summary>
/// <param name="pixels">The pixel accessor providing acces to the image pixels.</param>
/// <param name="pixels">The pixel accessor providing access to the image pixels.</param>
private void WriteSOS<TColor, TPacked>(PixelAccessor<TColor, TPacked> pixels)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
@ -871,6 +831,55 @@ namespace ImageSharp.Formats
Chrominance = 1,
}
/// <summary>
/// A compiled look-up table representation of a huffmanSpec.
/// Each value maps to a uint32 of which the 8 most significant bits hold the
/// codeword size in bits and the 24 least significant bits hold the codeword.
/// The maximum codeword size is 16 bits.
/// </summary>
private class HuffmanLut
{
/// <summary>
/// The collection of huffman values.
/// </summary>
public readonly uint[] Values;
/// <summary>
/// Initializes a new instance of the <see cref="HuffmanLut"/> class.
/// </summary>
/// <param name="spec">The encoding specifications.</param>
public HuffmanLut(HuffmanSpec spec)
{
int maxValue = 0;
foreach (byte v in spec.Values)
{
if (v > maxValue)
{
maxValue = v;
}
}
this.Values = new uint[maxValue + 1];
int code = 0;
int k = 0;
for (int i = 0; i < spec.Count.Length; i++)
{
int bits = (i + 1) << 24;
for (int j = 0; j < spec.Count[i]; j++)
{
this.Values[spec.Values[k]] = (uint)(bits | code);
code++;
k++;
}
code <<= 1;
}
}
}
/// <summary>
/// The Huffman encoding specifications.
/// </summary>

Loading…
Cancel
Save