diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanLut.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanLut.cs
index c371a199e1..bd4cc5545f 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanLut.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanLut.cs
@@ -26,32 +26,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder
///
internal readonly struct HuffmanLut
{
- ///
- /// The compiled representations of theHuffmanSpec.
- ///
- public static readonly HuffmanLut[] TheHuffmanLut = new HuffmanLut[4];
-
- public static readonly HuffmanLut[] DcHuffmanLut = new HuffmanLut[2];
- public static readonly HuffmanLut[] AcHuffmanLut = new HuffmanLut[2];
-
- ///
- /// Initializes static members of the struct.
- ///
- static HuffmanLut()
- {
- // Initialize the Huffman tables
- for (int i = 0; i < HuffmanSpec.TheHuffmanSpecs.Length; i++)
- {
- TheHuffmanLut[i] = new HuffmanLut(HuffmanSpec.TheHuffmanSpecs[i]);
- }
-
- // TODO: REWRITE THIS
- DcHuffmanLut[0] = new HuffmanLut(HuffmanSpec.TheHuffmanSpecs[0]);
- DcHuffmanLut[1] = new HuffmanLut(HuffmanSpec.TheHuffmanSpecs[2]);
- AcHuffmanLut[0] = new HuffmanLut(HuffmanSpec.TheHuffmanSpecs[1]);
- AcHuffmanLut[1] = new HuffmanLut(HuffmanSpec.TheHuffmanSpecs[3]);
- }
-
///
/// Initializes a new instance of the struct.
///
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanSpec.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanSpec.cs
index 5ec8fd198e..97f051c76c 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanSpec.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanSpec.cs
@@ -8,109 +8,120 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder
///
public readonly struct HuffmanSpec
{
-#pragma warning disable SA1118 // ParameterMustNotSpanMultipleLines
+ ///
+ /// Huffman talbe specification for luminance DC.
+ ///
+ ///
+ /// This is an example specification taken from the jpeg specification paper.
+ ///
+ public static readonly HuffmanSpec LuminanceDC = new(
+ new byte[]
+ {
+ 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
+ 0, 0, 0
+ },
+ new byte[]
+ {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
+ });
///
- /// The Huffman encoding specifications.
- /// This encoder uses the same Huffman encoding for all images.
+ /// Huffman talbe specification for luminance AC.
///
- public static readonly HuffmanSpec[] TheHuffmanSpecs =
+ ///
+ /// This is an example specification taken from the jpeg specification paper.
+ ///
+ public static readonly HuffmanSpec LuminanceAC = new(
+ new byte[]
{
- // Luminance DC.
- new HuffmanSpec(
- new byte[]
- {
- 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
- 0, 0, 0
- },
- new byte[]
- {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
- }),
+ 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0,
+ 0, 1, 125
+ },
+ new byte[]
+ {
+ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11,
+ 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13,
+ 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32,
+ 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1,
+ 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33,
+ 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
+ 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38,
+ 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56,
+ 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65,
+ 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74,
+ 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83,
+ 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a,
+ 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+ 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6,
+ 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 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, 0xe1, 0xe2, 0xe3, 0xe4,
+ 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1,
+ 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xf9, 0xfa
+ });
- // Luminance AC.
- new HuffmanSpec(
- new byte[]
- {
- 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0,
- 0, 1, 125
- },
- new byte[]
- {
- 0x01, 0x02, 0x03, 0x00, 0x04, 0x11,
- 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13,
- 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32,
- 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1,
- 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33,
- 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17,
- 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
- 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38,
- 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47,
- 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56,
- 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65,
- 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74,
- 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83,
- 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a,
- 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
- 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6,
- 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 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, 0xe1, 0xe2, 0xe3, 0xe4,
- 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1,
- 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
- 0xf9, 0xfa
- }),
+ ///
+ /// Huffman talbe specification for chrominance DC.
+ ///
+ ///
+ /// This is an example specification taken from the jpeg specification paper.
+ ///
+ public static readonly HuffmanSpec ChrominanceDC = new(
+ new byte[]
+ {
+ 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+ 0, 0, 0
+ },
+ new byte[]
+ {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
+ });
- // Chrominance DC.
- new HuffmanSpec(
- new byte[]
- {
- 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
- 0, 0, 0
- },
- new byte[]
- {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
- }),
+ ///
+ /// Huffman talbe specification for chrominance DC.
+ ///
+ ///
+ /// This is an example specification taken from the jpeg specification paper.
+ ///
+ public static readonly HuffmanSpec ChrominanceAC = new(
+ new byte[]
+ {
+ 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0,
+ 1, 2, 119
+ },
+ new byte[]
+ {
+ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
+ 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51,
+ 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81,
+ 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1,
+ 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62,
+ 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1,
+ 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
+ 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46,
+ 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55,
+ 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
+ 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73,
+ 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a,
+ 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
+ 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
+ 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4,
+ 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2,
+ 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
+ });
- // Chrominance AC.
- new HuffmanSpec(
- new byte[]
- {
- 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0,
- 1, 2, 119
- },
- new byte[]
- {
- 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
- 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51,
- 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81,
- 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1,
- 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62,
- 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1,
- 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
- 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37,
- 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46,
- 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55,
- 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
- 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73,
- 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a,
- 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
- 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
- 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4,
- 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2,
- 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
///
/// Gets count[i] - The number of codes of length i bits.
///
diff --git a/src/ImageSharp/Formats/Jpeg/JpegEncoder.cs b/src/ImageSharp/Formats/Jpeg/JpegEncoder.cs
index c86f37dd8a..5bad2a5b04 100644
--- a/src/ImageSharp/Formats/Jpeg/JpegEncoder.cs
+++ b/src/ImageSharp/Formats/Jpeg/JpegEncoder.cs
@@ -41,8 +41,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
///
public JpegEncodingColor? ColorType { get; set; }
- internal JpegFrameConfig FrameConfig { get; set; }
-
///
/// Encodes the image to the specified stream from the .
///
diff --git a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.FrameConfig.cs b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.FrameConfig.cs
new file mode 100644
index 0000000000..2397c75639
--- /dev/null
+++ b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.FrameConfig.cs
@@ -0,0 +1,196 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+using SixLabors.ImageSharp.Formats.Jpeg.Components;
+using SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder;
+
+namespace SixLabors.ImageSharp.Formats.Jpeg
+{
+ ///
+ /// Image encoder for writing an image to a stream as a jpeg.
+ ///
+ internal sealed unsafe partial class JpegEncoderCore
+ {
+ private static JpegFrameConfig[] CreateFrameConfigs()
+ {
+ var defaultLuminanceHuffmanDC = new JpegHuffmanTableConfig(@class: 0, destIndex: 0, HuffmanSpec.LuminanceDC);
+ var defaultLuminanceHuffmanAC = new JpegHuffmanTableConfig(@class: 1, destIndex: 0, HuffmanSpec.LuminanceAC);
+ var defaultChrominanceHuffmanDC = new JpegHuffmanTableConfig(@class: 0, destIndex: 1, HuffmanSpec.ChrominanceDC);
+ var defaultChrominanceHuffmanAC = new JpegHuffmanTableConfig(@class: 1, destIndex: 1, HuffmanSpec.ChrominanceAC);
+
+ var defaultLuminanceQuantTable = new JpegQuantizationTableConfig(0, Quantization.LuminanceTable);
+ var defaultChrominanceQuantTable = new JpegQuantizationTableConfig(1, Quantization.ChrominanceTable);
+
+ var yCbCrHuffmanConfigs = new JpegHuffmanTableConfig[]
+ {
+ defaultLuminanceHuffmanDC,
+ defaultLuminanceHuffmanAC,
+ defaultChrominanceHuffmanDC,
+ defaultChrominanceHuffmanAC,
+ };
+
+ var yCbCrQuantTableConfigs = new JpegQuantizationTableConfig[]
+ {
+ defaultLuminanceQuantTable,
+ defaultChrominanceQuantTable,
+ };
+
+ return new JpegFrameConfig[]
+ {
+ // YCbCr 4:4:4
+ new JpegFrameConfig(
+ JpegColorSpace.YCbCr,
+ JpegEncodingColor.YCbCrRatio444,
+ new JpegComponentConfig[]
+ {
+ new JpegComponentConfig(id: 1, hsf: 1, vsf: 1, quantIndex: 0, dcIndex: 0, acIndex: 0),
+ new JpegComponentConfig(id: 2, hsf: 1, vsf: 1, quantIndex: 1, dcIndex: 1, acIndex: 1),
+ new JpegComponentConfig(id: 3, hsf: 1, vsf: 1, quantIndex: 1, dcIndex: 1, acIndex: 1),
+ },
+ yCbCrHuffmanConfigs,
+ yCbCrQuantTableConfigs),
+
+ // YCbCr 4:2:2
+ new JpegFrameConfig(
+ JpegColorSpace.YCbCr,
+ JpegEncodingColor.YCbCrRatio422,
+ new JpegComponentConfig[]
+ {
+ new JpegComponentConfig(id: 1, hsf: 2, vsf: 1, quantIndex: 0, dcIndex: 0, acIndex: 0),
+ new JpegComponentConfig(id: 2, hsf: 1, vsf: 1, quantIndex: 1, dcIndex: 1, acIndex: 1),
+ new JpegComponentConfig(id: 3, hsf: 1, vsf: 1, quantIndex: 1, dcIndex: 1, acIndex: 1),
+ },
+ yCbCrHuffmanConfigs,
+ yCbCrQuantTableConfigs),
+
+ // YCbCr 4:2:0
+ new JpegFrameConfig(
+ JpegColorSpace.YCbCr,
+ JpegEncodingColor.YCbCrRatio420,
+ new JpegComponentConfig[]
+ {
+ new JpegComponentConfig(id: 1, hsf: 2, vsf: 2, quantIndex: 0, dcIndex: 0, acIndex: 0),
+ new JpegComponentConfig(id: 2, hsf: 1, vsf: 1, quantIndex: 1, dcIndex: 1, acIndex: 1),
+ new JpegComponentConfig(id: 3, hsf: 1, vsf: 1, quantIndex: 1, dcIndex: 1, acIndex: 1),
+ },
+ yCbCrHuffmanConfigs,
+ yCbCrQuantTableConfigs),
+
+ // YCbCr 4:1:1
+ new JpegFrameConfig(
+ JpegColorSpace.YCbCr,
+ JpegEncodingColor.YCbCrRatio411,
+ new JpegComponentConfig[]
+ {
+ new JpegComponentConfig(id: 1, hsf: 4, vsf: 1, quantIndex: 0, dcIndex: 0, acIndex: 0),
+ new JpegComponentConfig(id: 2, hsf: 1, vsf: 1, quantIndex: 1, dcIndex: 1, acIndex: 1),
+ new JpegComponentConfig(id: 3, hsf: 1, vsf: 1, quantIndex: 1, dcIndex: 1, acIndex: 1),
+ },
+ yCbCrHuffmanConfigs,
+ yCbCrQuantTableConfigs),
+
+ // YCbCr 4:1:0
+ new JpegFrameConfig(
+ JpegColorSpace.YCbCr,
+ JpegEncodingColor.YCbCrRatio410,
+ new JpegComponentConfig[]
+ {
+ new JpegComponentConfig(id: 1, hsf: 4, vsf: 2, quantIndex: 0, dcIndex: 0, acIndex: 0),
+ new JpegComponentConfig(id: 2, hsf: 1, vsf: 1, quantIndex: 1, dcIndex: 1, acIndex: 1),
+ new JpegComponentConfig(id: 3, hsf: 1, vsf: 1, quantIndex: 1, dcIndex: 1, acIndex: 1),
+ },
+ yCbCrHuffmanConfigs,
+ yCbCrQuantTableConfigs),
+
+ // Luminance
+ new JpegFrameConfig(
+ JpegColorSpace.Grayscale,
+ JpegEncodingColor.Luminance,
+ new JpegComponentConfig[]
+ {
+ new JpegComponentConfig(id: 0, hsf: 1, vsf: 1, quantIndex: 0, dcIndex: 0, acIndex: 0),
+ },
+ new JpegHuffmanTableConfig[]
+ {
+ defaultLuminanceHuffmanDC,
+ defaultLuminanceHuffmanAC
+ },
+ new JpegQuantizationTableConfig[]
+ {
+ defaultLuminanceQuantTable
+ }),
+
+ // Rgb
+ new JpegFrameConfig(
+ JpegColorSpace.RGB,
+ JpegEncodingColor.Rgb,
+ new JpegComponentConfig[]
+ {
+ new JpegComponentConfig(id: 82, hsf: 1, vsf: 1, quantIndex: 0, dcIndex: 0, acIndex: 0),
+ new JpegComponentConfig(id: 71, hsf: 1, vsf: 1, quantIndex: 0, dcIndex: 0, acIndex: 0),
+ new JpegComponentConfig(id: 66, hsf: 1, vsf: 1, quantIndex: 0, dcIndex: 0, acIndex: 0),
+ },
+ new JpegHuffmanTableConfig[]
+ {
+ defaultLuminanceHuffmanDC,
+ defaultLuminanceHuffmanAC
+ },
+ new JpegQuantizationTableConfig[]
+ {
+ defaultLuminanceQuantTable
+ })
+ {
+ AdobeColorTransformMarkerFlag = JpegConstants.Adobe.ColorTransformUnknown
+ },
+
+ // Cmyk
+ new JpegFrameConfig(
+ JpegColorSpace.Cmyk,
+ JpegEncodingColor.Cmyk,
+ new JpegComponentConfig[]
+ {
+ new JpegComponentConfig(id: 1, hsf: 1, vsf: 1, quantIndex: 0, dcIndex: 0, acIndex: 0),
+ new JpegComponentConfig(id: 2, hsf: 1, vsf: 1, quantIndex: 0, dcIndex: 0, acIndex: 0),
+ new JpegComponentConfig(id: 3, hsf: 1, vsf: 1, quantIndex: 0, dcIndex: 0, acIndex: 0),
+ new JpegComponentConfig(id: 4, hsf: 1, vsf: 1, quantIndex: 0, dcIndex: 0, acIndex: 0),
+ },
+ new JpegHuffmanTableConfig[]
+ {
+ defaultLuminanceHuffmanDC,
+ defaultLuminanceHuffmanAC
+ },
+ new JpegQuantizationTableConfig[]
+ {
+ defaultLuminanceQuantTable
+ })
+ {
+ AdobeColorTransformMarkerFlag = JpegConstants.Adobe.ColorTransformUnknown,
+ },
+
+ // YccK
+ new JpegFrameConfig(
+ JpegColorSpace.Ycck,
+ JpegEncodingColor.Ycck,
+ new JpegComponentConfig[]
+ {
+ new JpegComponentConfig(id: 1, hsf: 1, vsf: 1, quantIndex: 0, dcIndex: 0, acIndex: 0),
+ new JpegComponentConfig(id: 2, hsf: 1, vsf: 1, quantIndex: 0, dcIndex: 0, acIndex: 0),
+ new JpegComponentConfig(id: 3, hsf: 1, vsf: 1, quantIndex: 0, dcIndex: 0, acIndex: 0),
+ new JpegComponentConfig(id: 4, hsf: 1, vsf: 1, quantIndex: 0, dcIndex: 0, acIndex: 0),
+ },
+ new JpegHuffmanTableConfig[]
+ {
+ defaultLuminanceHuffmanDC,
+ defaultLuminanceHuffmanAC
+ },
+ new JpegQuantizationTableConfig[]
+ {
+ defaultLuminanceQuantTable
+ })
+ {
+ AdobeColorTransformMarkerFlag = JpegConstants.Adobe.ColorTransformYcck,
+ },
+ };
+ }
+ }
+}
diff --git a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
index 0336d71d32..ea29e071ce 100644
--- a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
+++ b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
@@ -21,7 +21,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
///
/// Image encoder for writing an image to a stream as a jpeg.
///
- internal sealed unsafe class JpegEncoderCore : IImageEncoderInternals
+ internal sealed unsafe partial class JpegEncoderCore : IImageEncoderInternals
{
///
/// The available encodable frame configs.
@@ -244,8 +244,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
return;
}
- const int MaxBytesApp1 = 65533; // 64k - 2 padding bytes
- const int MaxBytesWithExifId = 65527; // Max - 6 bytes for EXIF header.
+ const int maxBytesApp1 = 65533; // 64k - 2 padding bytes
+ const int maxBytesWithExifId = 65527; // Max - 6 bytes for EXIF header.
byte[] data = exifProfile.ToByteArray();
@@ -257,7 +257,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
// We can write up to a maximum of 64 data to the initial marker so calculate boundaries.
int exifMarkerLength = Components.Decoder.ProfileResolver.ExifMarker.Length;
int remaining = exifMarkerLength + data.Length;
- int bytesToWrite = remaining > MaxBytesApp1 ? MaxBytesApp1 : remaining;
+ int bytesToWrite = remaining > maxBytesApp1 ? maxBytesApp1 : remaining;
int app1Length = bytesToWrite + 2;
// Write the app marker, EXIF marker, and data
@@ -267,9 +267,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
remaining -= bytesToWrite;
// If the exif data exceeds 64K, write it in multiple APP1 Markers
- for (int idx = MaxBytesWithExifId; idx < data.Length; idx += MaxBytesWithExifId)
+ for (int idx = maxBytesWithExifId; idx < data.Length; idx += maxBytesWithExifId)
{
- bytesToWrite = remaining > MaxBytesWithExifId ? MaxBytesWithExifId : remaining;
+ bytesToWrite = remaining > maxBytesWithExifId ? maxBytesWithExifId : remaining;
app1Length = bytesToWrite + 2 + exifMarkerLength;
this.WriteApp1Header(app1Length);
@@ -293,7 +293,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
///
private void WriteIptcProfile(IptcProfile iptcProfile)
{
- const int Max = 65533;
+ const int maxBytes = 65533;
if (iptcProfile is null || !iptcProfile.Values.Any())
{
return;
@@ -306,9 +306,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
return;
}
- if (data.Length > Max)
+ if (data.Length > maxBytes)
{
- throw new ImageFormatException($"Iptc profile size exceeds limit of {Max} bytes");
+ throw new ImageFormatException($"Iptc profile size exceeds limit of {maxBytes} bytes");
}
int app13Length = 2 + Components.Decoder.ProfileResolver.AdobePhotoshopApp13Marker.Length +
@@ -340,9 +340,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
return;
}
- const int XmpOverheadLength = 29;
- const int Max = 65533;
- const int MaxData = Max - XmpOverheadLength;
+ const int xmpOverheadLength = 29;
+ const int maxBytes = 65533;
+ const int maxData = maxBytes - xmpOverheadLength;
byte[] data = xmpProfile.Data;
@@ -358,9 +358,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
{
int length = dataLength; // Number of bytes to write.
- if (length > MaxData)
+ if (length > maxData)
{
- length = MaxData;
+ length = maxData;
}
dataLength -= length;
@@ -410,9 +410,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
return;
}
- const int IccOverheadLength = 14;
- const int Max = 65533;
- const int MaxData = Max - IccOverheadLength;
+ const int iccOverheadLength = 14;
+ const int maxBytes = 65533;
+ const int maxData = maxBytes - iccOverheadLength;
byte[] data = iccProfile.ToByteArray();
@@ -423,9 +423,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
// Calculate the number of markers we'll need, rounding up of course.
int dataLength = data.Length;
- int count = dataLength / MaxData;
+ int count = dataLength / maxData;
- if (count * MaxData != dataLength)
+ if (count * maxData != dataLength)
{
count++;
}
@@ -438,9 +438,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
{
int length = dataLength; // Number of bytes to write.
- if (length > MaxData)
+ if (length > maxData)
{
- length = MaxData;
+ length = maxData;
}
dataLength -= length;
@@ -468,7 +468,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
this.buffer[12] = (byte)current; // The position within the collection.
this.buffer[13] = (byte)count; // The total number of profiles.
- this.outputStream.Write(this.buffer, 0, IccOverheadLength);
+ this.outputStream.Write(this.buffer, 0, iccOverheadLength);
this.outputStream.Write(data, offset, length);
current++;
@@ -712,187 +712,5 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
return frameConfig;
}
-
- private static JpegFrameConfig[] CreateFrameConfigs()
- {
- var defaultLuminanceHuffmanDC = new JpegHuffmanTableConfig(@class: 0, destIndex: 0, HuffmanSpec.TheHuffmanSpecs[0]);
- var defaultLuminanceHuffmanAC = new JpegHuffmanTableConfig(@class: 1, destIndex: 0, HuffmanSpec.TheHuffmanSpecs[1]);
- var defaultChrominanceHuffmanDC = new JpegHuffmanTableConfig(@class: 0, destIndex: 1, HuffmanSpec.TheHuffmanSpecs[2]);
- var defaultChrominanceHuffmanAC = new JpegHuffmanTableConfig(@class: 1, destIndex: 1, HuffmanSpec.TheHuffmanSpecs[3]);
-
- var defaultLuminanceQuantTable = new JpegQuantizationTableConfig(0, Quantization.LuminanceTable);
- var defaultChrominanceQuantTable = new JpegQuantizationTableConfig(1, Quantization.ChrominanceTable);
-
- var yCbCrHuffmanConfigs = new JpegHuffmanTableConfig[]
- {
- defaultLuminanceHuffmanDC,
- defaultLuminanceHuffmanAC,
- defaultChrominanceHuffmanDC,
- defaultChrominanceHuffmanAC,
- };
-
- var yCbCrQuantTableConfigs = new JpegQuantizationTableConfig[]
- {
- defaultLuminanceQuantTable,
- defaultChrominanceQuantTable,
- };
-
- return new JpegFrameConfig[]
- {
- // YCbCr 4:4:4
- new JpegFrameConfig(
- JpegColorSpace.YCbCr,
- JpegEncodingColor.YCbCrRatio444,
- new JpegComponentConfig[]
- {
- new JpegComponentConfig(id: 1, hsf: 1, vsf: 1, quantIndex: 0, dcIndex: 0, acIndex: 0),
- new JpegComponentConfig(id: 2, hsf: 1, vsf: 1, quantIndex: 1, dcIndex: 1, acIndex: 1),
- new JpegComponentConfig(id: 3, hsf: 1, vsf: 1, quantIndex: 1, dcIndex: 1, acIndex: 1),
- },
- yCbCrHuffmanConfigs,
- yCbCrQuantTableConfigs),
-
- // YCbCr 4:2:2
- new JpegFrameConfig(
- JpegColorSpace.YCbCr,
- JpegEncodingColor.YCbCrRatio422,
- new JpegComponentConfig[]
- {
- new JpegComponentConfig(id: 1, hsf: 2, vsf: 1, quantIndex: 0, dcIndex: 0, acIndex: 0),
- new JpegComponentConfig(id: 2, hsf: 1, vsf: 1, quantIndex: 1, dcIndex: 1, acIndex: 1),
- new JpegComponentConfig(id: 3, hsf: 1, vsf: 1, quantIndex: 1, dcIndex: 1, acIndex: 1),
- },
- yCbCrHuffmanConfigs,
- yCbCrQuantTableConfigs),
-
- // YCbCr 4:2:0
- new JpegFrameConfig(
- JpegColorSpace.YCbCr,
- JpegEncodingColor.YCbCrRatio420,
- new JpegComponentConfig[]
- {
- new JpegComponentConfig(id: 1, hsf: 2, vsf: 2, quantIndex: 0, dcIndex: 0, acIndex: 0),
- new JpegComponentConfig(id: 2, hsf: 1, vsf: 1, quantIndex: 1, dcIndex: 1, acIndex: 1),
- new JpegComponentConfig(id: 3, hsf: 1, vsf: 1, quantIndex: 1, dcIndex: 1, acIndex: 1),
- },
- yCbCrHuffmanConfigs,
- yCbCrQuantTableConfigs),
-
- // YCbCr 4:1:1
- new JpegFrameConfig(
- JpegColorSpace.YCbCr,
- JpegEncodingColor.YCbCrRatio411,
- new JpegComponentConfig[]
- {
- new JpegComponentConfig(id: 1, hsf: 4, vsf: 1, quantIndex: 0, dcIndex: 0, acIndex: 0),
- new JpegComponentConfig(id: 2, hsf: 1, vsf: 1, quantIndex: 1, dcIndex: 1, acIndex: 1),
- new JpegComponentConfig(id: 3, hsf: 1, vsf: 1, quantIndex: 1, dcIndex: 1, acIndex: 1),
- },
- yCbCrHuffmanConfigs,
- yCbCrQuantTableConfigs),
-
- // YCbCr 4:1:0
- new JpegFrameConfig(
- JpegColorSpace.YCbCr,
- JpegEncodingColor.YCbCrRatio410,
- new JpegComponentConfig[]
- {
- new JpegComponentConfig(id: 1, hsf: 4, vsf: 2, quantIndex: 0, dcIndex: 0, acIndex: 0),
- new JpegComponentConfig(id: 2, hsf: 1, vsf: 1, quantIndex: 1, dcIndex: 1, acIndex: 1),
- new JpegComponentConfig(id: 3, hsf: 1, vsf: 1, quantIndex: 1, dcIndex: 1, acIndex: 1),
- },
- yCbCrHuffmanConfigs,
- yCbCrQuantTableConfigs),
-
- // Luminance
- new JpegFrameConfig(
- JpegColorSpace.Grayscale,
- JpegEncodingColor.Luminance,
- new JpegComponentConfig[]
- {
- new JpegComponentConfig(id: 0, hsf: 1, vsf: 1, quantIndex: 0, dcIndex: 0, acIndex: 0),
- },
- new JpegHuffmanTableConfig[]
- {
- defaultLuminanceHuffmanDC,
- defaultLuminanceHuffmanAC
- },
- new JpegQuantizationTableConfig[]
- {
- defaultLuminanceQuantTable
- }),
-
- // Rgb
- new JpegFrameConfig(
- JpegColorSpace.RGB,
- JpegEncodingColor.Rgb,
- new JpegComponentConfig[]
- {
- new JpegComponentConfig(id: 82, hsf: 1, vsf: 1, quantIndex: 0, dcIndex: 0, acIndex: 0),
- new JpegComponentConfig(id: 71, hsf: 1, vsf: 1, quantIndex: 0, dcIndex: 0, acIndex: 0),
- new JpegComponentConfig(id: 66, hsf: 1, vsf: 1, quantIndex: 0, dcIndex: 0, acIndex: 0),
- },
- new JpegHuffmanTableConfig[]
- {
- defaultLuminanceHuffmanDC,
- defaultLuminanceHuffmanAC
- },
- new JpegQuantizationTableConfig[]
- {
- defaultLuminanceQuantTable
- })
- {
- AdobeColorTransformMarkerFlag = JpegConstants.Adobe.ColorTransformUnknown
- },
-
- // Cmyk
- new JpegFrameConfig(
- JpegColorSpace.Cmyk,
- JpegEncodingColor.Cmyk,
- new JpegComponentConfig[]
- {
- new JpegComponentConfig(id: 1, hsf: 1, vsf: 1, quantIndex: 0, dcIndex: 0, acIndex: 0),
- new JpegComponentConfig(id: 2, hsf: 1, vsf: 1, quantIndex: 0, dcIndex: 0, acIndex: 0),
- new JpegComponentConfig(id: 3, hsf: 1, vsf: 1, quantIndex: 0, dcIndex: 0, acIndex: 0),
- new JpegComponentConfig(id: 4, hsf: 1, vsf: 1, quantIndex: 0, dcIndex: 0, acIndex: 0),
- },
- new JpegHuffmanTableConfig[]
- {
- defaultLuminanceHuffmanDC,
- defaultLuminanceHuffmanAC
- },
- new JpegQuantizationTableConfig[]
- {
- defaultLuminanceQuantTable
- })
- {
- AdobeColorTransformMarkerFlag = JpegConstants.Adobe.ColorTransformUnknown,
- },
-
- // YccK
- new JpegFrameConfig(
- JpegColorSpace.Ycck,
- JpegEncodingColor.Ycck,
- new JpegComponentConfig[]
- {
- new JpegComponentConfig(id: 1, hsf: 1, vsf: 1, quantIndex: 0, dcIndex: 0, acIndex: 0),
- new JpegComponentConfig(id: 2, hsf: 1, vsf: 1, quantIndex: 0, dcIndex: 0, acIndex: 0),
- new JpegComponentConfig(id: 3, hsf: 1, vsf: 1, quantIndex: 0, dcIndex: 0, acIndex: 0),
- new JpegComponentConfig(id: 4, hsf: 1, vsf: 1, quantIndex: 0, dcIndex: 0, acIndex: 0),
- },
- new JpegHuffmanTableConfig[]
- {
- defaultLuminanceHuffmanDC,
- defaultLuminanceHuffmanAC
- },
- new JpegQuantizationTableConfig[]
- {
- defaultLuminanceQuantTable
- })
- {
- AdobeColorTransformMarkerFlag = JpegConstants.Adobe.ColorTransformYcck,
- },
- };
- }
}
}