Browse Source

Style Stalin

af/merge-core
antonfirsov 10 years ago
parent
commit
f3a3391cd6
  1. 6
      src/ImageSharp/Formats/Jpg/Components/Block8x8F.cs
  2. 2
      src/ImageSharp/Formats/Jpg/Components/Decoder/HuffmanTree.cs
  3. 6
      src/ImageSharp/Formats/Jpg/Components/Encoder/HuffIndex.cs
  4. 45
      src/ImageSharp/Formats/Jpg/Components/Encoder/HuffmanLut.cs
  5. 166
      src/ImageSharp/Formats/Jpg/Components/Encoder/HuffmanSpec.cs
  6. 12
      src/ImageSharp/Formats/Jpg/Components/Encoder/QuantIndex.cs
  7. 253
      src/ImageSharp/Formats/Jpg/JpegEncoderCore.cs
  8. 80
      src/ImageSharp/Formats/Jpg/Utils/JpegUtils.cs

6
src/ImageSharp/Formats/Jpg/Components/Block8x8F.cs

@ -3,7 +3,6 @@
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
// </copyright> // </copyright>
// ReSharper disable InconsistentNaming // ReSharper disable InconsistentNaming
namespace ImageSharp.Formats namespace ImageSharp.Formats
{ {
using System; using System;
@ -19,6 +18,7 @@ namespace ImageSharp.Formats
internal partial struct Block8x8F internal partial struct Block8x8F
{ {
#pragma warning disable SA1204 // Static members must appear before non-static members #pragma warning disable SA1204 // Static members must appear before non-static members
/// <summary> /// <summary>
/// Vector count /// Vector count
/// </summary> /// </summary>
@ -116,7 +116,7 @@ namespace ImageSharp.Formats
float* fPtr = (float*)blockPtr; float* fPtr = (float*)blockPtr;
for (int i = 0; i < ScalarCount; i++) for (int i = 0; i < ScalarCount; i++)
{ {
dest[i] = (byte) *fPtr; dest[i] = (byte)*fPtr;
fPtr++; fPtr++;
} }
} }
@ -146,7 +146,7 @@ namespace ImageSharp.Formats
Marshal.Copy((IntPtr)ptr, dest.Data, dest.Offset, ScalarCount); Marshal.Copy((IntPtr)ptr, dest.Data, dest.Offset, ScalarCount);
} }
} }
/// <summary> /// <summary>
/// Copy raw 32bit floating point data to dest /// Copy raw 32bit floating point data to dest
/// </summary> /// </summary>

2
src/ImageSharp/Formats/Jpg/Components/Decoder/HuffmanTree.cs

@ -1,4 +1,4 @@
// <copyright file="Huffman.cs" company="James Jackson-South"> // <copyright file="HuffmanTree.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors. // Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
// </copyright> // </copyright>

6
src/ImageSharp/Formats/Jpg/Components/Encoder/HuffIndex.cs

@ -1,4 +1,8 @@
namespace ImageSharp.Formats.Jpg.Components.Encoder // <copyright file="HuffIndex.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.Encoder
{ {
/// <summary> /// <summary>
/// Enumerates the Huffman tables /// Enumerates the Huffman tables

45
src/ImageSharp/Formats/Jpg/Components/Encoder/HuffmanLut.cs

@ -1,4 +1,9 @@
namespace ImageSharp.Formats.Jpg.Components.Encoder // <copyright file="HuffmanLut.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.Encoder
{ {
/// <summary> /// <summary>
/// A compiled look-up table representation of a huffmanSpec. /// A compiled look-up table representation of a huffmanSpec.
@ -9,9 +14,26 @@
internal struct HuffmanLut internal struct HuffmanLut
{ {
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="HuffmanLut"/> class. /// The compiled representations of theHuffmanSpec.
/// </summary>
public static readonly HuffmanLut[] TheHuffmanLut = new HuffmanLut[4];
/// <summary>
/// Initializes static members of the <see cref="HuffmanLut"/> struct.
/// </summary>
static HuffmanLut()
{
// Initialize the Huffman tables
for (int i = 0; i < HuffmanSpec.TheHuffmanSpecs.Length; i++)
{
TheHuffmanLut[i] = new HuffmanLut(HuffmanSpec.TheHuffmanSpecs[i]);
}
}
/// <summary>
/// Initializes a new instance of the <see cref="HuffmanLut"/> struct.
/// </summary> /// </summary>
/// <param name="spec">The encoding specifications.</param> /// <param name="spec">dasd</param>
public HuffmanLut(HuffmanSpec spec) public HuffmanLut(HuffmanSpec spec)
{ {
int maxValue = 0; int maxValue = 0;
@ -43,26 +65,9 @@
} }
} }
/// <summary>
/// Initialize static members
/// </summary>
static HuffmanLut()
{
// Initialize the Huffman tables
for (int i = 0; i < HuffmanSpec.TheHuffmanSpecs.Length; i++)
{
HuffmanLut.TheHuffmanLut[i] = new HuffmanLut(HuffmanSpec.TheHuffmanSpecs[i]);
}
}
/// <summary> /// <summary>
/// Gets the collection of huffman values. /// Gets the collection of huffman values.
/// </summary> /// </summary>
public uint[] Values { get; } public uint[] Values { get; }
/// <summary>
/// The compiled representations of theHuffmanSpec.
/// </summary>
public static readonly HuffmanLut[] TheHuffmanLut = new HuffmanLut[4];
} }
} }

