Browse Source

comment cleanup & BlockQuad

pull/58/head
Anton Firszov 10 years ago
parent
commit
2c8d09986c
  1. 18
      src/ImageSharp/Formats/Jpg/Components/BlockQuad.cs
  2. 255
      src/ImageSharp/Formats/Jpg/JpegEncoderCore.cs

18
src/ImageSharp/Formats/Jpg/Components/BlockQuad.cs

@ -0,0 +1,18 @@
// <copyright file="BlockQuad.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.Components
{
/// <summary>
/// Poor man's stackalloc: Contains a value-type <see cref="float"/> buffer sized for 4 <see cref="Block8x8F"/> instances.
/// Useful for decoder/encoder operations allocating a block for each Jpeg component.
/// </summary>
internal unsafe struct BlockQuad
{
/// <summary>
/// The value-type <see cref="float"/> buffer sized for 4 <see cref="Block8x8F"/> instances.
/// </summary>
public fixed float Data[4 * Block8x8F.ScalarCount];
}
}

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

@ -11,19 +11,20 @@ namespace ImageSharp.Formats
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using ImageSharp.Formats.Jpg; using ImageSharp.Formats.Jpg;
using ImageSharp.Formats.Jpg.Components;
/// <summary> /// <summary>
/// Image encoder for writing an image to a stream as a jpeg. /// Image encoder for writing an image to a stream as a jpeg.
/// </summary> /// </summary>
internal unsafe class JpegEncoderCore internal unsafe class JpegEncoderCore
{ {
/// <summary> /// <summary>
/// The number of quantization tables. /// The number of quantization tables.
/// </summary> /// </summary>
private const int QuantizationTableCount = 2; private const int QuantizationTableCount = 2;
/// <summary> /// <summary>
/// Counts the number of bits needed to hold an integer. /// Counts the number of bits needed to hold an integer.
/// </summary> /// </summary>
private static readonly uint[] BitCountLut = private static readonly uint[] BitCountLut =
{ {
@ -43,15 +44,15 @@ namespace ImageSharp.Formats
}; };
/// <summary> /// <summary>
/// The SOS (Start Of Scan) marker "\xff\xda" followed by 12 bytes: /// The SOS (Start Of Scan) marker "\xff\xda" followed by 12 bytes:
/// - the marker length "\x00\x0c", /// - the marker length "\x00\x0c",
/// - the number of components "\x03", /// - the number of components "\x03",
/// - component 1 uses DC table 0 and AC table 0 "\x01\x00", /// - component 1 uses DC table 0 and AC table 0 "\x01\x00",
/// - component 2 uses DC table 1 and AC table 1 "\x02\x11", /// - component 2 uses DC table 1 and AC table 1 "\x02\x11",
/// - component 3 uses DC table 1 and AC table 1 "\x03\x11", /// - component 3 uses DC table 1 and AC table 1 "\x03\x11",
/// - the bytes "\x00\x3f\x00". Section B.2.3 of the spec says that for /// - the bytes "\x00\x3f\x00". Section B.2.3 of the spec says that for
/// sequential DCTs, those bytes (8-bit Ss, 8-bit Se, 4-bit Ah, 4-bit Al) /// sequential DCTs, those bytes (8-bit Ss, 8-bit Se, 4-bit Ah, 4-bit Al)
/// should be 0x00, 0x3f, 0x00&lt;&lt;4 | 0x00. /// should be 0x00, 0x3f, 0x00&lt;&lt;4 | 0x00.
/// </summary> /// </summary>
private static readonly byte[] SosHeaderYCbCr = private static readonly byte[] SosHeaderYCbCr =
{ {
@ -76,10 +77,10 @@ namespace ImageSharp.Formats
}; };
/// <summary> /// <summary>
/// The unscaled quantization tables in zig-zag order. Each /// The unscaled quantization tables in zig-zag order. Each
/// encoder copies and scales the tables according to its quality parameter. /// encoder copies and scales the tables according to its quality parameter.
/// The values are derived from section K.1 after converting from natural to /// The values are derived from section K.1 after converting from natural to
/// zig-zag order. /// zig-zag order.
/// </summary> /// </summary>
private static readonly byte[,] UnscaledQuant = private static readonly byte[,] UnscaledQuant =
{ {
@ -102,69 +103,59 @@ namespace ImageSharp.Formats
}; };
/// <summary> /// <summary>
/// A scratch buffer to reduce allocations. /// A scratch buffer to reduce allocations.
/// </summary> /// </summary>
private readonly byte[] buffer = new byte[16]; private readonly byte[] buffer = new byte[16];
/// <summary> /// <summary>
/// A buffer for reducing the number of stream writes when emitting Huffman tables. 64 seems to be enough. /// A buffer for reducing the number of stream writes when emitting Huffman tables. 64 seems to be enough.
/// </summary> /// </summary>
private readonly byte[] emitBuffer = new byte[64]; private readonly byte[] emitBuffer = new byte[64];
/// <summary> /// <summary>
/// A buffer for reducing the number of stream writes when emitting Huffman tables. Max combined table lengths + /// A buffer for reducing the number of stream writes when emitting Huffman tables. Max combined table lengths +
/// identifier. /// identifier.
/// </summary> /// </summary>
private readonly byte[] huffmanBuffer = new byte[179]; private readonly byte[] huffmanBuffer = new byte[179];
/// <summary> /// <summary>
/// The accumulated bits to write to the stream. /// The accumulated bits to write to the stream.
/// </summary> /// </summary>
private uint accumulatedBits; private uint accumulatedBits;
/// <summary> /// <summary>
/// The accumulated bit count. /// The accumulated bit count.
/// </summary> /// </summary>
private uint bitCount; private uint bitCount;
/// <summary> /// <summary>
/// The scaled chrominance table, in zig-zag order. /// The scaled chrominance table, in zig-zag order.
/// </summary> /// </summary>
private Block8x8F chrominanceQuantTable; private Block8x8F chrominanceQuantTable;
/// <summary> /// <summary>
/// The scaled luminance table, in zig-zag order. /// The scaled luminance table, in zig-zag order.
/// </summary> /// </summary>
private Block8x8F luminanceQuantTable; private Block8x8F luminanceQuantTable;
/// <summary> /// <summary>
/// The output stream. All attempted writes after the first error become no-ops. /// The output stream. All attempted writes after the first error become no-ops.
/// </summary> /// </summary>
private Stream outputStream; private Stream outputStream;
/// <summary> /// <summary>
/// The subsampling method to use. /// The subsampling method to use.
/// </summary> /// </summary>
private JpegSubsample subsample; private JpegSubsample subsample;
/// <summary> /// <summary>
/// Encode writes the image to the jpeg baseline format with the given options. /// Encode writes the image to the jpeg baseline format with the given options.
/// </summary> /// </summary>
/// <typeparam name="TColor"> /// <typeparam name="TColor">The pixel format.</typeparam>
/// The pixel format. /// <param name="image">The image to write from.</param>
/// </typeparam> /// <param name="stream">The stream to write to.</param>
/// <param name="image"> /// <param name="quality">The quality.</param>
/// The image to write from. /// <param name="sample">The subsampling mode.</param>
/// </param>
/// <param name="stream">
/// The stream to write to.
/// </param>
/// <param name="quality">
/// The quality.
/// </param>
/// <param name="sample">
/// The subsampling mode.
/// </param>
public void Encode<TColor>(Image<TColor> image, Stream stream, int quality, JpegSubsample sample) public void Encode<TColor>(Image<TColor> image, Stream stream, int quality, JpegSubsample sample)
where TColor : struct, IPackedPixel, IEquatable<TColor> where TColor : struct, IPackedPixel, IEquatable<TColor>
{ {
@ -258,30 +249,14 @@ namespace ImageSharp.Formats
/// <summary> /// <summary>
/// Converts the 8x8 region of the image whose top-left corner is x,y to its YCbCr values. /// Converts the 8x8 region of the image whose top-left corner is x,y to its YCbCr values.
/// </summary> /// </summary>
/// <typeparam name="TColor"> /// <typeparam name="TColor">The pixel format.</typeparam>
/// The pixel format. /// <param name="pixels">The pixel accessor.</param>
/// </typeparam> /// <param name="x">The x-position within the image.</param>
/// <param name="pixels"> /// <param name="y">The y-position within the image.</param>
/// The pixel accessor. /// <param name="yBlock">The luminance block.</param>
/// </param> /// <param name="cbBlock">The red chroma block.</param>
/// <param name="x"> /// <param name="crBlock">The blue chroma block.</param>
/// The x-position within the image. /// <param name="rgbBytes">Temporal <see cref="PixelArea{TColor}"/> provided by the caller</param>
/// </param>
/// <param name="y">
/// The y-position within the image.
/// </param>
/// <param name="yBlock">
/// The luminance block.
/// </param>
/// <param name="cbBlock">
/// The red chroma block.
/// </param>
/// <param name="crBlock">
/// The blue chroma block.
/// </param>
/// <param name="rgbBytes">
/// Temporal <see cref="PixelArea{TColor}"/> provided by the caller
/// </param>
private static void ToYCbCr<TColor>( private static void ToYCbCr<TColor>(
PixelAccessor<TColor> pixels, PixelAccessor<TColor> pixels,
int x, int x,
@ -326,18 +301,14 @@ namespace ImageSharp.Formats
/// <summary> /// <summary>
/// Emits the least significant count of bits of bits to the bit-stream. /// Emits the least significant count of bits of bits to the bit-stream.
/// The precondition is bits /// The precondition is bits
/// <example> /// <example>
/// &lt; 1&lt;&lt;nBits &amp;&amp; nBits &lt;= 16 /// &lt; 1&lt;&lt;nBits &amp;&amp; nBits &lt;= 16
/// </example> /// </example>
/// . /// .
/// </summary> /// </summary>
/// <param name="bits"> /// <param name="bits">The packed bits.</param>
/// The packed bits. /// <param name="count">The number of bits</param>
/// </param>
/// <param name="count">
/// The number of bits
/// </param>
private void Emit(uint bits, uint count) private void Emit(uint bits, uint count)
{ {
count += this.bitCount; count += this.bitCount;
@ -375,12 +346,8 @@ namespace ImageSharp.Formats
/// <summary> /// <summary>
/// Emits the given value with the given Huffman encoder. /// Emits the given value with the given Huffman encoder.
/// </summary> /// </summary>
/// <param name="index"> /// <param name="index">The index of the Huffman encoder</param>
/// The index of the Huffman encoder /// <param name="value">The value to encode.</param>
/// </param>
/// <param name="value">
/// The value to encode.
/// </param>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void EmitHuff(HuffIndex index, int value) private void EmitHuff(HuffIndex index, int value)
{ {
@ -391,15 +358,9 @@ namespace ImageSharp.Formats
/// <summary> /// <summary>
/// Emits a run of runLength copies of value encoded with the given Huffman encoder. /// Emits a run of runLength copies of value encoded with the given Huffman encoder.
/// </summary> /// </summary>
/// <param name="index"> /// <param name="index">The index of the Huffman encoder</param>
/// The index of the Huffman encoder /// <param name="runLength">The number of copies to encode.</param>
/// </param> /// <param name="value">The value to encode.</param>
/// <param name="runLength">
/// The number of copies to encode.
/// </param>
/// <param name="value">
/// The value to encode.
/// </param>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void EmitHuffRLE(HuffIndex index, int runLength, int value) private void EmitHuffRLE(HuffIndex index, int runLength, int value)
{ {
@ -431,12 +392,8 @@ namespace ImageSharp.Formats
/// <summary> /// <summary>
/// Encodes the image with no subsampling. /// Encodes the image with no subsampling.
/// </summary> /// </summary>
/// <typeparam name="TColor"> /// <typeparam name="TColor">The pixel format.</typeparam>
/// The pixel format. /// <param name="pixels">The pixel accessor providing access to the image pixels.</param>
/// </typeparam>
/// <param name="pixels">
/// The pixel accessor providing access to the image pixels.
/// </param>
private void Encode444<TColor>(PixelAccessor<TColor> pixels) private void Encode444<TColor>(PixelAccessor<TColor> pixels)
where TColor : struct, IPackedPixel, IEquatable<TColor> where TColor : struct, IPackedPixel, IEquatable<TColor>
{ {
@ -496,12 +453,8 @@ namespace ImageSharp.Formats
/// <summary> /// <summary>
/// Writes the application header containing the JFIF identifier plus extra data. /// Writes the application header containing the JFIF identifier plus extra data.
/// </summary> /// </summary>
/// <param name="horizontalResolution"> /// <param name="horizontalResolution">The resolution of the image in the x- direction.</param>
/// The resolution of the image in the x- direction. /// <param name="verticalResolution">The resolution of the image in the y- direction.</param>
/// </param>
/// <param name="verticalResolution">
/// The resolution of the image in the y- direction.
/// </param>
private void WriteApplicationHeader(short horizontalResolution, short verticalResolution) private void WriteApplicationHeader(short horizontalResolution, short verticalResolution)
{ {
// Write the start of image marker. Markers are always prefixed with with 0xff. // Write the start of image marker. Markers are always prefixed with with 0xff.
@ -539,30 +492,16 @@ namespace ImageSharp.Formats
/// <summary> /// <summary>
/// Writes a block of pixel data using the given quantization table, /// Writes a block of pixel data using the given quantization table,
/// returning the post-quantized DC value of the DCT-transformed block. /// returning the post-quantized DC value of the DCT-transformed block.
/// The block is in natural (not zig-zag) order. /// The block is in natural (not zig-zag) order.
/// </summary> /// </summary>
/// <param name="index"> /// <param name="index">The quantization table index.</param>
/// The quantization table index. /// <param name="prevDC">The previous DC value.</param>
/// </param> /// <param name="src">Source block</param>
/// <param name="prevDC"> /// <param name="tempDest">Temporal block to be used as FDCT Destination</param>
/// The previous DC value. /// <param name="temp2">Temporal block 2</param>
/// </param> /// <param name="quant">Quantization table</param>
/// <param name="src"> /// <param name="unzigPtr">The 8x8 Unzig block ptr</param>
/// Source block
/// </param>
/// <param name="tempDest">
/// Temporal block to be used as FDCT Destination
/// </param>
/// <param name="temp2">
/// Temporal block 2
/// </param>
/// <param name="quant">
/// Quantization table
/// </param>
/// <param name="unzigPtr">
/// The 8x8 Unzig block ptr
/// </param>
/// <returns> /// <returns>
/// The <see cref="int"/> /// The <see cref="int"/>
/// </returns> /// </returns>
@ -622,9 +561,7 @@ namespace ImageSharp.Formats
/// <summary> /// <summary>
/// Writes the Define Huffman Table marker and tables. /// Writes the Define Huffman Table marker and tables.
/// </summary> /// </summary>
/// <param name="componentCount"> /// <param name="componentCount">The number of components to write.</param>
/// The number of components to write.
/// </param>
private void WriteDefineHuffmanTables(int componentCount) private void WriteDefineHuffmanTables(int componentCount)
{ {
// Table identifiers. // Table identifiers.
@ -671,7 +608,7 @@ namespace ImageSharp.Formats
} }
/// <summary> /// <summary>
/// Writes the Define Quantization Marker and tables. /// Writes the Define Quantization Marker and tables.
/// </summary> /// </summary>
private void WriteDefineQuantizationTables() private void WriteDefineQuantizationTables()
{ {
@ -695,9 +632,7 @@ namespace ImageSharp.Formats
/// <summary> /// <summary>
/// Writes the EXIF profile. /// Writes the EXIF profile.
/// </summary> /// </summary>
/// <param name="exifProfile"> /// <param name="exifProfile">The exif profile.</param>
/// The exif profile.
/// </param>
/// <exception cref="ImageFormatException"> /// <exception cref="ImageFormatException">
/// Thrown if the EXIF profile size exceeds the limit /// Thrown if the EXIF profile size exceeds the limit
/// </exception> /// </exception>
@ -729,12 +664,8 @@ namespace ImageSharp.Formats
/// <summary> /// <summary>
/// Writes the metadata profiles to the image. /// Writes the metadata profiles to the image.
/// </summary> /// </summary>
/// <param name="image"> /// <param name="image">The image.</param>
/// The image. /// <typeparam name="TColor">The pixel format.</typeparam>
/// </param>
/// <typeparam name="TColor">
/// The pixel format.
/// </typeparam>
private void WriteProfiles<TColor>(Image<TColor> image) private void WriteProfiles<TColor>(Image<TColor> image)
where TColor : struct, IPackedPixel, IEquatable<TColor> where TColor : struct, IPackedPixel, IEquatable<TColor>
{ {
@ -744,15 +675,9 @@ namespace ImageSharp.Formats
/// <summary> /// <summary>
/// Writes the Start Of Frame (Baseline) marker /// Writes the Start Of Frame (Baseline) marker
/// </summary> /// </summary>
/// <param name="width"> /// <param name="width">The width of the image</param>
/// The width of the image /// <param name="height">The height of the image</param>
/// </param> /// <param name="componentCount">The number of components in a pixel</param>
/// <param name="height">
/// The height of the image
/// </param>
/// <param name="componentCount">
/// The number of components in a pixel
/// </param>
private void WriteStartOfFrame(int width, int height, int componentCount) private void WriteStartOfFrame(int width, int height, int componentCount)
{ {
// "default" to 4:2:0 // "default" to 4:2:0
@ -806,12 +731,8 @@ namespace ImageSharp.Formats
/// <summary> /// <summary>
/// Writes the StartOfScan marker. /// Writes the StartOfScan marker.
/// </summary> /// </summary>
/// <typeparam name="TColor"> /// <typeparam name="TColor">The pixel format.</typeparam>
/// The pixel format. /// <param name="pixels">The pixel accessor providing access to the image pixels.</param>
/// </typeparam>
/// <param name="pixels">
/// The pixel accessor providing access to the image pixels.
/// </param>
private void WriteStartOfScan<TColor>(PixelAccessor<TColor> pixels) private void WriteStartOfScan<TColor>(PixelAccessor<TColor> pixels)
where TColor : struct, IPackedPixel, IEquatable<TColor> where TColor : struct, IPackedPixel, IEquatable<TColor>
{ {
@ -833,28 +754,12 @@ namespace ImageSharp.Formats
this.Emit(0x7f, 7); this.Emit(0x7f, 7);
} }
#pragma warning disable SA1201 // MethodShouldNotFollowAStruct
/// <summary>
/// Poor man's stackalloc for Encode420.
/// This struct belongs to Encode420. Much easeier to understand code if they are close to each other. Why should I
/// move it Up? :P
/// </summary>
private struct BlockQuad
{
public fixed float Data[4 * Block8x8F.ScalarCount];
}
/// <summary> /// <summary>
/// Encodes the image with subsampling. The Cb and Cr components are each subsampled /// Encodes the image with subsampling. The Cb and Cr components are each subsampled
/// at a factor of 2 both horizontally and vertically. /// at a factor of 2 both horizontally and vertically.
/// </summary> /// </summary>
/// <typeparam name="TColor"> /// <typeparam name="TColor">The pixel format.</typeparam>
/// The pixel format. /// <param name="pixels">The pixel accessor providing access to the image pixels.</param>
/// </typeparam>
/// <param name="pixels">
/// The pixel accessor providing access to the image pixels.
/// </param>
private void Encode420<TColor>(PixelAccessor<TColor> pixels) private void Encode420<TColor>(PixelAccessor<TColor> pixels)
where TColor : struct, IPackedPixel, IEquatable<TColor> where TColor : struct, IPackedPixel, IEquatable<TColor>
{ {
@ -923,17 +828,11 @@ namespace ImageSharp.Formats
} }
} }
#pragma warning restore SA1201
/// <summary> /// <summary>
/// Writes the header for a marker with the given length. /// Writes the header for a marker with the given length.
/// </summary> /// </summary>
/// <param name="marker"> /// <param name="marker">The marker to write.</param>
/// The marker to write. /// <param name="length">The marker length.</param>
/// </param>
/// <param name="length">
/// The marker length.
/// </param>
private void WriteMarkerHeader(byte marker, int length) private void WriteMarkerHeader(byte marker, int length)
{ {
// Markers are always prefixed with with 0xff. // Markers are always prefixed with with 0xff.

Loading…
Cancel
Save