Browse Source

Merge constants and rename decoder core

pull/571/head
James Jackson-South 8 years ago
parent
commit
5b34aad1dd
  1. 69
      src/ImageSharp/Formats/Jpeg/Common/JpegConstants.cs
  2. 10
      src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/Bytes.cs
  3. 8
      src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/InputProcessor.cs
  4. 10
      src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigComponent.cs
  5. 4
      src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegScanDecoder.ComputationData.cs
  6. 36
      src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegScanDecoder.cs
  7. 48
      src/ImageSharp/Formats/Jpeg/GolangPort/GolangJpegDecoderCore.cs
  8. 61
      src/ImageSharp/Formats/Jpeg/GolangPort/JpegEncoderCore.cs
  9. 189
      src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegConstants.cs
  10. 4
      src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoder.cs
  11. 4
      src/ImageSharp/Formats/Jpeg/JpegDecoder.cs
  12. 7
      src/ImageSharp/Formats/Jpeg/JpegFormat.cs
  13. 4
      src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsScanDecoder.cs
  14. 70
      src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs
  15. 26
      tests/ImageSharp.Tests/Formats/Jpg/AdobeMarkerTests.cs
  16. 4
      tests/ImageSharp.Tests/Formats/Jpg/JpegImagePostProcessorTests.cs
  17. 8
      tests/ImageSharp.Tests/Formats/Jpg/ParseStreamTests.cs
  18. 4
      tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs
  19. 4
      tests/ImageSharp.Tests/Formats/Jpg/Utils/JpegFixture.cs
  20. 2
      tests/ImageSharp.Tests/Formats/Jpg/Utils/LibJpegTools.SpectralData.cs

69
src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegConstants.cs → src/ImageSharp/Formats/Jpeg/Common/JpegConstants.cs

@ -1,23 +1,45 @@
// Copyright (c) Six Labors and contributors. // Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
// ReSharper disable InconsistentNaming using System.Collections.Generic;
namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
namespace SixLabors.ImageSharp.Formats.Jpeg.Common
{ {
/// <summary> /// <summary>
/// Contains jpeg constant values /// Contains jpeg constant values defined in the specification.
/// </summary> /// </summary>
internal static class PdfJsJpegConstants internal static class JpegConstants
{ {
/// <summary>
/// The maximum allowable length in each dimension of a jpeg image.
/// </summary>
public const ushort MaxLength = 65535;
/// <summary>
/// The list of mimetypes that equate to a jpeg.
/// </summary>
public static readonly IEnumerable<string> MimeTypes = new[] { "image/jpeg", "image/pjpeg" };
/// <summary>
/// The list of file extensions that equate to a jpeg.
/// </summary>
public static readonly IEnumerable<string> FileExtensions = new[] { "jpg", "jpeg", "jfif" };
/// <summary> /// <summary>
/// Contains marker specific constants /// Contains marker specific constants
/// </summary> /// </summary>
public static class Markers // ReSharper disable InconsistentNaming
internal static class Markers
{ {
/// <summary> /// <summary>
/// The prefix used for all markers. /// The prefix used for all markers.
/// </summary> /// </summary>
public const byte Prefix = 0xFF; public const byte XFF = 0xFF;
/// <summary>
/// Same as <see cref="XFF"/> but of type <see cref="int"/>
/// </summary>
public const int XFFInt = XFF;
/// <summary> /// <summary>
/// The Start of Image marker /// The Start of Image marker
@ -161,7 +183,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
/// <summary> /// <summary>
/// Define Restart Interval /// Define Restart Interval
/// <remarks> /// <remarks>
/// Specifies the interval between RSTn markers, in macroblocks.This marker is followed by two bytes indicating the fixed size so it can be treated like any other variable size segment. /// Specifies the interval between RSTn markers, in macroblocks.This marker is followed by two bytes indicating the fixed size so
/// it can be treated like any other variable size segment.
/// </remarks> /// </remarks>
/// </summary> /// </summary>
public const byte DRI = 0xDD; public const byte DRI = 0xDD;
@ -193,27 +216,27 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
/// </remarks> /// </remarks>
/// </summary> /// </summary>
public const byte RST7 = 0xD7; public const byte RST7 = 0xD7;
}
/// <summary>
/// Contains Adobe specific constants
/// </summary>
internal static class Adobe
{
/// <summary> /// <summary>
/// Contains Adobe specific markers /// The color transform is unknown.(RGB or CMYK)
/// </summary> /// </summary>
public static class Adobe public const byte ColorTransformUnknown = 0;
{
/// <summary>
/// The color transform is unknown.(RGB or CMYK)
/// </summary>
public const byte ColorTransformUnknown = 0;
/// <summary> /// <summary>
/// The color transform is YCbCr (luminance, red chroma, blue chroma) /// The color transform is YCbCr (luminance, red chroma, blue chroma)
/// </summary> /// </summary>
public const byte ColorTransformYCbCr = 1; public const byte ColorTransformYCbCr = 1;
/// <summary> /// <summary>
/// The color transform is YCCK (luminance, red chroma, blue chroma, keyline) /// The color transform is YCCK (luminance, red chroma, blue chroma, keyline)
/// </summary> /// </summary>
public const byte ColorTransformYcck = 2; public const byte ColorTransformYcck = 2;
}
} }
} }
} }

10
src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/Bytes.cs

@ -5,6 +5,8 @@ using System;
using System.IO; using System.IO;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Formats.Jpeg.Common;
namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
{ {
/// <summary> /// <summary>
@ -86,7 +88,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
x = this.BufferAsInt[this.I]; x = this.BufferAsInt[this.I];
this.I++; this.I++;
this.UnreadableBytes = 1; this.UnreadableBytes = 1;
if (x != OrigJpegConstants.Markers.XFFInt) if (x != JpegConstants.Markers.XFFInt)
{ {
return OrigDecoderErrorCode.NoError; return OrigDecoderErrorCode.NoError;
} }
@ -98,7 +100,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
this.I++; this.I++;
this.UnreadableBytes = 2; this.UnreadableBytes = 2;
x = OrigJpegConstants.Markers.XFF; x = JpegConstants.Markers.XFF;
return OrigDecoderErrorCode.NoError; return OrigDecoderErrorCode.NoError;
} }
@ -111,7 +113,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
return errorCode; return errorCode;
} }
if (x != OrigJpegConstants.Markers.XFF) if (x != JpegConstants.Markers.XFF)
{ {
return OrigDecoderErrorCode.NoError; return OrigDecoderErrorCode.NoError;
} }
@ -128,7 +130,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
return OrigDecoderErrorCode.MissingFF00; return OrigDecoderErrorCode.MissingFF00;
} }
x = OrigJpegConstants.Markers.XFF; x = JpegConstants.Markers.XFF;
return OrigDecoderErrorCode.NoError; return OrigDecoderErrorCode.NoError;
} }

8
src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/InputProcessor.cs