166
src/ImageSharp/Formats/Jpg/Components/Encoder/HuffmanSpec.cs

@ -1,35 +1,19 @@
namespace ImageSharp.Formats.Jpg.Components.Encoder // <copyright file="HuffmanSpec.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.Encoder
{ {
/// <summary> /// <summary>
/// The Huffman encoding specifications. /// The Huffman encoding specifications.
/// </summary> /// </summary>
internal struct HuffmanSpec internal struct HuffmanSpec
{ {
/// <summary>
/// Gets count[i] - The number of codes of length i bits.
/// </summary>
public readonly byte[] Count;
/// <summary>
/// Gets value[i] - The decoded value of the codeword at the given index.
/// </summary>
public readonly byte[] Values;
/// <summary>
/// Initializes a new instance of the <see cref="HuffmanSpec"/> struct.
/// </summary>
/// <param name="count">The number of codes.</param>
/// <param name="values">The decoded values.</param>
public HuffmanSpec(byte[] count, byte[] values)
{
this.Count = count;
this.Values = values;
}
#pragma warning disable SA1118 // ParameterMustNotSpanMultipleLines #pragma warning disable SA1118 // ParameterMustNotSpanMultipleLines
/// <summary> /// <summary>
/// The Huffman encoding specifications. /// The Huffman encoding specifications.
/// This encoder uses the same Huffman encoding for all images. /// This encoder uses the same Huffman encoding for all images.
/// </summary> /// </summary>
public static readonly HuffmanSpec[] TheHuffmanSpecs = public static readonly HuffmanSpec[] TheHuffmanSpecs =
{ {
@ -37,76 +21,116 @@
new HuffmanSpec( new HuffmanSpec(
new byte[] new byte[]
{ {
0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
0, 0, 0
}, },
new byte[] new byte[]
{ {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
}), }),
new HuffmanSpec( new HuffmanSpec(
new byte[] new byte[]
{ {
0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 125 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0,
0, 1, 125
}, },
new byte[] new byte[]
{ {
0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11,
0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13,
0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32,
0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1,
0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33,
0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17,
0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38,
0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47,
0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56,
0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65,
0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74,
0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83,
0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a,
0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6,
0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2,
0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9,
0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4,
0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1,
0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
0xf9, 0xfa
}), }),
new HuffmanSpec( new HuffmanSpec(
new byte[] new byte[]
{ {
0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
0, 0, 0
}, },
new byte[] new byte[]
{ {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
}), }),
// Chrominance AC. // Chrominance AC.
new HuffmanSpec( new HuffmanSpec(
new byte[] new byte[]
{ {
0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 119 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0,
1, 2, 119
}, },
new byte[] new byte[]
{ {
0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51,
0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81,
0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1,
0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62,
0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1,
0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37,
0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46,
0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55,
0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73,
0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a,
0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4,
0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2,
0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5,
0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3,
0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
0xf9, 0xfa
}) })
}; };
#pragma warning restore SA1118 // ParameterMustNotSpanMultipleLines #pragma warning restore SA1118 // ParameterMustNotSpanMultipleLines
/// <summary>
/// Gets count[i] - The number of codes of length i bits.
/// </summary>
public readonly byte[] Count;
/// <summary>
/// Gets value[i] - The decoded value of the codeword at the given index.
/// </summary>
public readonly byte[] Values;
/// <summary>
/// Initializes a new instance of the <see cref="HuffmanSpec"/> struct.
/// </summary>
/// <param name="count">
/// The number of codes.
/// </param>
/// <param name="values">
/// The decoded values.
/// </param>
public HuffmanSpec(byte[] count, byte[] values)
{
this.Count = count;
this.Values = values;
}
} }
} }

