Browse Source

Merge remote-tracking branch 'origin/jpeg-optimizations-experimental' into jpeg-optimizations

af/merge-core
Anton Firszov 10 years ago
parent
commit
13dd34d75f
  1. 2
      ImageSharp.sln
  2. 182
      src/ImageSharp/Formats/Jpg/JpegDecoderCore.cs

2
ImageSharp.sln

@ -32,8 +32,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Source", "Source", "{815C06
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{56801022-D71A-4FBE-BC5B-CBA08E2284EC}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{56801022-D71A-4FBE-BC5B-CBA08E2284EC}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageSharp.Tests46", "tests\ImageSharp.Tests46\ImageSharp.Tests46.csproj", "{88C5FB74-5845-4CC0-8F1E-A25EBABC95C2}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU

182
src/ImageSharp/Formats/Jpg/JpegDecoderCore.cs

@ -7,7 +7,6 @@ namespace ImageSharp.Formats
using System; using System;
using System.IO; using System.IO;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading.Tasks; using System.Threading.Tasks;
using ImageSharp.Formats.Jpg; using ImageSharp.Formats.Jpg;
@ -20,39 +19,7 @@ namespace ImageSharp.Formats
/// <summary> /// <summary>
/// The maximum number of color components /// The maximum number of color components
/// </summary> /// </summary>
internal const int MaxComponents = 4; public const int MaxComponents = 4;
/// <summary>
/// The maximum number of quantization tables
/// </summary>
private const int MaxTq = 3;
/// <summary>
/// The component array
/// </summary>
internal Component[] ComponentArray { get; }
/// <summary>
/// The huffman trees
/// </summary>
internal HuffmanTree[] HuffmanTrees { get; }
/// <summary>
/// Saved state between progressive-mode scans.
/// </summary>
internal Block8x8F[][] ProgCoeffs { get; }
/// <summary>
/// Quantization tables, in zigzag order.
/// </summary>
internal Block8x8F[] QuantizationTables { get; }
/// <summary>
/// A temporary buffer for holding pixels
/// </summary>
internal byte[] Temp { get; }
// TODO: the usage of this buffer is unclean + need to move it to the stack for performance
/// <summary> /// <summary>
/// The App14 marker color-space /// The App14 marker color-space
@ -67,26 +34,22 @@ namespace ImageSharp.Formats
/// <summary> /// <summary>
/// Holds the unprocessed bits that have been taken from the byte-stream. /// Holds the unprocessed bits that have been taken from the byte-stream.
/// </summary> /// </summary>
internal Bits Bits; public Bits Bits;
private JpegPixelArea blackImage;
//private int blockIndex;
/// <summary> /// <summary>
/// The byte buffer. /// The byte buffer.
/// </summary> /// </summary>
private Bytes bytes; public Bytes Bytes;
/// <summary> /// <summary>
/// The number of color components within the image. /// End-of-Band run, specified in section G.1.2.2.
/// </summary> /// </summary>
internal int ComponentCount { get; private set; } public ushort EobRun;
/// <summary> /// <summary>
/// End-of-Band run, specified in section G.1.2.2. /// The black image to decode to.
/// </summary> /// </summary>
internal ushort EobRun; private JpegPixelArea blackImage;
/// <summary> /// <summary>
/// A grayscale image to decode to. /// A grayscale image to decode to.
@ -99,35 +62,15 @@ namespace ImageSharp.Formats
private short horizontalResolution; private short horizontalResolution;
/// <summary> /// <summary>
/// The image height /// The maximum number of quantization tables
/// </summary>
internal int ImageHeight { get; private set; }
/// <summary>
/// The image width
/// </summary>
internal int ImageWidth { get; private set; }
/// <summary>
/// The byte buffer.
/// </summary> /// </summary>
private Stream inputStream; private const int MaxTq = 3;
/// <summary> /// <summary>
/// Whether the image has a JFIF header /// Whether the image has a JFIF header
/// </summary> /// </summary>
private bool isJfif; private bool isJfif;
/// <summary>
/// Whether the image is interlaced (progressive)
/// </summary>
public bool IsProgressive { get; private set; }
/// <summary>
/// The restart interval
/// </summary>
internal int RestartInterval { get; private set; }
/// <summary> /// <summary>
/// The vertical resolution. Calculated if the image has a JFIF header. /// The vertical resolution. Calculated if the image has a JFIF header.
/// </summary> /// </summary>
@ -149,7 +92,7 @@ namespace ImageSharp.Formats
this.ComponentArray = new Component[MaxComponents]; this.ComponentArray = new Component[MaxComponents];
this.ProgCoeffs = new Block8x8F[MaxComponents][]; this.ProgCoeffs = new Block8x8F[MaxComponents][];
this.Bits = default(Bits); this.Bits = default(Bits);
this.bytes = Bytes.Create(); this.Bytes = Bytes.Create();
} }
/// <summary> /// <summary>
@ -169,32 +112,59 @@ namespace ImageSharp.Formats
MissingFF00 MissingFF00
} }
/// <summary> /// <summary>
/// Gets or sets the byte buffer. /// The component array
/// </summary> /// </summary>
public Bytes Bytes public Component[] ComponentArray { get; }
{
get
{
return this.bytes;
}
set /// <summary>
{ /// The huffman trees
this.bytes = value; /// </summary>
} public HuffmanTree[] HuffmanTrees { get; }
}
/// <summary>
/// Saved state between progressive-mode scans.
/// </summary>
public Block8x8F[][] ProgCoeffs { get; }
/// <summary>
/// Quantization tables, in zigzag order.
/// </summary>
public Block8x8F[] QuantizationTables { get; }
/// <summary>
/// A temporary buffer for holding pixels
/// </summary>
// TODO: the usage rules of this buffer seem to be unclean + need to consider stack-allocating it for perf
public byte[] Temp { get; }
/// <summary>
/// The number of color components within the image.
/// </summary>
public int ComponentCount { get; private set; }
/// <summary>
/// The image height
/// </summary>
public int ImageHeight { get; private set; }
/// <summary>
/// The image width
/// </summary>
public int ImageWidth { get; private set; }
/// <summary> /// <summary>
/// Gets the input stream. /// Gets the input stream.
/// </summary> /// </summary>
public Stream InputStream public Stream InputStream { get; private set; }
{ /// <summary>
get /// Whether the image is interlaced (progressive)
{ /// </summary>
return this.inputStream; public bool IsProgressive { get; private set; }
}
} /// <summary>
/// The restart interval
/// </summary>
public int RestartInterval { get; private set; }
/// <summary> /// <summary>
/// Decodes the image from the specified this._stream and sets /// Decodes the image from the specified this._stream and sets
@ -207,7 +177,7 @@ namespace ImageSharp.Formats
public void Decode<TColor>(Image<TColor> image, Stream stream, bool configOnly) public void Decode<TColor>(Image<TColor> image, Stream stream, bool configOnly)
where TColor : struct, IPackedPixel, IEquatable<TColor> where TColor : struct, IPackedPixel, IEquatable<TColor>
{ {
this.inputStream = stream; this.InputStream = stream;
// Check for the Start Of Image marker. // Check for the Start Of Image marker.
this.ReadFull(this.Temp, 0, 2); this.ReadFull(this.Temp, 0, 2);
@ -427,7 +397,7 @@ namespace ImageSharp.Formats
} }
this.ycbcrImage?.Dispose(); this.ycbcrImage?.Dispose();
this.bytes.Dispose(); this.Bytes.Dispose();
this.grayImage.ReturnPooled(); this.grayImage.ReturnPooled();
this.blackImage.ReturnPooled(); this.blackImage.ReturnPooled();
} }
@ -439,7 +409,7 @@ namespace ImageSharp.Formats
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal byte ReadByte() internal byte ReadByte()
{ {
return this.bytes.ReadByte(this.inputStream); return this.Bytes.ReadByte(this.InputStream);
} }
/// <summary> /// <summary>
@ -451,32 +421,32 @@ namespace ImageSharp.Formats
internal void ReadFull(byte[] data, int offset, int length) internal void ReadFull(byte[] data, int offset, int length)
{ {
// Unread the overshot bytes, if any. // Unread the overshot bytes, if any.
if (this.bytes.UnreadableBytes != 0) if (this.Bytes.UnreadableBytes != 0)
{ {
if (this.Bits.UnreadBits >= 8) if (this.Bits.UnreadBits >= 8)
{ {
this.UnreadByteStuffedByte(); this.UnreadByteStuffedByte();
} }
this.bytes.UnreadableBytes = 0; this.Bytes.UnreadableBytes = 0;
} }
while (length > 0) while (length > 0)
{ {
if (this.bytes.J - this.bytes.I >= length) if (this.Bytes.J - this.Bytes.I >= length)
{ {
Array.Copy(this.bytes.Buffer, this.bytes.I, data, offset, length); Array.Copy(this.Bytes.Buffer, this.Bytes.I, data, offset, length);
this.bytes.I += length; this.Bytes.I += length;
length -= length; length -= length;
} }
else else
{ {
Array.Copy(this.bytes.Buffer, this.bytes.I, data, offset, this.bytes.J - this.bytes.I); Array.Copy(this.Bytes.Buffer, this.Bytes.I, data, offset, this.Bytes.J - this.Bytes.I);
offset += this.bytes.J - this.bytes.I; offset += this.Bytes.J - this.Bytes.I;
length -= this.bytes.J - this.bytes.I; length -= this.Bytes.J - this.Bytes.I;
this.bytes.I += this.bytes.J - this.bytes.I; this.Bytes.I += this.Bytes.J - this.Bytes.I;
this.bytes.Fill(this.inputStream); this.Bytes.Fill(this.InputStream);
} }
} }
} }
@ -1415,32 +1385,32 @@ namespace ImageSharp.Formats
private void Skip(int count) private void Skip(int count)
{ {
// Unread the overshot bytes, if any. // Unread the overshot bytes, if any.
if (this.bytes.UnreadableBytes != 0) if (this.Bytes.UnreadableBytes != 0)
{ {
if (this.Bits.UnreadBits >= 8) if (this.Bits.UnreadBits >= 8)
{ {
this.UnreadByteStuffedByte(); this.UnreadByteStuffedByte();
} }
this.bytes.UnreadableBytes = 0; this.Bytes.UnreadableBytes = 0;
} }
while (true) while (true)
{ {
int m = this.bytes.J - this.bytes.I; int m = this.Bytes.J - this.Bytes.I;
if (m > count) if (m > count)
{ {
m = count; m = count;
} }
this.bytes.I += m; this.Bytes.I += m;
count -= m; count -= m;
if (count == 0) if (count == 0)
{ {
break; break;
} }
this.bytes.Fill(this.inputStream); this.Bytes.Fill(this.InputStream);
} }
} }
@ -1453,8 +1423,8 @@ namespace ImageSharp.Formats
/// </summary> /// </summary>
private void UnreadByteStuffedByte() private void UnreadByteStuffedByte()
{ {
this.bytes.I -= this.bytes.UnreadableBytes; this.Bytes.I -= this.Bytes.UnreadableBytes;
this.bytes.UnreadableBytes = 0; this.Bytes.UnreadableBytes = 0;
if (this.Bits.UnreadBits >= 8) if (this.Bits.UnreadBits >= 8)
{ {
this.Bits.Accumulator >>= 8; this.Bits.Accumulator >>= 8;

Loading…
Cancel
Save