@ -8,7 +8,7 @@ using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
{ {
/// <summary> /// <summary>
/// Encapsulates stream reading and processing data and operations for <see cref="OrigJpegDecoderCore"/>. /// Encapsulates stream reading and processing data and operations for <see cref="GolangJpegDecoderCore"/>.
/// It's a value type for imporved data locality, and reduced number of CALLVIRT-s /// It's a value type for imporved data locality, and reduced number of CALLVIRT-s
/// </summary> /// </summary>
internal struct InputProcessor : IDisposable internal struct InputProcessor : IDisposable
@ -27,7 +27,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
/// Initializes a new instance of the <see cref="InputProcessor"/> struct. /// Initializes a new instance of the <see cref="InputProcessor"/> struct.
/// </summary> /// </summary>
/// <param name="inputStream">The input <see cref="Stream"/></param> /// <param name="inputStream">The input <see cref="Stream"/></param>
/// <param name="temp">Temporal buffer, same as <see cref="OrigJpegDecoderCore.Temp"/></param> /// <param name="temp">Temporal buffer, same as <see cref="GolangJpegDecoderCore.Temp"/></param>
public InputProcessor(Stream inputStream, byte[] temp) public InputProcessor(Stream inputStream, byte[] temp)
{ {
this.Bits = default(Bits); this.Bits = default(Bits);
@ -43,7 +43,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
public Stream InputStream { get; } public Stream InputStream { get; }
/// <summary> /// <summary>
/// Gets the temporary buffer, same instance as <see cref="OrigJpegDecoderCore.Temp"/> /// Gets the temporary buffer, same instance as <see cref="GolangJpegDecoderCore.Temp"/>
/// </summary> /// </summary>
public byte[] Temp { get; } public byte[] Temp { get; }
@ -138,7 +138,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
/// <summary> /// <summary>
/// Reads exactly length bytes into data. It does not care about byte stuffing. /// Reads exactly length bytes into data. It does not care about byte stuffing.
/// Does not throw on errors, returns <see cref="OrigJpegDecoderCore"/> instead! /// Does not throw on errors, returns <see cref="GolangJpegDecoderCore"/> instead!
/// </summary> /// </summary>
/// <param name="data">The data to write to.</param> /// <param name="data">The data to write to.</param>
/// <param name="offset">The offset in the source buffer</param> /// <param name="offset">The offset in the source buffer</param>

10
src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigComponent.cs

@ -56,8 +56,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
/// Initializes <see cref="SpectralBlocks"/> /// Initializes <see cref="SpectralBlocks"/>
/// </summary> /// </summary>
/// <param name="memoryManager">The <see cref="MemoryManager"/> to use for buffer allocations.</param> /// <param name="memoryManager">The <see cref="MemoryManager"/> to use for buffer allocations.</param>
/// <param name="decoder">The <see cref="OrigJpegDecoderCore"/> instance</param> /// <param name="decoder">The <see cref="GolangJpegDecoderCore"/> instance</param>
public void InitializeDerivedData(MemoryManager memoryManager, OrigJpegDecoderCore decoder) public void InitializeDerivedData(MemoryManager memoryManager, GolangJpegDecoderCore decoder)
{ {
// For 4-component images (either CMYK or YCbCrK), we only support two // For 4-component images (either CMYK or YCbCrK), we only support two
// hv vectors: [0x11 0x11 0x11 0x11] and [0x22 0x11 0x11 0x22]. // hv vectors: [0x11 0x11 0x11 0x11] and [0x22 0x11 0x11 0x22].
@ -86,8 +86,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
/// <summary> /// <summary>
/// Initializes all component data except <see cref="SpectralBlocks"/>. /// Initializes all component data except <see cref="SpectralBlocks"/>.
/// </summary> /// </summary>
/// <param name="decoder">The <see cref="OrigJpegDecoderCore"/> instance</param> /// <param name="decoder">The <see cref="GolangJpegDecoderCore"/> instance</param>
public void InitializeCoreData(OrigJpegDecoderCore decoder) public void InitializeCoreData(GolangJpegDecoderCore decoder)
{ {
// Section B.2.2 states that "the value of C_i shall be different from // Section B.2.2 states that "the value of C_i shall be different from
// the values of C_1 through C_(i-1)". // the values of C_1 through C_(i-1)".
@ -102,7 +102,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
} }
this.QuantizationTableIndex = decoder.Temp[8 + (3 * i)]; this.QuantizationTableIndex = decoder.Temp[8 + (3 * i)];
if (this.QuantizationTableIndex > OrigJpegDecoderCore.MaxTq) if (this.QuantizationTableIndex > GolangJpegDecoderCore.MaxTq)
{ {
throw new ImageFormatException("Bad Tq value"); throw new ImageFormatException("Bad Tq value");
} }

4
src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegScanDecoder.ComputationData.cs

@ -30,12 +30,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
/// <summary> /// <summary>
/// The buffer storing the <see cref="OrigComponentScan"/>-s for each component /// The buffer storing the <see cref="OrigComponentScan"/>-s for each component
/// </summary> /// </summary>
public fixed byte ScanData[3 * OrigJpegDecoderCore.MaxComponents]; public fixed byte ScanData[3 * GolangJpegDecoderCore.MaxComponents];
/// <summary> /// <summary>
/// The DC values for each component /// The DC values for each component
/// </summary> /// </summary>
public fixed int Dc[OrigJpegDecoderCore.MaxComponents]; public fixed int Dc[GolangJpegDecoderCore.MaxComponents];
/// <summary> /// <summary>
/// Creates and initializes a new <see cref="ComputationData"/> instance /// Creates and initializes a new <see cref="ComputationData"/> instance

36
src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegScanDecoder.cs

@ -110,12 +110,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
private byte expectedRst; private byte expectedRst;
/// <summary> /// <summary>
/// Initializes a default-constructed <see cref="OrigJpegScanDecoder"/> instance for reading data from <see cref="OrigJpegDecoderCore"/>-s stream. /// Initializes a default-constructed <see cref="OrigJpegScanDecoder"/> instance for reading data from <see cref="GolangJpegDecoderCore"/>-s stream.
/// </summary> /// </summary>
/// <param name="p">Pointer to <see cref="OrigJpegScanDecoder"/> on the stack</param> /// <param name="p">Pointer to <see cref="OrigJpegScanDecoder"/> on the stack</param>
/// <param name="decoder">The <see cref="OrigJpegDecoderCore"/> instance</param> /// <param name="decoder">The <see cref="GolangJpegDecoderCore"/> instance</param>
/// <param name="remaining">The remaining bytes in the segment block.</param> /// <param name="remaining">The remaining bytes in the segment block.</param>
public static void InitStreamReading(OrigJpegScanDecoder* p, OrigJpegDecoderCore decoder, int remaining) public static void InitStreamReading(OrigJpegScanDecoder* p, GolangJpegDecoderCore decoder, int remaining)
{ {
p->data = ComputationData.Create(); p->data = ComputationData.Create();
p->pointers = new DataPointers(&p->data); p->pointers = new DataPointers(&p->data);
@ -123,7 +123,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
} }
/// <summary> /// <summary>
/// Read Huffman data from Jpeg scans in <see cref="OrigJpegDecoderCore.InputStream"/>, /// Read Huffman data from Jpeg scans in <see cref="GolangJpegDecoderCore.InputStream"/>,
/// and decode it as <see cref="Block8x8"/> into <see cref="OrigComponent.SpectralBlocks"/>. /// and decode it as <see cref="Block8x8"/> into <see cref="OrigComponent.SpectralBlocks"/>.
/// ///
/// The blocks are traversed one MCU at a time. For 4:2:0 chroma /// The blocks are traversed one MCU at a time. For 4:2:0 chroma
@ -149,14 +149,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
/// 0 1 2 /// 0 1 2
/// 3 4 5 /// 3 4 5
/// </summary> /// </summary>
/// <param name="decoder">The <see cref="OrigJpegDecoderCore"/> instance</param> /// <param name="decoder">The <see cref="GolangJpegDecoderCore"/> instance</param>
public void DecodeBlocks(OrigJpegDecoderCore decoder) public void DecodeBlocks(GolangJpegDecoderCore decoder)
{ {
decoder.InputProcessor.ResetErrorState(); decoder.InputProcessor.ResetErrorState();
this.blockCounter = 0; this.blockCounter = 0;
this.mcuCounter = 0; this.mcuCounter = 0;
this.expectedRst = OrigJpegConstants.Markers.RST0; this.expectedRst = JpegConstants.Markers.RST0;
for (int my = 0; my < decoder.MCUCountY; my++) for (int my = 0; my < decoder.MCUCountY; my++)
{ {
@ -177,7 +177,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
} }
} }
private void DecodeBlocksAtMcuIndex(OrigJpegDecoderCore decoder, int mx, int my) private void DecodeBlocksAtMcuIndex(GolangJpegDecoderCore decoder, int mx, int my)
{ {
for (int scanIndex = 0; scanIndex < this.componentScanCount; scanIndex++) for (int scanIndex = 0; scanIndex < this.componentScanCount; scanIndex++)
{ {
@ -223,7 +223,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
} }
} }
private void ProcessRSTMarker(OrigJpegDecoderCore decoder) private void ProcessRSTMarker(GolangJpegDecoderCore decoder)
{ {
// Attempt to look for RST[0-7] markers to resynchronize from corrupt input. // Attempt to look for RST[0-7] markers to resynchronize from corrupt input.
if (!decoder.InputProcessor.ReachedEOF) if (!decoder.InputProcessor.ReachedEOF)
@ -262,15 +262,15 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
} }
this.expectedRst++; this.expectedRst++;
if (this.expectedRst == OrigJpegConstants.Markers.RST7 + 1) if (this.expectedRst == JpegConstants.Markers.RST7 + 1)
{ {
this.expectedRst = OrigJpegConstants.Markers.RST0; this.expectedRst = JpegConstants.Markers.RST0;
} }
} }
} }
} }
private void Reset(OrigJpegDecoderCore decoder) private void Reset(GolangJpegDecoderCore decoder)
{ {
decoder.InputProcessor.ResetHuffmanDecoder(); decoder.InputProcessor.ResetHuffmanDecoder();
@ -285,15 +285,15 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
/// </summary> /// </summary>
private void ResetDcValues() private void ResetDcValues()
{ {
Unsafe.InitBlock(this.pointers.Dc, default(byte), sizeof(int) * OrigJpegDecoderCore.MaxComponents); Unsafe.InitBlock(this.pointers.Dc, default(byte), sizeof(int) * GolangJpegDecoderCore.MaxComponents);
} }
/// <summary> /// <summary>
/// The implementation part of <see cref="InitStreamReading"/> as an instance method. /// The implementation part of <see cref="InitStreamReading"/> as an instance method.
/// </summary> /// </summary>
/// <param name="decoder">The <see cref="OrigJpegDecoderCore"/></param> /// <param name="decoder">The <see cref="GolangJpegDecoderCore"/></param>
/// <param name="remaining">The remaining bytes</param> /// <param name="remaining">The remaining bytes</param>
private void InitStreamReadingImpl(OrigJpegDecoderCore decoder, int remaining) private void InitStreamReadingImpl(GolangJpegDecoderCore decoder, int remaining)
{ {
if (decoder.ComponentCount == 0) if (decoder.ComponentCount == 0)
{ {
@ -360,7 +360,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
/// </summary> /// </summary>
/// <param name="decoder">The decoder</param> /// <param name="decoder">The decoder</param>
/// <param name="scanIndex">The index of the scan</param> /// <param name="scanIndex">The index of the scan</param>
private void DecodeBlock(OrigJpegDecoderCore decoder, int scanIndex) private void DecodeBlock(GolangJpegDecoderCore decoder, int scanIndex)
{ {
Block8x8* b = this.pointers.Block; Block8x8* b = this.pointers.Block;
int huffmannIdx = (OrigHuffmanTree.AcTableIndex * OrigHuffmanTree.ThRowSize) + this.pointers.ComponentScan[scanIndex].AcTableSelector; int huffmannIdx = (OrigHuffmanTree.AcTableIndex * OrigHuffmanTree.ThRowSize) + this.pointers.ComponentScan[scanIndex].AcTableSelector;
@ -475,7 +475,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
this.eobRun |= bitsResult; this.eobRun |= bitsResult;
} }
private void InitComponentScan(OrigJpegDecoderCore decoder, int i, ref OrigComponentScan currentComponentScan, ref int totalHv) private void InitComponentScan(GolangJpegDecoderCore decoder, int i, ref OrigComponentScan currentComponentScan, ref int totalHv)
{ {
// Component selector. // Component selector.
int cs = decoder.Temp[1 + (2 * i)]; int cs = decoder.Temp[1 + (2 * i)];
@ -500,7 +500,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
} }
private void ProcessComponentImpl( private void ProcessComponentImpl(
OrigJpegDecoderCore decoder, GolangJpegDecoderCore decoder,
int i, int i,
ref OrigComponentScan currentComponentScan, ref OrigComponentScan currentComponentScan,
ref int totalHv, ref int totalHv,

48
src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs → src/ImageSharp/Formats/Jpeg/GolangPort/GolangJpegDecoderCore.cs

@ -19,7 +19,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
/// <summary> /// <summary>
/// Performs the jpeg decoding operation. /// Performs the jpeg decoding operation.
/// </summary> /// </summary>
internal sealed unsafe class OrigJpegDecoderCore : IRawJpegData internal sealed unsafe class GolangJpegDecoderCore : IRawJpegData
{ {
/// <summary> /// <summary>
/// The maximum number of color components /// The maximum number of color components
@ -40,7 +40,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
#pragma warning disable SA1401 // FieldsMustBePrivate #pragma warning disable SA1401 // FieldsMustBePrivate
/// <summary> /// <summary>
/// Encapsulates stream reading and processing data and operations for <see cref="OrigJpegDecoderCore"/>. /// Encapsulates stream reading and processing data and operations for <see cref="GolangJpegDecoderCore"/>.
/// It's a value type for improved data locality, and reduced number of CALLVIRT-s /// It's a value type for improved data locality, and reduced number of CALLVIRT-s
/// </summary> /// </summary>
public InputProcessor InputProcessor; public InputProcessor InputProcessor;
@ -79,11 +79,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
private AdobeMarker adobe; private AdobeMarker adobe;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="OrigJpegDecoderCore" /> class. /// Initializes a new instance of the <see cref="GolangJpegDecoderCore" /> class.
/// </summary> /// </summary>
/// <param name="configuration">The configuration.</param> /// <param name="configuration">The configuration.</param>
/// <param name="options">The options.</param> /// <param name="options">The options.</param>
public OrigJpegDecoderCore(Configuration configuration, IJpegDecoderOptions options) public GolangJpegDecoderCore(Configuration configuration, IJpegDecoderOptions options)
{ {
this.IgnoreMetadata = options.IgnoreMetadata; this.IgnoreMetadata = options.IgnoreMetadata;
this.configuration = configuration ?? Configuration.Default; this.configuration = configuration ?? Configuration.Default;
@ -238,7 +238,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
// Check for the Start Of Image marker. // Check for the Start Of Image marker.
this.InputProcessor.ReadFull(this.Temp, 0, 2); this.InputProcessor.ReadFull(this.Temp, 0, 2);
if (this.Temp[0] != OrigJpegConstants.Markers.XFF || this.Temp[1] != OrigJpegConstants.Markers.SOI) if (this.Temp[0] != JpegConstants.Markers.XFF || this.Temp[1] != JpegConstants.Markers.SOI)
{ {
throw new ImageFormatException("Missing SOI marker."); throw new ImageFormatException("Missing SOI marker.");
} }
@ -302,12 +302,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
} }
// End Of Image. // End Of Image.
if (marker == OrigJpegConstants.Markers.EOI) if (marker == JpegConstants.Markers.EOI)
{ {
break; break;
} }
if (marker >= OrigJpegConstants.Markers.RST0 && marker <= OrigJpegConstants.Markers.RST7) if (marker >= JpegConstants.Markers.RST0 && marker <= JpegConstants.Markers.RST7)
{ {
// Figures B.2 and B.16 of the specification suggest that restart markers should // Figures B.2 and B.16 of the specification suggest that restart markers should
// only occur between Entropy Coded Segments and not after the final ECS. // only occur between Entropy Coded Segments and not after the final ECS.
@ -329,14 +329,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
switch (marker) switch (marker)
{ {
case OrigJpegConstants.Markers.SOF0: case JpegConstants.Markers.SOF0:
case OrigJpegConstants.Markers.SOF1: case JpegConstants.Markers.SOF1:
case OrigJpegConstants.Markers.SOF2: case JpegConstants.Markers.SOF2:
this.IsProgressive = marker == OrigJpegConstants.Markers.SOF2; this.IsProgressive = marker == JpegConstants.Markers.SOF2;
this.ProcessStartOfFrameMarker(remaining, metadataOnly); this.ProcessStartOfFrameMarker(remaining, metadataOnly);
break; break;
case OrigJpegConstants.Markers.DHT: case JpegConstants.Markers.DHT:
if (metadataOnly) if (metadataOnly)
{ {
this.InputProcessor.Skip(remaining); this.InputProcessor.Skip(remaining);
@ -347,7 +347,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
} }
break; break;
case OrigJpegConstants.Markers.DQT: case JpegConstants.Markers.DQT:
if (metadataOnly) if (metadataOnly)
{ {
this.InputProcessor.Skip(remaining); this.InputProcessor.Skip(remaining);
@ -358,7 +358,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
} }
break; break;
case OrigJpegConstants.Markers.SOS: case JpegConstants.Markers.SOS:
if (!metadataOnly) if (!metadataOnly)
{ {
this.ProcessStartOfScanMarker(remaining); this.ProcessStartOfScanMarker(remaining);
@ -377,7 +377,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
break; break;
case OrigJpegConstants.Markers.DRI: case JpegConstants.Markers.DRI:
if (metadataOnly) if (metadataOnly)
{ {
this.InputProcessor.Skip(remaining); this.InputProcessor.Skip(remaining);
@ -388,21 +388,21 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
} }
break; break;
case OrigJpegConstants.Markers.APP0: case JpegConstants.Markers.APP0:
this.ProcessApplicationHeaderMarker(remaining); this.ProcessApplicationHeaderMarker(remaining);
break; break;
case OrigJpegConstants.Markers.APP1: case JpegConstants.Markers.APP1:
this.ProcessApp1Marker(remaining); this.ProcessApp1Marker(remaining);
break; break;
case OrigJpegConstants.Markers.APP2: case JpegConstants.Markers.APP2:
this.ProcessApp2Marker(remaining); this.ProcessApp2Marker(remaining);
break; break;
case OrigJpegConstants.Markers.APP14: case JpegConstants.Markers.APP14:
this.ProcessApp14Marker(remaining); this.ProcessApp14Marker(remaining);
break; break;
default: default:
if ((marker >= OrigJpegConstants.Markers.APP0 && marker <= OrigJpegConstants.Markers.APP15) if ((marker >= JpegConstants.Markers.APP0 && marker <= JpegConstants.Markers.APP15)
|| marker == OrigJpegConstants.Markers.COM) || marker == JpegConstants.Markers.COM)
{ {
this.InputProcessor.Skip(remaining); this.InputProcessor.Skip(remaining);
} }
@ -779,19 +779,19 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
case 1: case 1:
return JpegColorSpace.Grayscale; return JpegColorSpace.Grayscale;
case 3: case 3:
if (!this.isAdobe || this.adobe.ColorTransform == OrigJpegConstants.Adobe.ColorTransformYCbCr) if (!this.isAdobe || this.adobe.ColorTransform == JpegConstants.Adobe.ColorTransformYCbCr)
{ {
return JpegColorSpace.YCbCr; return JpegColorSpace.YCbCr;
} }
if (this.adobe.ColorTransform == OrigJpegConstants.Adobe.ColorTransformUnknown) if (this.adobe.ColorTransform == JpegConstants.Adobe.ColorTransformUnknown)
{ {
return JpegColorSpace.RGB; return JpegColorSpace.RGB;
} }
break; break;
case 4: case 4:
if (this.adobe.ColorTransform == OrigJpegConstants.Adobe.ColorTransformYcck) if (this.adobe.ColorTransform == JpegConstants.Adobe.ColorTransformYcck)
{ {
return JpegColorSpace.Ycck; return JpegColorSpace.Ycck;
} }

61
src/ImageSharp/Formats/Jpeg/GolangPort/JpegEncoderCore.cs

@ -1,17 +1,14 @@
// Copyright (c) Six Labors and contributors. // Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using System.Buffers;
using System.IO; using System.IO;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Formats.Jpeg.Common; using SixLabors.ImageSharp.Formats.Jpeg.Common;
using SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components; using SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components;
using SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Encoder; using SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Encoder;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.MetaData.Profiles.Exif; using SixLabors.ImageSharp.MetaData.Profiles.Exif;
using SixLabors.ImageSharp.MetaData.Profiles.Icc; using SixLabors.ImageSharp.MetaData.Profiles.Icc;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using Block8x8F = SixLabors.ImageSharp.Formats.Jpeg.Common.Block8x8F;
namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
{ {
@ -58,7 +55,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
/// </summary> /// </summary>
private static readonly byte[] SosHeaderYCbCr = private static readonly byte[] SosHeaderYCbCr =
{ {
OrigJpegConstants.Markers.XFF, OrigJpegConstants.Markers.SOS, JpegConstants.Markers.XFF, JpegConstants.Markers.SOS,
// Marker // Marker
0x00, 0x0c, 0x00, 0x0c,
@ -190,7 +187,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
Guard.NotNull(image, nameof(image)); Guard.NotNull(image, nameof(image));
Guard.NotNull(stream, nameof(stream)); Guard.NotNull(stream, nameof(stream));
ushort max = OrigJpegConstants.MaxLength; ushort max = JpegConstants.MaxLength;
if (image.Width >= max || image.Height >= max) if (image.Width >= max || image.Height >= max)
{ {
throw new ImageFormatException($"Image is too large to encode at {image.Width}x{image.Height}."); throw new ImageFormatException($"Image is too large to encode at {image.Width}x{image.Height}.");
@ -234,8 +231,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
this.WriteStartOfScan(image); this.WriteStartOfScan(image);
// Write the End Of Image marker. // Write the End Of Image marker.
this.buffer[0] = OrigJpegConstants.Markers.XFF; this.buffer[0] = JpegConstants.Markers.XFF;
this.buffer[1] = OrigJpegConstants.Markers.EOI; this.buffer[1] = JpegConstants.Markers.EOI;
stream.Write(this.buffer, 0, 2); stream.Write(this.buffer, 0, 2);
stream.Flush(); stream.Flush();
} }
@ -382,18 +379,18 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
{ {
// TODO: Need a JpegScanEncoder<TPixel> class or struct that encapsulates the scan-encoding implementation. (Similar to JpegScanDecoder.) // TODO: Need a JpegScanEncoder<TPixel> class or struct that encapsulates the scan-encoding implementation. (Similar to JpegScanDecoder.)
// (Partially done with YCbCrForwardConverter<TPixel>) // (Partially done with YCbCrForwardConverter<TPixel>)
Block8x8F temp1 = default(Block8x8F); Block8x8F temp1 = default;
Block8x8F temp2 = default(Block8x8F); Block8x8F temp2 = default;
Block8x8F onStackLuminanceQuantTable = this.luminanceQuantTable; Block8x8F onStackLuminanceQuantTable = this.luminanceQuantTable;
Block8x8F onStackChrominanceQuantTable = this.chrominanceQuantTable; Block8x8F onStackChrominanceQuantTable = this.chrominanceQuantTable;
ZigZag unzig = ZigZag.CreateUnzigTable(); var unzig = ZigZag.CreateUnzigTable();
// ReSharper disable once InconsistentNaming // ReSharper disable once InconsistentNaming
int prevDCY = 0, prevDCCb = 0, prevDCCr = 0; int prevDCY = 0, prevDCCb = 0, prevDCCr = 0;
YCbCrForwardConverter<TPixel> pixelConverter = YCbCrForwardConverter<TPixel>.Create(); var pixelConverter = YCbCrForwardConverter<TPixel>.Create();
for (int y = 0; y < pixels.Height; y += 8) for (int y = 0; y < pixels.Height; y += 8)
{ {
@ -437,12 +434,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
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.
this.buffer[0] = OrigJpegConstants.Markers.XFF; this.buffer[0] = JpegConstants.Markers.XFF;
this.buffer[1] = OrigJpegConstants.Markers.SOI; this.buffer[1] = JpegConstants.Markers.SOI;
// Write the JFIF headers // Write the JFIF headers
this.buffer[2] = OrigJpegConstants.Markers.XFF; this.buffer[2] = JpegConstants.Markers.XFF;
this.buffer[3] = OrigJpegConstants.Markers.APP0; // Application Marker this.buffer[3] = JpegConstants.Markers.APP0; // Application Marker
this.buffer[4] = 0x00; this.buffer[4] = 0x00;
this.buffer[5] = 0x10; this.buffer[5] = 0x10;
this.buffer[6] = 0x4a; // J this.buffer[6] = 0x4a; // J
@ -502,7 +499,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
this.EmitHuffRLE((HuffIndex)((2 * (int)index) + 0), 0, dc - prevDC); this.EmitHuffRLE((HuffIndex)((2 * (int)index) + 0), 0, dc - prevDC);
// Emit the AC components. // Emit the AC components.
HuffIndex h = (HuffIndex)((2 * (int)index) + 1); var h = (HuffIndex)((2 * (int)index) + 1);
int runLength = 0; int runLength = 0;
for (int zig = 1; zig < Block8x8F.Size; zig++) for (int zig = 1; zig < Block8x8F.Size; zig++)
@ -556,7 +553,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
markerlen += 1 + 16 + s.Values.Length; markerlen += 1 + 16 + s.Values.Length;
} }
this.WriteMarkerHeader(OrigJpegConstants.Markers.DHT, markerlen); this.WriteMarkerHeader(JpegConstants.Markers.DHT, markerlen);
for (int i = 0; i < specs.Length; i++) for (int i = 0; i < specs.Length; i++)
{ {
HuffmanSpec spec = specs[i]; HuffmanSpec spec = specs[i];
@ -590,7 +587,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
{ {
// Marker + quantization table lengths // Marker + quantization table lengths
int markerlen = 2 + (QuantizationTableCount * (1 + Block8x8F.Size)); int markerlen = 2 + (QuantizationTableCount * (1 + Block8x8F.Size));
this.WriteMarkerHeader(OrigJpegConstants.Markers.DQT, markerlen); this.WriteMarkerHeader(JpegConstants.Markers.DQT, markerlen);
// Loop through and collect the tables as one array. // Loop through and collect the tables as one array.
// This allows us to reduce the number of writes to the stream. // This allows us to reduce the number of writes to the stream.
@ -627,8 +624,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
int length = data.Length + 2; int length = data.Length + 2;
this.buffer[0] = OrigJpegConstants.Markers.XFF; this.buffer[0] = JpegConstants.Markers.XFF;
this.buffer[1] = OrigJpegConstants.Markers.APP1; // Application Marker this.buffer[1] = JpegConstants.Markers.APP1; // Application Marker
this.buffer[2] = (byte)((length >> 8) & 0xFF); this.buffer[2] = (byte)((length >> 8) & 0xFF);
this.buffer[3] = (byte)(length & 0xFF); this.buffer[3] = (byte)(length & 0xFF);
@ -686,8 +683,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
dataLength -= length; dataLength -= length;
this.buffer[0] = OrigJpegConstants.Markers.XFF; this.buffer[0] = JpegConstants.Markers.XFF;
this.buffer[1] = OrigJpegConstants.Markers.APP2; // Application Marker this.buffer[1] = JpegConstants.Markers.APP2; // Application Marker
int markerLength = length + 16; int markerLength = length + 16;
this.buffer[2] = (byte)((markerLength >> 8) & 0xFF); this.buffer[2] = (byte)((markerLength >> 8) & 0xFF);
this.buffer[3] = (byte)(markerLength & 0xFF); this.buffer[3] = (byte)(markerLength & 0xFF);
@ -759,7 +756,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
// Length (high byte, low byte), 8 + components * 3. // Length (high byte, low byte), 8 + components * 3.
int markerlen = 8 + (3 * componentCount); int markerlen = 8 + (3 * componentCount);
this.WriteMarkerHeader(OrigJpegConstants.Markers.SOF0, markerlen); this.WriteMarkerHeader(JpegConstants.Markers.SOF0, markerlen);
this.buffer[0] = 8; // Data Precision. 8 for now, 12 and 16 bit jpegs not supported this.buffer[0] = 8; // Data Precision. 8 for now, 12 and 16 bit jpegs not supported
this.buffer[1] = (byte)(height >> 8); this.buffer[1] = (byte)(height >> 8);
this.buffer[2] = (byte)(height & 0xff); // (2 bytes, Hi-Lo), must be > 0 if DNL not supported this.buffer[2] = (byte)(height & 0xff); // (2 bytes, Hi-Lo), must be > 0 if DNL not supported
@ -827,20 +824,20 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
// TODO: Need a JpegScanEncoder<TPixel> class or struct that encapsulates the scan-encoding implementation. (Similar to JpegScanDecoder.) // TODO: Need a JpegScanEncoder<TPixel> class or struct that encapsulates the scan-encoding implementation. (Similar to JpegScanDecoder.)
Block8x8F b = default(Block8x8F); Block8x8F b = default;
BlockQuad cb = default(BlockQuad); BlockQuad cb = default;
BlockQuad cr = default(BlockQuad); BlockQuad cr = default;
Block8x8F* cbPtr = (Block8x8F*)cb.Data; var cbPtr = (Block8x8F*)cb.Data;
Block8x8F* crPtr = (Block8x8F*)cr.Data; var crPtr = (Block8x8F*)cr.Data;
Block8x8F temp1 = default(Block8x8F); Block8x8F temp1 = default;
Block8x8F temp2 = default(Block8x8F); Block8x8F temp2 = default;
Block8x8F onStackLuminanceQuantTable = this.luminanceQuantTable; Block8x8F onStackLuminanceQuantTable = this.luminanceQuantTable;
Block8x8F onStackChrominanceQuantTable = this.chrominanceQuantTable; Block8x8F onStackChrominanceQuantTable = this.chrominanceQuantTable;
ZigZag unzig = ZigZag.CreateUnzigTable(); var unzig = ZigZag.CreateUnzigTable();
var pixelConverter = YCbCrForwardConverter<TPixel>.Create(); var pixelConverter = YCbCrForwardConverter<TPixel>.Create();
@ -902,7 +899,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
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.
this.buffer[0] = OrigJpegConstants.Markers.XFF; this.buffer[0] = JpegConstants.Markers.XFF;
this.buffer[1] = marker; this.buffer[1] = marker;
this.buffer[2] = (byte)(length >> 8); this.buffer[2] = (byte)(length >> 8);
this.buffer[3] = (byte)(length & 0xff); this.buffer[3] = (byte)(length & 0xff);

189
src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegConstants.cs

@ -1,189 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Collections.Generic;
namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
{
/// <summary>
/// Defines jpeg constants defined in the specification.
/// </summary>
internal static class OrigJpegConstants
{
/// <summary>
/// The maximum allowable length in each dimension of a jpeg image.
/// </summary>
public const ushort MaxLength = 65535;
/// <summary>
/// The list of mimetypes that equate to a jpeg.
/// </summary>
public static readonly IEnumerable<string> MimeTypes = new[] { "image/jpeg", "image/pjpeg" };
/// <summary>
/// The list of file extensions that equate to a jpeg.
/// </summary>
public static readonly IEnumerable<string> FileExtensions = new[] { "jpg", "jpeg", "jfif" };
/// <summary>
/// Describes common Jpeg markers
/// </summary>
internal static class Markers
{
/// <summary>
/// Marker prefix. Next byte is a marker.
/// </summary>
public const byte XFF = 0xff;
/// <summary>
/// Same as <see cref="XFF"/> but of type <see cref="int"/>
/// </summary>
public const int XFFInt = XFF;
/// <summary>
/// Start of Image
/// </summary>
public const byte SOI = 0xd8;
/// <summary>
/// Start of Frame (baseline DCT)
/// <remarks>
/// Indicates that this is a baseline DCT-based JPEG, and specifies the width, height, number of components,
/// and component subsampling (e.g., 4:2:0).
/// </remarks>
/// </summary>
public const byte SOF0 = 0xc0;
/// <summary>
/// Start Of Frame (Extended Sequential DCT)
/// <remarks>
/// Indicates that this is a progressive DCT-based JPEG, and specifies the width, height, number of components,
/// and component subsampling (e.g., 4:2:0).
/// </remarks>
/// </summary>
public const byte SOF1 = 0xc1;
/// <summary>
/// Start Of Frame (progressive DCT)
/// <remarks>
/// Indicates that this is a progressive DCT-based JPEG, and specifies the width, height, number of components,
/// and component subsampling (e.g., 4:2:0).
/// </remarks>
/// </summary>
public const byte SOF2 = 0xc2;
/// <summary>
/// Define Huffman Table(s)
/// <remarks>
/// Specifies one or more Huffman tables.
/// </remarks>
/// </summary>
public const byte DHT = 0xc4;
/// <summary>
/// Define Quantization Table(s)
/// <remarks>
/// Specifies one or more quantization tables.
/// </remarks>
/// </summary>
public const byte DQT = 0xdb;
/// <summary>
/// Define Restart Interval
/// <remarks>
/// Specifies the interval between RSTn markers, in macroblocks. This marker is followed by two bytes
/// indicating the fixed size so it can be treated like any other variable size segment.
/// </remarks>
/// </summary>
public const byte DRI = 0xdd;
/// <summary>
/// Define First Restart
/// <remarks>
/// Inserted every r macroblocks, where r is the restart interval set by a DRI marker.
/// Not used if there was no DRI marker. The low three bits of the marker code cycle in value from 0 to 7.
/// </remarks>
/// </summary>
public const byte RST0 = 0xd0;
/// <summary>
/// Define Eigth Restart
/// <remarks>
/// Inserted every r macroblocks, where r is the restart interval set by a DRI marker.
/// Not used if there was no DRI marker. The low three bits of the marker code cycle in value from 0 to 7.
/// </remarks>
/// </summary>
public const byte RST7 = 0xd7;
/// <summary>
/// Start of Scan
/// <remarks>
/// Begins a top-to-bottom scan of the image. In baseline DCT JPEG images, there is generally a single scan.
/// Progressive DCT JPEG images usually contain multiple scans. This marker specifies which slice of data it
/// will contain, and is immediately followed by entropy-coded data.
/// </remarks>
/// </summary>
public const byte SOS = 0xda;
/// <summary>
/// Comment
/// <remarks>
/// Contains a text comment.
/// </remarks>
/// </summary>
public const byte COM = 0xfe;
/// <summary>
/// End of Image
/// </summary>
public const byte EOI = 0xd9;
/// <summary>
/// Application specific marker for marking the jpeg format.
/// <see href="http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/JPEG.html"/>
/// </summary>
public const byte APP0 = 0xe0;
/// <summary>
/// Application specific marker for marking where to store metadata.
/// </summary>
public const byte APP1 = 0xe1;
/// <summary>
/// Application specific marker for marking where to store ICC profile information.
/// </summary>
public const byte APP2 = 0xe2;
/// <summary>
/// Application specific marker used by Adobe for storing encoding information for DCT filters.
/// </summary>
public const byte APP14 = 0xee;
/// <summary>
/// Application specific marker used by GraphicConverter to store JPEG quality.
/// </summary>
public const byte APP15 = 0xef;
}
/// <summary>
/// Describes Adobe specific markers <see href="http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/JPEG.html#Adobe"/>
/// </summary>
internal static class Adobe
{
/// <summary>
/// The color transform is unknown.(RGB or CMYK)
/// </summary>
public const int ColorTransformUnknown = 0;
/// <summary>
/// The color transform is YCbCr (luminance, red chroma, blue chroma)
/// </summary>
public const int ColorTransformYCbCr = 1;
/// <summary>
/// The color transform is YCCK (luminance, red chroma, blue chroma, keyline)
/// </summary>
public const int ColorTransformYcck = 2;
}
}
}

4
src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoder.cs

@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
{ {
Guard.NotNull(stream, nameof(stream)); Guard.NotNull(stream, nameof(stream));
using (var decoder = new OrigJpegDecoderCore(configuration, this)) using (var decoder = new GolangJpegDecoderCore(configuration, this))
{ {
return decoder.Decode<TPixel>(stream); return decoder.Decode<TPixel>(stream);
} }
@ -33,7 +33,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
{ {
Guard.NotNull(stream, nameof(stream)); Guard.NotNull(stream, nameof(stream));
using (var decoder = new OrigJpegDecoderCore(configuration, this)) using (var decoder = new GolangJpegDecoderCore(configuration, this))
{ {
return decoder.Identify(stream); return decoder.Identify(stream);
} }

4
src/ImageSharp/Formats/Jpeg/JpegDecoder.cs

@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
{ {
Guard.NotNull(stream, nameof(stream)); Guard.NotNull(stream, nameof(stream));
using (var decoder = new OrigJpegDecoderCore(configuration, this)) using (var decoder = new GolangJpegDecoderCore(configuration, this))
{ {
return decoder.Decode<TPixel>(stream); return decoder.Decode<TPixel>(stream);
} }
@ -35,7 +35,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
{ {
Guard.NotNull(stream, "stream"); Guard.NotNull(stream, "stream");
using (var decoder = new OrigJpegDecoderCore(configuration, this)) using (var decoder = new GolangJpegDecoderCore(configuration, this))
{ {
return decoder.Identify(stream); return decoder.Identify(stream);
} }

7
src/ImageSharp/Formats/Jpeg/JpegFormat.cs

@ -2,7 +2,8 @@
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using System.Collections.Generic; using System.Collections.Generic;
using SixLabors.ImageSharp.Formats.Jpeg.GolangPort;
using SixLabors.ImageSharp.Formats.Jpeg.Common;
namespace SixLabors.ImageSharp.Formats.Jpeg namespace SixLabors.ImageSharp.Formats.Jpeg
{ {
@ -18,9 +19,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
public string DefaultMimeType => "image/jpeg"; public string DefaultMimeType => "image/jpeg";
/// <inheritdoc/> /// <inheritdoc/>
public IEnumerable<string> MimeTypes => OrigJpegConstants.MimeTypes; public IEnumerable<string> MimeTypes => JpegConstants.MimeTypes;
/// <inheritdoc/> /// <inheritdoc/>
public IEnumerable<string> FileExtensions => OrigJpegConstants.FileExtensions; public IEnumerable<string> FileExtensions => JpegConstants.FileExtensions;
} }
} }

4
src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsScanDecoder.cs

@ -136,7 +136,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
byte marker = fileMarker.Marker; byte marker = fileMarker.Marker;
// RSTn - We've already read the bytes and altered the position so no need to skip // RSTn - We've already read the bytes and altered the position so no need to skip
if (marker >= PdfJsJpegConstants.Markers.RST0 && marker <= PdfJsJpegConstants.Markers.RST7) if (marker >= JpegConstants.Markers.RST0 && marker <= JpegConstants.Markers.RST7)
{ {
continue; continue;
} }
@ -452,7 +452,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
this.endOfStreamReached = true; this.endOfStreamReached = true;
return false; return false;
case PdfJsJpegConstants.Markers.Prefix: case JpegConstants.Markers.XFF:
int nextByte = stream.ReadByte(); int nextByte = stream.ReadByte();
if (nextByte == -0x1) if (nextByte == -0x1)

70
src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs

@ -150,20 +150,20 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
if (value == 0) if (value == 0)
{ {
return new PdfJsFileMarker(PdfJsJpegConstants.Markers.EOI, stream.Length - 2); return new PdfJsFileMarker(JpegConstants.Markers.EOI, stream.Length - 2);
} }
if (marker[0] == PdfJsJpegConstants.Markers.Prefix) if (marker[0] == JpegConstants.Markers.XFF)
{ {
// According to Section B.1.1.2: // According to Section B.1.1.2:
// "Any marker may optionally be preceded by any number of fill bytes, which are bytes assigned code 0xFF." // "Any marker may optionally be preceded by any number of fill bytes, which are bytes assigned code 0xFF."
int m = marker[1]; int m = marker[1];
while (m == PdfJsJpegConstants.Markers.Prefix) while (m == JpegConstants.Markers.XFF)
{ {
int suffix = stream.ReadByte(); int suffix = stream.ReadByte();
if (suffix == -1) if (suffix == -1)
{ {
return new PdfJsFileMarker(PdfJsJpegConstants.Markers.EOI, stream.Length - 2); return new PdfJsFileMarker(JpegConstants.Markers.EOI, stream.Length - 2);
} }
m = suffix; m = suffix;
@ -213,7 +213,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
// Check for the Start Of Image marker. // Check for the Start Of Image marker.
this.InputStream.Read(this.markerBuffer, 0, 2); this.InputStream.Read(this.markerBuffer, 0, 2);
var fileMarker = new PdfJsFileMarker(this.markerBuffer[1], 0); var fileMarker = new PdfJsFileMarker(this.markerBuffer[1], 0);
if (fileMarker.Marker != PdfJsJpegConstants.Markers.SOI) if (fileMarker.Marker != JpegConstants.Markers.SOI)
{ {
throw new ImageFormatException("Missing SOI marker."); throw new ImageFormatException("Missing SOI marker.");
} }
@ -230,7 +230,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
this.acHuffmanTables = new PdfJsHuffmanTables(); this.acHuffmanTables = new PdfJsHuffmanTables();
} }
while (fileMarker.Marker != PdfJsJpegConstants.Markers.EOI) while (fileMarker.Marker != JpegConstants.Markers.EOI)
{ {
if (!fileMarker.Invalid) if (!fileMarker.Invalid)
{ {
@ -239,13 +239,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
switch (fileMarker.Marker) switch (fileMarker.Marker)
{ {
case PdfJsJpegConstants.Markers.SOF0: case JpegConstants.Markers.SOF0:
case PdfJsJpegConstants.Markers.SOF1: case JpegConstants.Markers.SOF1:
case PdfJsJpegConstants.Markers.SOF2: case JpegConstants.Markers.SOF2:
this.ProcessStartOfFrameMarker(remaining, fileMarker, metadataOnly); this.ProcessStartOfFrameMarker(remaining, fileMarker, metadataOnly);
break; break;
case PdfJsJpegConstants.Markers.SOS: case JpegConstants.Markers.SOS:
if (!metadataOnly) if (!metadataOnly)
{ {
this.ProcessStartOfScanMarker(); this.ProcessStartOfScanMarker();
@ -258,7 +258,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
return; return;
} }
case PdfJsJpegConstants.Markers.DHT: case JpegConstants.Markers.DHT:
if (metadataOnly) if (metadataOnly)
{ {
this.InputStream.Skip(remaining); this.InputStream.Skip(remaining);
@ -270,7 +270,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
break; break;
case PdfJsJpegConstants.Markers.DQT: case JpegConstants.Markers.DQT:
if (metadataOnly) if (metadataOnly)
{ {
this.InputStream.Skip(remaining); this.InputStream.Skip(remaining);
@ -282,7 +282,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
break; break;
case PdfJsJpegConstants.Markers.DRI: case JpegConstants.Markers.DRI:
if (metadataOnly) if (metadataOnly)
{ {
this.InputStream.Skip(remaining); this.InputStream.Skip(remaining);
@ -294,38 +294,38 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
break; break;
case PdfJsJpegConstants.Markers.APP0: case JpegConstants.Markers.APP0:
this.ProcessApplicationHeaderMarker(remaining); this.ProcessApplicationHeaderMarker(remaining);
break; break;
case PdfJsJpegConstants.Markers.APP1: case JpegConstants.Markers.APP1:
this.ProcessApp1Marker(remaining); this.ProcessApp1Marker(remaining);
break; break;
case PdfJsJpegConstants.Markers.APP2: case JpegConstants.Markers.APP2:
this.ProcessApp2Marker(remaining); this.ProcessApp2Marker(remaining);
break; break;
case PdfJsJpegConstants.Markers.APP3: case JpegConstants.Markers.APP3:
case PdfJsJpegConstants.Markers.APP4: case JpegConstants.Markers.APP4:
case PdfJsJpegConstants.Markers.APP5: case JpegConstants.Markers.APP5:
case PdfJsJpegConstants.Markers.APP6: case JpegConstants.Markers.APP6:
case PdfJsJpegConstants.Markers.APP7: case JpegConstants.Markers.APP7:
case PdfJsJpegConstants.Markers.APP8: case JpegConstants.Markers.APP8:
case PdfJsJpegConstants.Markers.APP9: case JpegConstants.Markers.APP9:
case PdfJsJpegConstants.Markers.APP10: case JpegConstants.Markers.APP10:
case PdfJsJpegConstants.Markers.APP11: case JpegConstants.Markers.APP11:
case PdfJsJpegConstants.Markers.APP12: case JpegConstants.Markers.APP12:
case PdfJsJpegConstants.Markers.APP13: case JpegConstants.Markers.APP13:
this.InputStream.Skip(remaining); this.InputStream.Skip(remaining);
break; break;
case PdfJsJpegConstants.Markers.APP14: case JpegConstants.Markers.APP14:
this.ProcessApp14Marker(remaining); this.ProcessApp14Marker(remaining);
break; break;
case PdfJsJpegConstants.Markers.APP15: case JpegConstants.Markers.APP15:
case PdfJsJpegConstants.Markers.COM: case JpegConstants.Markers.COM:
this.InputStream.Skip(remaining); this.InputStream.Skip(remaining);
break; break;
} }
@ -362,11 +362,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
if (this.ComponentCount == 3) if (this.ComponentCount == 3)
{ {
if (this.adobe.Equals(default) || this.adobe.ColorTransform == PdfJsJpegConstants.Markers.Adobe.ColorTransformYCbCr) if (this.adobe.Equals(default) || this.adobe.ColorTransform == JpegConstants.Adobe.ColorTransformYCbCr)
{ {
return JpegColorSpace.YCbCr; return JpegColorSpace.YCbCr;
} }
else if (this.adobe.ColorTransform == PdfJsJpegConstants.Markers.Adobe.ColorTransformUnknown) else if (this.adobe.ColorTransform == JpegConstants.Adobe.ColorTransformUnknown)
{ {
return JpegColorSpace.RGB; return JpegColorSpace.RGB;
} }
@ -374,7 +374,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
if (this.ComponentCount == 4) if (this.ComponentCount == 4)
{ {
return this.adobe.ColorTransform == PdfJsJpegConstants.Markers.Adobe.ColorTransformYcck return this.adobe.ColorTransform == JpegConstants.Adobe.ColorTransformYcck
? JpegColorSpace.Ycck ? JpegColorSpace.Ycck
: JpegColorSpace.Cmyk; : JpegColorSpace.Cmyk;
} }
@ -622,8 +622,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
this.Frame = new PdfJsFrame this.Frame = new PdfJsFrame
{ {
Extended = frameMarker.Marker == PdfJsJpegConstants.Markers.SOF1, Extended = frameMarker.Marker == JpegConstants.Markers.SOF1,
Progressive = frameMarker.Marker == PdfJsJpegConstants.Markers.SOF2, Progressive = frameMarker.Marker == JpegConstants.Markers.SOF2,
Precision = this.temp[0], Precision = this.temp[0],
Scanlines = (short)((this.temp[1] << 8) | this.temp[2]), Scanlines = (short)((this.temp[1] << 8) | this.temp[2]),
SamplesPerLine = (short)((this.temp[3] << 8) | this.temp[4]), SamplesPerLine = (short)((this.temp[3] << 8) | this.temp[4]),

26
tests/ImageSharp.Tests/Formats/Jpg/AdobeMarkerTests.cs

@ -1,8 +1,8 @@
// Copyright (c) Six Labors and contributors. // Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Formats.Jpeg.Common;
using SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder; using SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder;
using SixLabors.ImageSharp.Formats.Jpeg.GolangPort;
using Xunit; using Xunit;
@ -25,29 +25,29 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[Fact] [Fact]
public void MarkerReturnsCorrectParsedValue() public void MarkerReturnsCorrectParsedValue()
{ {
bool isAdobe = AdobeMarker.TryParse(this.bytes, out var marker); bool isAdobe = AdobeMarker.TryParse(this.bytes, out AdobeMarker marker);
Assert.True(isAdobe); Assert.True(isAdobe);
Assert.Equal(100, marker.DCTEncodeVersion); Assert.Equal(100, marker.DCTEncodeVersion);
Assert.Equal(0, marker.APP14Flags0); Assert.Equal(0, marker.APP14Flags0);
Assert.Equal(0, marker.APP14Flags1); Assert.Equal(0, marker.APP14Flags1);
Assert.Equal(OrigJpegConstants.Adobe.ColorTransformYcck, marker.ColorTransform); Assert.Equal(JpegConstants.Adobe.ColorTransformYcck, marker.ColorTransform);
} }
[Fact] [Fact]
public void MarkerIgnoresIncorrectValue() public void MarkerIgnoresIncorrectValue()
{ {
bool isAdobe = AdobeMarker.TryParse(new byte[] { 0, 0, 0, 0 }, out var marker); bool isAdobe = AdobeMarker.TryParse(new byte[] { 0, 0, 0, 0 }, out AdobeMarker marker);
Assert.False(isAdobe); Assert.False(isAdobe);
Assert.Equal(default(AdobeMarker), marker); Assert.Equal(default, marker);
} }
[Fact] [Fact]
public void MarkerEqualityIsCorrect() public void MarkerEqualityIsCorrect()
{ {
AdobeMarker.TryParse(this.bytes, out var marker); AdobeMarker.TryParse(this.bytes, out AdobeMarker marker);
AdobeMarker.TryParse(this.bytes, out var marker2); AdobeMarker.TryParse(this.bytes, out AdobeMarker marker2);
Assert.True(marker.Equals(marker2)); Assert.True(marker.Equals(marker2));
} }
@ -55,8 +55,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[Fact] [Fact]
public void MarkerInEqualityIsCorrect() public void MarkerInEqualityIsCorrect()
{ {
AdobeMarker.TryParse(this.bytes, out var marker); AdobeMarker.TryParse(this.bytes, out AdobeMarker marker);
AdobeMarker.TryParse(this.bytes2, out var marker2); AdobeMarker.TryParse(this.bytes2, out AdobeMarker marker2);
Assert.False(marker.Equals(marker2)); Assert.False(marker.Equals(marker2));
} }
@ -64,8 +64,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[Fact] [Fact]
public void MarkerHashCodeIsReplicable() public void MarkerHashCodeIsReplicable()
{ {
AdobeMarker.TryParse(this.bytes, out var marker); AdobeMarker.TryParse(this.bytes, out AdobeMarker marker);
AdobeMarker.TryParse(this.bytes, out var marker2); AdobeMarker.TryParse(this.bytes, out AdobeMarker marker2);
Assert.True(marker.GetHashCode().Equals(marker2.GetHashCode())); Assert.True(marker.GetHashCode().Equals(marker2.GetHashCode()));
} }
@ -73,8 +73,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[Fact] [Fact]
public void MarkerHashCodeIsUnique() public void MarkerHashCodeIsUnique()
{ {
AdobeMarker.TryParse(this.bytes, out var marker); AdobeMarker.TryParse(this.bytes, out AdobeMarker marker);
AdobeMarker.TryParse(this.bytes2, out var marker2); AdobeMarker.TryParse(this.bytes2, out AdobeMarker marker2);
Assert.False(marker.GetHashCode().Equals(marker2.GetHashCode())); Assert.False(marker.GetHashCode().Equals(marker2.GetHashCode()));
} }

4
tests/ImageSharp.Tests/Formats/Jpg/JpegImagePostProcessorTests.cs

@ -57,7 +57,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
string imageFile = provider.SourceFileOrDescription; string imageFile = provider.SourceFileOrDescription;
using (OrigJpegDecoderCore decoder = JpegFixture.ParseStream(imageFile)) using (GolangJpegDecoderCore decoder = JpegFixture.ParseStream(imageFile))
using (var pp = new JpegImagePostProcessor(Configuration.Default.MemoryManager, decoder)) using (var pp = new JpegImagePostProcessor(Configuration.Default.MemoryManager, decoder))
using (var imageFrame = new ImageFrame<Rgba32>(Configuration.Default.MemoryManager, decoder.ImageWidth, decoder.ImageHeight)) using (var imageFrame = new ImageFrame<Rgba32>(Configuration.Default.MemoryManager, decoder.ImageWidth, decoder.ImageHeight))
{ {
@ -79,7 +79,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
string imageFile = provider.SourceFileOrDescription; string imageFile = provider.SourceFileOrDescription;
using (OrigJpegDecoderCore decoder = JpegFixture.ParseStream(imageFile)) using (GolangJpegDecoderCore decoder = JpegFixture.ParseStream(imageFile))
using (var pp = new JpegImagePostProcessor(Configuration.Default.MemoryManager, decoder)) using (var pp = new JpegImagePostProcessor(Configuration.Default.MemoryManager, decoder))
using (var image = new Image<Rgba32>(decoder.ImageWidth, decoder.ImageHeight)) using (var image = new Image<Rgba32>(decoder.ImageWidth, decoder.ImageHeight))
{ {

8
tests/ImageSharp.Tests/Formats/Jpg/ParseStreamTests.cs

@ -33,7 +33,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
{ {
var expecteColorSpace = (JpegColorSpace)expectedColorSpaceValue; var expecteColorSpace = (JpegColorSpace)expectedColorSpaceValue;
using (OrigJpegDecoderCore decoder = JpegFixture.ParseStream(imageFile, false)) using (GolangJpegDecoderCore decoder = JpegFixture.ParseStream(imageFile, false))
{ {
Assert.Equal(expecteColorSpace, decoder.ColorSpace); Assert.Equal(expecteColorSpace, decoder.ColorSpace);
} }
@ -42,7 +42,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[Fact] [Fact]
public void ComponentScalingIsCorrect_1ChannelJpeg() public void ComponentScalingIsCorrect_1ChannelJpeg()
{ {
using (OrigJpegDecoderCore decoder = JpegFixture.ParseStream(TestImages.Jpeg.Baseline.Jpeg400, false)) using (GolangJpegDecoderCore decoder = JpegFixture.ParseStream(TestImages.Jpeg.Baseline.Jpeg400, false))
{ {
Assert.Equal(1, decoder.ComponentCount); Assert.Equal(1, decoder.ComponentCount);
Assert.Equal(1, decoder.Components.Length); Assert.Equal(1, decoder.Components.Length);
@ -68,7 +68,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
{ {
var sb = new StringBuilder(); var sb = new StringBuilder();
using (OrigJpegDecoderCore decoder = JpegFixture.ParseStream(imageFile, false)) using (GolangJpegDecoderCore decoder = JpegFixture.ParseStream(imageFile, false))
{ {
sb.AppendLine(imageFile); sb.AppendLine(imageFile);
sb.AppendLine($"Size:{decoder.ImageSizeInPixels} MCU:{decoder.ImageSizeInMCU}"); sb.AppendLine($"Size:{decoder.ImageSizeInPixels} MCU:{decoder.ImageSizeInMCU}");
@ -103,7 +103,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
Size fLuma = (Size)expectedLumaFactors; Size fLuma = (Size)expectedLumaFactors;
Size fChroma = (Size)expectedChromaFactors; Size fChroma = (Size)expectedChromaFactors;
using (OrigJpegDecoderCore decoder = JpegFixture.ParseStream(imageFile, false)) using (GolangJpegDecoderCore decoder = JpegFixture.ParseStream(imageFile, false))
{ {
Assert.Equal(componentCount, decoder.ComponentCount); Assert.Equal(componentCount, decoder.ComponentCount);
Assert.Equal(componentCount, decoder.Components.Length); Assert.Equal(componentCount, decoder.Components.Length);

4
tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs

@ -63,7 +63,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public void OriginalDecoder_ParseStream_SaveSpectralResult<TPixel>(TestImageProvider<TPixel> provider) public void OriginalDecoder_ParseStream_SaveSpectralResult<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
var decoder = new OrigJpegDecoderCore(Configuration.Default, new JpegDecoder()); var decoder = new GolangJpegDecoderCore(Configuration.Default, new JpegDecoder());
byte[] sourceBytes = TestFile.Create(provider.SourceFileOrDescription).Bytes; byte[] sourceBytes = TestFile.Create(provider.SourceFileOrDescription).Bytes;
@ -153,7 +153,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
return; return;
} }
var decoder = new OrigJpegDecoderCore(Configuration.Default, new JpegDecoder()); var decoder = new GolangJpegDecoderCore(Configuration.Default, new JpegDecoder());
byte[] sourceBytes = TestFile.Create(provider.SourceFileOrDescription).Bytes; byte[] sourceBytes = TestFile.Create(provider.SourceFileOrDescription).Bytes;

4
tests/ImageSharp.Tests/Formats/Jpg/Utils/JpegFixture.cs

@ -174,12 +174,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
Assert.False(failed); Assert.False(failed);
} }
internal static OrigJpegDecoderCore ParseStream(string testFileName, bool metaDataOnly = false) internal static GolangJpegDecoderCore ParseStream(string testFileName, bool metaDataOnly = false)
{ {
byte[] bytes = TestFile.Create(testFileName).Bytes; byte[] bytes = TestFile.Create(testFileName).Bytes;
using (var ms = new MemoryStream(bytes)) using (var ms = new MemoryStream(bytes))
{ {
var decoder = new OrigJpegDecoderCore(Configuration.Default, new JpegDecoder()); var decoder = new GolangJpegDecoderCore(Configuration.Default, new JpegDecoder());
decoder.ParseStream(ms, metaDataOnly); decoder.ParseStream(ms, metaDataOnly);
return decoder; return decoder;
} }

2
tests/ImageSharp.Tests/Formats/Jpg/Utils/LibJpegTools.SpectralData.cs

@ -37,7 +37,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
return new SpectralData(destComponents); return new SpectralData(destComponents);
} }
public static SpectralData LoadFromImageSharpDecoder(OrigJpegDecoderCore decoder) public static SpectralData LoadFromImageSharpDecoder(GolangJpegDecoderCore decoder)
{ {
OrigComponent[] srcComponents = decoder.Components; OrigComponent[] srcComponents = decoder.Components;
LibJpegTools.ComponentData[] destComponents = srcComponents.Select(LibJpegTools.ComponentData.Load).ToArray(); LibJpegTools.ComponentData[] destComponents = srcComponents.Select(LibJpegTools.ComponentData.Load).ToArray();

Loading…
Cancel
Save