12
src/ImageSharp/Formats/Jpg/Components/Encoder/QuantIndex.cs

@ -1,17 +1,21 @@
namespace ImageSharp.Formats.Jpg.Components.Encoder // <copyright file="QuantIndex.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.Encoder
{ {
/// <summary> /// <summary>
/// Enumerates the quantization tables /// Enumerates the quantization tables
/// </summary> /// </summary>
internal enum QuantIndex internal enum QuantIndex
{ {
/// <summary> /// <summary>
/// The luminance quantization table index /// The luminance quantization table index
/// </summary> /// </summary>
Luminance = 0, Luminance = 0,
/// <summary> /// <summary>
/// The chrominance quantization table index /// The chrominance quantization table index
/// </summary> /// </summary>
Chrominance = 1, Chrominance = 1,
} }

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

@ -10,22 +10,21 @@ namespace ImageSharp.Formats
using System.Numerics; using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using ImageSharp.Formats.Jpg.Components;
using ImageSharp.Formats.Jpg.Components.Encoder; using ImageSharp.Formats.Jpg.Components.Encoder;
using ImageSharp.Formats.Jpg.Utils; using ImageSharp.Formats.Jpg.Utils;
/// <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 =
{ {
@ -45,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 =
{ {
@ -78,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 =
{ {
@ -104,58 +103,69 @@ 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 + identifier. /// A buffer for reducing the number of stream writes when emitting Huffman tables. Max combined table lengths +
/// 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">The pixel format.</typeparam> /// <typeparam name="TColor">
/// <param name="image">The image to write from.</param> /// The pixel format.
/// <param name="stream">The stream to write to.</param> /// </typeparam>
/// <param name="quality">The quality.</param> /// <param name="image">
/// <param name="sample">The subsampling mode.</param> /// The image to write from.
/// </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>
{ {
@ -249,14 +259,30 @@ 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">The pixel format.</typeparam> /// <typeparam name="TColor">
/// <param name="pixels">The pixel accessor.</param> /// The pixel format.
/// <param name="x">The x-position within the image.</param> /// </typeparam>
/// <param name="y">The y-position within the image.</param> /// <param name="pixels">
/// <param name="yBlock">The luminance block.</param> /// The pixel accessor.
/// <param name="cbBlock">The red chroma block.</param> /// </param>
/// <param name="crBlock">The blue chroma block.</param> /// <param name="x">
/// <param name="rgbBytes">Temporal <see cref="PixelArea{TColor}"/> provided by the caller</param> /// The x-position within the image.
/// </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,
@ -264,7 +290,8 @@ namespace ImageSharp.Formats
Block8x8F* yBlock, Block8x8F* yBlock,
Block8x8F* cbBlock, Block8x8F* cbBlock,
Block8x8F* crBlock, Block8x8F* crBlock,
PixelArea<TColor> rgbBytes) where TColor : struct, IPackedPixel, IEquatable<TColor> PixelArea<TColor> rgbBytes)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{ {
float* yBlockRaw = (float*)yBlock; float* yBlockRaw = (float*)yBlock;
float* cbBlockRaw = (float*)cbBlock; float* cbBlockRaw = (float*)cbBlock;
@ -300,10 +327,18 @@ 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 <example>&lt; 1&lt;&lt;nBits &amp;&amp; nBits &lt;= 16</example>. /// The precondition is bits
/// <example>
/// &lt; 1&lt;&lt;nBits &amp;&amp; nBits &lt;= 16
/// </example>
/// .
/// </summary> /// </summary>
/// <param name="bits">The packed bits.</param> /// <param name="bits">
/// <param name="count">The number of bits</param> /// The packed bits.
/// </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;
@ -341,8 +376,12 @@ 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">The index of the Huffman encoder</param> /// <param name="index">
/// <param name="value">The value to encode.</param> /// The index of the Huffman encoder
/// </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)
{ {
@ -353,9 +392,15 @@ 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">The index of the Huffman encoder</param> /// <param name="index">
/// <param name="runLength">The number of copies to encode.</param> /// The index of the Huffman encoder
/// <param name="value">The value to encode.</param> /// </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)
{ {
@ -387,8 +432,12 @@ namespace ImageSharp.Formats
/// <summary> /// <summary>
/// Encodes the image with no subsampling. /// Encodes the image with no subsampling.
/// </summary> /// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam> /// <typeparam name="TColor">
/// <param name="pixels">The pixel accessor providing access to the image pixels.</param> /// The pixel format.
/// </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>
{ {
@ -448,8 +497,12 @@ 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">The resolution of the image in the x- direction.</param> /// <param name="horizontalResolution">
/// <param name="verticalResolution">The resolution of the image in the y- direction.</param> /// The resolution of the image in the x- direction.
/// </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.
@ -487,17 +540,33 @@ 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">The quantization table index.</param> /// <param name="index">
/// <param name="prevDC">The previous DC value.</param> /// The quantization table index.
/// <param name="src">Source block</param> /// </param>
/// <param name="tempDest">Temporal block to be used as FDCT Destination</param> /// <param name="prevDC">
/// <param name="temp2">Temporal block 2</param> /// The previous DC value.
/// <param name="quant">Quantization table</param> /// </param>
/// <param name="unzigPtr">The 8x8 Unzig block ptr</param> /// <param name="src">
/// <returns>The <see cref="int"/></returns> /// 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>
/// The <see cref="int"/>
/// </returns>
private float WriteBlock( private float WriteBlock(
QuantIndex index, QuantIndex index,
float prevDC, float prevDC,
@ -554,7 +623,9 @@ 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">The number of components to write.</param> /// <param name="componentCount">
/// The number of components to write.
/// </param>
private void WriteDefineHuffmanTables(int componentCount) private void WriteDefineHuffmanTables(int componentCount)
{ {
// Table identifiers. // Table identifiers.
@ -601,7 +672,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()
{ {
@ -625,7 +696,9 @@ namespace ImageSharp.Formats
/// <summary> /// <summary>
/// Writes the EXIF profile. /// Writes the EXIF profile.
/// </summary> /// </summary>
/// <param name="exifProfile">The exif profile.</param> /// <param name="exifProfile">
/// 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>
@ -657,9 +730,14 @@ namespace ImageSharp.Formats
/// <summary> /// <summary>
/// Writes the metadata profiles to the image. /// Writes the metadata profiles to the image.
/// </summary> /// </summary>
/// <param name="image">The image.</param> /// <param name="image">
/// <typeparam name="TColor">The pixel format.</typeparam> /// The image.
private void WriteProfiles<TColor>(Image<TColor> image) where TColor : struct, IPackedPixel, IEquatable<TColor> /// </param>
/// <typeparam name="TColor">
/// The pixel format.
/// </typeparam>
private void WriteProfiles<TColor>(Image<TColor> image)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{ {
this.WriteProfile(image.ExifProfile); this.WriteProfile(image.ExifProfile);
} }
@ -667,9 +745,15 @@ namespace ImageSharp.Formats
/// <summary> /// <summary>
/// Writes the Start Of Frame (Baseline) marker /// Writes the Start Of Frame (Baseline) marker
/// </summary> /// </summary>
/// <param name="width">The width of the image</param> /// <param name="width">
/// <param name="height">The height of the image</param> /// The width of the image
/// <param name="componentCount">The number of components in a pixel</param> /// </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
@ -723,7 +807,9 @@ namespace ImageSharp.Formats
/// <summary> /// <summary>
/// Writes the StartOfScan marker. /// Writes the StartOfScan marker.
/// </summary> /// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam> /// <typeparam name="TColor">
/// The pixel format.
/// </typeparam>
/// <param name="pixels"> /// <param name="pixels">
/// The pixel accessor providing access to the image pixels. /// The pixel accessor providing access to the image pixels.
/// </param> /// </param>
@ -751,8 +837,9 @@ namespace ImageSharp.Formats
#pragma warning disable SA1201 // MethodShouldNotFollowAStruct #pragma warning disable SA1201 // MethodShouldNotFollowAStruct
/// <summary> /// <summary>
/// Poor man's stackalloc for Encode420. /// 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 /// 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> /// </summary>
private struct BlockQuad private struct BlockQuad
{ {
@ -761,10 +848,14 @@ namespace ImageSharp.Formats
/// <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">The pixel format.</typeparam> /// <typeparam name="TColor">
/// <param name="pixels">The pixel accessor providing access to the image pixels.</param> /// The pixel format.
/// </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>
{ {
@ -838,8 +929,12 @@ namespace ImageSharp.Formats
/// <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">The marker to write.</param> /// <param name="marker">
/// <param name="length">The marker length.</param> /// The marker to write.
/// </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.

80
src/ImageSharp/Formats/Jpg/Utils/JpegUtils.cs

@ -10,18 +10,29 @@ namespace ImageSharp.Formats.Jpg.Utils
using ImageSharp.Formats.Jpg.Components.Encoder; using ImageSharp.Formats.Jpg.Components.Encoder;
/// <summary> /// <summary>
/// Jpeg specific utilities and extension methods /// Jpeg specific utilities and extension methods
/// </summary> /// </summary>
internal static unsafe class JpegUtils internal static unsafe class JpegUtils
{ {
/// <summary> /// <summary>
/// Copy a region of an image into dest. De "outlier" area will be stretched out with pixels on the right and bottom of the image. /// Copy a region of an image into dest. De "outlier" area will be stretched out with pixels on the right and bottom of
/// the image.
/// </summary> /// </summary>
/// <typeparam name="TColor">The pixel type</typeparam> /// <typeparam name="TColor">
/// <param name="pixels">The input pixel acessor</param> /// The pixel type
/// <param name="dest">The destination <see cref="PixelArea{TColor}"/> </param> /// </typeparam>
/// <param name="sourceY">Starting Y coord</param> /// <param name="pixels">
/// <param name="sourceX">Starting X coord</param> /// The input pixel acessor
/// </param>
/// <param name="dest">
/// The destination <see cref="PixelArea{TColor}"/>
/// </param>
/// <param name="sourceY">
/// Starting Y coord
/// </param>
/// <param name="sourceX">
/// Starting X coord
/// </param>
public static void CopyRGBBytesStretchedTo<TColor>( public static void CopyRGBBytesStretchedTo<TColor>(
this PixelAccessor<TColor> pixels, this PixelAccessor<TColor> pixels,
PixelArea<TColor> dest, PixelArea<TColor> dest,
@ -38,8 +49,12 @@ namespace ImageSharp.Formats.Jpg.Utils
/// <summary> /// <summary>
/// Copy an RGB value /// Copy an RGB value
/// </summary> /// </summary>
/// <param name="source">Source pointer</param> /// <param name="source">
/// <param name="dest">Destination pointer</param> /// Source pointer
/// </param>
/// <param name="dest">
/// Destination pointer
/// </param>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void CopyRgb(byte* source, byte* dest) internal static void CopyRgb(byte* source, byte* dest)
{ {
@ -48,6 +63,37 @@ namespace ImageSharp.Formats.Jpg.Utils
*dest = *source; // B *dest = *source; // B
} }
/// <summary>
/// Writes data to "Define Quantization Tables" block for QuantIndex
/// </summary>
/// <param name="dqt">
/// The "Define Quantization Tables" block
/// </param>
/// <param name="offset">
/// Offset in dqt
/// </param>
/// <param name="i">
/// The quantization index
/// </param>
/// <param name="q">
/// The quantazation table to copy data from
/// </param>
internal static void WriteDataToDqt(byte[] dqt, ref int offset, QuantIndex i, ref Block8x8F q)
{
dqt[offset++] = (byte)i;
for (int j = 0; j < Block8x8F.ScalarCount; j++)
{
dqt[offset++] = (byte)q[j];
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool IsInvalidStretchArea<TColor>(PixelArea<TColor> area, int fromX, int fromY)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return fromX <= 0 || fromY <= 0 || fromX >= area.Width || fromY >= area.Height;
}
private static void StretchPixels<TColor>(PixelArea<TColor> area, int fromX, int fromY) private static void StretchPixels<TColor>(PixelArea<TColor> area, int fromX, int fromY)
where TColor : struct, IPackedPixel, IEquatable<TColor> where TColor : struct, IPackedPixel, IEquatable<TColor>
{ {
@ -84,21 +130,5 @@ namespace ImageSharp.Formats.Jpg.Utils
} }
} }
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool IsInvalidStretchArea<TColor>(PixelArea<TColor> area, int fromX, int fromY)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return fromX <= 0 || fromY <= 0 || fromX >= area.Width || fromY >= area.Height;
}
internal static void WriteDataToDqt(byte[] dqt, ref int offset, QuantIndex i, ref Block8x8F q)
{
dqt[offset++] = (byte)i;
for (int j = 0; j < Block8x8F.ScalarCount; j++)
{
dqt[offset++] = (byte)q[j];
}
}
} }
} }
Loading…
Cancel
Save