diff --git a/Settings.StyleCop b/Settings.StyleCop
index 0eabc6cf3..b7a5355e0 100644
--- a/Settings.StyleCop
+++ b/Settings.StyleCop
@@ -31,6 +31,7 @@
ss
Vol
pp
+ cmyk
diff --git a/src/ImageSharp/Formats/Jpg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpg/JpegDecoderCore.cs
index 39a24db00..ede58a5f4 100644
--- a/src/ImageSharp/Formats/Jpg/JpegDecoderCore.cs
+++ b/src/ImageSharp/Formats/Jpg/JpegDecoderCore.cs
@@ -34,15 +34,24 @@ namespace ImageSharp.Formats
///
private const int MaxComponents = 4;
- private const int maxTc = 1;
+ private const int MaxTc = 1;
- private const int maxTh = 3;
+ private const int MaxTh = 3;
- private const int maxTq = 3;
+ ///
+ /// The maximum number of quantization tables
+ ///
+ private const int MaxTq = 3;
- private const int dcTable = 0;
+ ///
+ /// The DC table index
+ ///
+ private const int DcTable = 0;
- private const int acTable = 1;
+ ///
+ /// The AC table index
+ ///
+ private const int AcTable = 1;
///
/// Unzig maps from the zigzag ordering to the natural ordering. For example,
@@ -77,6 +86,11 @@ namespace ImageSharp.Formats
///
private readonly Block[] quantizationTables;
+ ///
+ /// A temporary buffer for holding pixels
+ ///
+ private readonly byte[] temp;
+
///
/// The byte buffer.
///
@@ -142,8 +156,14 @@ namespace ImageSharp.Formats
///
private bool isJfif;
+ ///
+ /// Whether the image is in CMYK format with an App14 marker
+ ///
private bool adobeTransformValid;
+ ///
+ /// The App14 marker color-space
+ ///
private byte adobeTransform;
///
@@ -151,11 +171,6 @@ namespace ImageSharp.Formats
///
private ushort eobRun;
- ///
- /// A temporary buffer for holding pixels
- ///
- private byte[] temp;
-
///
/// The horizontal resolution. Calculated if the image has a JFIF header.
///
@@ -171,17 +186,17 @@ namespace ImageSharp.Formats
///
public JpegDecoderCore()
{
- this.huffmanTrees = new Huffman[maxTc + 1, maxTh + 1];
- this.quantizationTables = new Block[maxTq + 1];
+ this.huffmanTrees = new Huffman[MaxTc + 1, MaxTh + 1];
+ this.quantizationTables = new Block[MaxTq + 1];
this.temp = new byte[2 * Block.BlockSize];
this.componentArray = new Component[MaxComponents];
this.progCoeffs = new Block[MaxComponents][];
this.bits = new Bits();
this.bytes = new Bytes();
- for (int i = 0; i < maxTc + 1; i++)
+ for (int i = 0; i < MaxTc + 1; i++)
{
- for (int j = 0; j < maxTh + 1; j++)
+ for (int j = 0; j < MaxTh + 1; j++)
{
this.huffmanTrees[i, j] = new Huffman(LutSize, MaxNCodes, MaxCodeLength);
}
@@ -204,10 +219,8 @@ namespace ImageSharp.Formats
///
/// The pixel format.
/// The packed format. uint, long, float.
- /// The stream, where the image should be
- /// decoded from. Cannot be null (Nothing in Visual Basic).
- /// The image, where the data should be set to.
- /// Cannot be null (Nothing in Visual Basic).
+ /// The image, where the data should be set to.
+ /// The stream, where the image should be.
/// Whether to decode metadata only.
public void Decode(Image image, Stream stream, bool configOnly)
where TColor : struct, IPackedPixel
@@ -283,7 +296,7 @@ namespace ImageSharp.Formats
// Read the 16-bit length of the segment. The value includes the 2 bytes for the
// length itself, so we subtract 2 to get the number of remaining bytes.
this.ReadFull(this.temp, 0, 2);
- int remaining = ((int)this.temp[0] << 8) + (int)this.temp[1] - 2;
+ int remaining = (this.temp[0] << 8) + this.temp[1] - 2;
if (remaining < 0)
{
throw new ImageFormatException("Short segment length.");
@@ -295,7 +308,7 @@ namespace ImageSharp.Formats
case JpegConstants.Markers.SOF1:
case JpegConstants.Markers.SOF2:
this.isProgressive = marker == JpegConstants.Markers.SOF2;
- this.ProcessSOF(remaining);
+ this.ProcessStartOfFrameMarker(remaining);
if (configOnly && this.isJfif)
{
return;
@@ -309,7 +322,7 @@ namespace ImageSharp.Formats
}
else
{
- this.ProcessDht(remaining);
+ this.ProcessDefineHuffmanTablesMarker(remaining);
}
break;
@@ -335,12 +348,12 @@ namespace ImageSharp.Formats
}
else
{
- this.ProcessDri(remaining);
+ this.ProcessDefineRestartIntervalMarker(remaining);
}
break;
case JpegConstants.Markers.APP0:
- this.ProcessApp0Marker(remaining);
+ this.ProcessApplicationHeader(remaining);
break;
case JpegConstants.Markers.APP1:
this.ProcessApp1Marker(remaining, image);
@@ -457,12 +470,12 @@ namespace ImageSharp.Formats
/// Processes a Define Huffman Table marker, and initializes a huffman
/// struct from its contents. Specified in section B.2.4.2.
///
- ///
- private void ProcessDht(int n)
+ /// The remaining bytes in the segment block.
+ private void ProcessDefineHuffmanTablesMarker(int remaining)
{
- while (n > 0)
+ while (remaining > 0)
{
- if (n < 17)
+ if (remaining < 17)
{
throw new ImageFormatException("DHT has wrong length");
}
@@ -470,13 +483,13 @@ namespace ImageSharp.Formats
this.ReadFull(this.temp, 0, 17);
int tc = this.temp[0] >> 4;
- if (tc > maxTc)
+ if (tc > MaxTc)
{
throw new ImageFormatException("Bad Tc value");
}
int th = this.temp[0] & 0x0f;
- if (th > maxTh || (!this.isProgressive && (th > 1)))
+ if (th > MaxTh || (!this.isProgressive && (th > 1)))
{
throw new ImageFormatException("Bad Th value");
}
@@ -505,8 +518,8 @@ namespace ImageSharp.Formats
throw new ImageFormatException("Huffman table has excessive length");
}
- n -= huffman.Length + 17;
- if (n < 0)
+ remaining -= huffman.Length + 17;
+ if (remaining < 0)
{
throw new ImageFormatException("DHT has wrong length");
}
@@ -571,8 +584,7 @@ namespace ImageSharp.Formats
}
///
- /// Returns the next Huffman-coded value from the bit-stream,
- /// decoded according to the given value.
+ /// Returns the next Huffman-coded value from the bit-stream, decoded according to the given value.
///
/// The huffman value
/// The
@@ -868,15 +880,18 @@ namespace ImageSharp.Formats
}
}
- // Specified in section B.2.2.
- private void ProcessSOF(int n)
+ ///
+ /// Processes the Start of Frame marker. Specified in section B.2.2.
+ ///
+ /// The remaining bytes in the segment block.
+ private void ProcessStartOfFrameMarker(int remaining)
{
if (this.componentCount != 0)
{
- throw new ImageFormatException("multiple SOF markers");
+ throw new ImageFormatException("Multiple SOF markers");
}
- switch (n)
+ switch (remaining)
{
case 6 + (3 * 1): // Grayscale image.
this.componentCount = 1;
@@ -891,7 +906,7 @@ namespace ImageSharp.Formats
throw new ImageFormatException("Incorrect number of components");
}
- this.ReadFull(this.temp, 0, n);
+ this.ReadFull(this.temp, 0, remaining);
// We only support 8-bit precision.
if (this.temp[0] != 8)
@@ -921,7 +936,7 @@ namespace ImageSharp.Formats
}
this.componentArray[i].Selector = this.temp[8 + (3 * i)];
- if (this.componentArray[i].Selector > maxTq)
+ if (this.componentArray[i].Selector > MaxTq)
{
throw new ImageFormatException("Bad Tq value");
}
@@ -1053,17 +1068,23 @@ namespace ImageSharp.Formats
}
}
- // Specified in section B.2.4.1.
- private void ProcessDqt(int n)
+ ///
+ /// Processes the Define Quantization Marker and tables. Specified in section B.2.4.1.
+ ///
+ /// The remaining bytes in the segment block.
+ ///
+ /// Thrown if the tables do not match the header
+ ///
+ private void ProcessDqt(int remaining)
{
- while (n > 0)
+ while (remaining > 0)
{
bool done = false;
- n--;
+ remaining--;
byte x = this.ReadByte();
byte tq = (byte)(x & 0x0f);
- if (tq > maxTq)
+ if (tq > MaxTq)
{
throw new ImageFormatException("Bad Tq value");
}
@@ -1071,13 +1092,13 @@ namespace ImageSharp.Formats
switch (x >> 4)
{
case 0:
- if (n < Block.BlockSize)
+ if (remaining < Block.BlockSize)
{
done = true;
break;
}
- n -= Block.BlockSize;
+ remaining -= Block.BlockSize;
this.ReadFull(this.temp, 0, Block.BlockSize);
for (int i = 0; i < Block.BlockSize; i++)
@@ -1087,13 +1108,13 @@ namespace ImageSharp.Formats
break;
case 1:
- if (n < 2 * Block.BlockSize)
+ if (remaining < 2 * Block.BlockSize)
{
done = true;
break;
}
- n -= 2 * Block.BlockSize;
+ remaining -= 2 * Block.BlockSize;
this.ReadFull(this.temp, 0, 2 * Block.BlockSize);
for (int i = 0; i < Block.BlockSize; i++)
@@ -1112,16 +1133,19 @@ namespace ImageSharp.Formats
}
}
- if (n != 0)
+ if (remaining != 0)
{
throw new ImageFormatException("DQT has wrong length");
}
}
- // Specified in section B.2.4.4.
- private void ProcessDri(int n)
+ ///
+ /// Processes the DRI (Define Restart Interval Marker) Which specifies the interval between RSTn markers, in macroblocks
+ ///
+ /// The remaining bytes in the segment block.
+ private void ProcessDefineRestartIntervalMarker(int remaining)
{
- if (n != 2)
+ if (remaining != 2)
{
throw new ImageFormatException("DRI has wrong length");
}
@@ -1130,16 +1154,20 @@ namespace ImageSharp.Formats
this.restartInterval = ((int)this.temp[0] << 8) + (int)this.temp[1];
}
- private void ProcessApp0Marker(int n)
+ ///
+ /// Processes the application header containing the JFIF identifier plus extra data.
+ ///
+ /// The remaining bytes in the segment block.
+ private void ProcessApplicationHeader(int remaining)
{
- if (n < 5)
+ if (remaining < 5)
{
- this.Skip(n);
+ this.Skip(remaining);
return;
}
this.ReadFull(this.temp, 0, 13);
- n -= 13;
+ remaining -= 13;
// TODO: We should be using constants for this.
this.isJfif = this.temp[0] == 'J' &&
@@ -1154,9 +1182,9 @@ namespace ImageSharp.Formats
this.verticalResolution = (short)(this.temp[11] + (this.temp[12] << 8));
}
- if (n > 0)
+ if (remaining > 0)
{
- this.Skip(n);
+ this.Skip(remaining);
}
}
@@ -1165,20 +1193,20 @@ namespace ImageSharp.Formats
///
/// The pixel format.
/// The packed format. uint, long, float.
- /// The position in the stream.
+ /// The remaining bytes in the segment block.
/// The image.
- private void ProcessApp1Marker(int n, Image image)
+ private void ProcessApp1Marker(int remaining, Image image)
where TColor : struct, IPackedPixel
where TPacked : struct
{
- if (n < 6)
+ if (remaining < 6)
{
- this.Skip(n);
+ this.Skip(remaining);
return;
}
- byte[] profile = new byte[n];
- this.ReadFull(profile, 0, n);
+ byte[] profile = new byte[remaining];
+ this.ReadFull(profile, 0, remaining);
if (profile[0] == 'E' &&
profile[1] == 'x' &&
@@ -1191,16 +1219,22 @@ namespace ImageSharp.Formats
}
}
- private void ProcessApp14Marker(int n)
+ ///
+ /// Processes the "Adobe" APP14 segment stores image encoding information for DCT filters.
+ /// This segment may be copied or deleted as a block using the Extra "Adobe" tag, but note that it is not
+ /// deleted by default when deleting all metadata because it may affect the appearance of the image.
+ ///
+ /// The remaining number of bytes in the stream.
+ private void ProcessApp14Marker(int remaining)
{
- if (n < 12)
+ if (remaining < 12)
{
- this.Skip(n);
+ this.Skip(remaining);
return;
}
this.ReadFull(this.temp, 0, 12);
- n -= 12;
+ remaining -= 12;
if (this.temp[0] == 'A' &&
this.temp[1] == 'd' &&
@@ -1212,14 +1246,14 @@ namespace ImageSharp.Formats
this.adobeTransform = this.temp[11];
}
- if (n > 0)
+ if (remaining > 0)
{
- this.Skip(n);
+ this.Skip(remaining);
}
}
///
- /// Converts the image from the original Cmyk image pixels.
+ /// Converts the image from the original CMYK image pixels.
///
/// The pixel format.
/// The packed format. uint, long, float.
@@ -1241,40 +1275,41 @@ namespace ImageSharp.Formats
{
int scale = this.componentArray[0].HorizontalFactor / this.componentArray[1].HorizontalFactor;
- TColor[] pixels = new TColor[width * height];
-
- // Convert the YCbCr part of the YCbCrK to RGB, invert the RGB to get
- // CMY, and patch in the original K. The RGB to CMY inversion cancels
- // out the 'Adobe inversion' described in the applyBlack doc comment
- // above, so in practice, only the fourth channel (black) is inverted.
- Parallel.For(
- 0,
- height,
- y =>
- {
- int yo = this.ycbcrImage.GetRowYOffset(y);
- int co = this.ycbcrImage.GetRowCOffset(y);
+ image.InitPixels(width, height);
- for (int x = 0; x < width; x++)
+ using (PixelAccessor pixels = image.Lock())
+ {
+ // Convert the YCbCr part of the YCbCrK to RGB, invert the RGB to get
+ // CMY, and patch in the original K. The RGB to CMY inversion cancels
+ // out the 'Adobe inversion' described in the applyBlack doc comment
+ // above, so in practice, only the fourth channel (black) is inverted.
+ Parallel.For(
+ 0,
+ height,
+ y =>
{
- byte yy = this.ycbcrImage.YChannel[yo + x];
- byte cb = this.ycbcrImage.CbChannel[co + (x / scale)];
- byte cr = this.ycbcrImage.CrChannel[co + (x / scale)];
+ int yo = this.ycbcrImage.GetRowYOffset(y);
+ int co = this.ycbcrImage.GetRowCOffset(y);
- int index = (y * width) + x;
-
- // Implicit casting FTW
- Color color = new YCbCr(yy, cb, cr);
- int keyline = 255 - this.blackPixels[(y * this.blackStride) + x];
- Color final = new Cmyk(color.R / 255F, color.G / 255F, color.B / 255F, keyline / 255F);
-
- TColor packed = default(TColor);
- packed.PackFromVector4(final.ToVector4());
- pixels[index] = packed;
- }
- });
+ for (int x = 0; x < width; x++)
+ {
+ byte yy = this.ycbcrImage.YChannel[yo + x];
+ byte cb = this.ycbcrImage.CbChannel[co + (x / scale)];
+ byte cr = this.ycbcrImage.CrChannel[co + (x / scale)];
+
+ // Implicit casting FTW
+ Color color = new YCbCr(yy, cb, cr);
+ int keyline = 255 - this.blackPixels[(y * this.blackStride) + x];
+ Color final = new Cmyk(color.R / 255F, color.G / 255F, color.B / 255F, keyline / 255F);
+
+ TColor packed = default(TColor);
+ packed.PackFromBytes(final.R, final.G, final.B, final.A);
+ pixels[x, y] = packed;
+ }
+ });
+ }
- image.SetPixels(width, height, pixels);
+ this.AssignResolution(image);
}
}
@@ -1290,27 +1325,28 @@ namespace ImageSharp.Formats
where TColor : struct, IPackedPixel
where TPacked : struct
{
- TColor[] pixels = new TColor[width * height];
+ image.InitPixels(width, height);
- Parallel.For(
- 0,
- height,
- Bootstrapper.Instance.ParallelOptions,
- y =>
- {
- int yoff = this.grayImage.GetRowOffset(y);
- for (int x = 0; x < width; x++)
+ using (PixelAccessor pixels = image.Lock())
+ {
+ Parallel.For(
+ 0,
+ height,
+ Bootstrapper.Instance.ParallelOptions,
+ y =>
{
- int offset = (y * width) + x;
- byte rgb = this.grayImage.Pixels[yoff + x];
+ int yoff = this.grayImage.GetRowOffset(y);
+ for (int x = 0; x < width; x++)
+ {
+ byte rgb = this.grayImage.Pixels[yoff + x];
- TColor packed = default(TColor);
- packed.PackFromVector4(new Color(rgb, rgb, rgb).ToVector4());
- pixels[offset] = packed;
- }
- });
+ TColor packed = default(TColor);
+ packed.PackFromBytes(rgb, rgb, rgb, 255);
+ pixels[x, y] = packed;
+ }
+ });
+ }
- image.SetPixels(width, height, pixels);
this.AssignResolution(image);
}
@@ -1327,14 +1363,15 @@ namespace ImageSharp.Formats
where TPacked : struct
{
int scale = this.componentArray[0].HorizontalFactor / this.componentArray[1].HorizontalFactor;
+ image.InitPixels(width, height);
- TColor[] pixels = new TColor[width * height];
-
- Parallel.For(
- 0,
- height,
- Bootstrapper.Instance.ParallelOptions,
- y =>
+ using (PixelAccessor pixels = image.Lock())
+ {
+ Parallel.For(
+ 0,
+ height,
+ Bootstrapper.Instance.ParallelOptions,
+ y =>
{
int yo = this.ycbcrImage.GetRowYOffset(y);
int co = this.ycbcrImage.GetRowCOffset(y);
@@ -1345,17 +1382,15 @@ namespace ImageSharp.Formats
byte cb = this.ycbcrImage.CbChannel[co + (x / scale)];
byte cr = this.ycbcrImage.CrChannel[co + (x / scale)];
- int index = (y * width) + x;
-
// Implicit casting FTW
Color color = new YCbCr(yy, cb, cr);
TColor packed = default(TColor);
- packed.PackFromVector4(color.ToVector4());
- pixels[index] = packed;
+ packed.PackFromBytes(color.R, color.G, color.B, color.A);
+ pixels[x, y] = packed;
}
});
+ }
- image.SetPixels(width, height, pixels);
this.AssignResolution(image);
}
@@ -1372,13 +1407,15 @@ namespace ImageSharp.Formats
where TPacked : struct
{
int scale = this.componentArray[0].HorizontalFactor / this.componentArray[1].HorizontalFactor;
- TColor[] pixels = new TColor[width * height];
+ image.InitPixels(width, height);
- Parallel.For(
- 0,
- height,
- Bootstrapper.Instance.ParallelOptions,
- y =>
+ using (PixelAccessor pixels = image.Lock())
+ {
+ Parallel.For(
+ 0,
+ height,
+ Bootstrapper.Instance.ParallelOptions,
+ y =>
{
int yo = this.ycbcrImage.GetRowYOffset(y);
int co = this.ycbcrImage.GetRowCOffset(y);
@@ -1389,15 +1426,13 @@ namespace ImageSharp.Formats
byte green = this.ycbcrImage.CbChannel[co + (x / scale)];
byte blue = this.ycbcrImage.CrChannel[co + (x / scale)];
- int index = (y * width) + x;
TColor packed = default(TColor);
- packed.PackFromVector4(new Color(red, green, blue).ToVector4());
-
- pixels[index] = packed;
+ packed.PackFromBytes(red, green, blue, 255);
+ pixels[x, y] = packed;
}
});
+ }
- image.SetPixels(width, height, pixels);
this.AssignResolution(image);
}
@@ -1424,29 +1459,27 @@ namespace ImageSharp.Formats
///
/// TODO: This also needs some significant refactoring to follow a more OO format.
///
- ///
- /// The first byte of the current image marker.
- ///
+ /// The remaining bytes in the segment block.
///
/// Missing SOF Marker
/// SOS has wrong length
///
- private void ProcessStartOfScan(int n)
+ private void ProcessStartOfScan(int remaining)
{
if (this.componentCount == 0)
{
throw new ImageFormatException("Missing SOF marker");
}
- if (n < 6 || 4 + (2 * this.componentCount) < n || n % 2 != 0)
+ if (remaining < 6 || 4 + (2 * this.componentCount) < remaining || remaining % 2 != 0)
{
throw new ImageFormatException("SOS has wrong length");
}
- this.ReadFull(this.temp, 0, n);
- byte lnComp = this.temp[0];
+ this.ReadFull(this.temp, 0, remaining);
+ byte scanComponentCount = this.temp[0];
- if (n != 4 + (2 * lnComp))
+ if (remaining != 4 + (2 * scanComponentCount))
{
throw new ImageFormatException("SOS length inconsistent with number of components");
}
@@ -1454,7 +1487,7 @@ namespace ImageSharp.Formats
Scan[] scan = new Scan[MaxComponents];
int totalHv = 0;
- for (int i = 0; i < lnComp; i++)
+ for (int i = 0; i < scanComponentCount; i++)
{
// Component selector.
int cs = this.temp[1 + (2 * i)];
@@ -1488,17 +1521,16 @@ namespace ImageSharp.Formats
}
}
- totalHv += this.componentArray[compIndex].HorizontalFactor
- * this.componentArray[compIndex].VerticalFactor;
+ totalHv += this.componentArray[compIndex].HorizontalFactor * this.componentArray[compIndex].VerticalFactor;
scan[i].DcTableSelector = (byte)(this.temp[2 + (2 * i)] >> 4);
- if (scan[i].DcTableSelector > maxTh)
+ if (scan[i].DcTableSelector > MaxTh)
{
throw new ImageFormatException("Bad DC table selector value");
}
scan[i].AcTableSelector = (byte)(this.temp[2 + (2 * i)] & 0x0f);
- if (scan[i].AcTableSelector > maxTh)
+ if (scan[i].AcTableSelector > MaxTh)
{
throw new ImageFormatException("Bad AC table selector value");
}
@@ -1532,17 +1564,17 @@ namespace ImageSharp.Formats
if (this.isProgressive)
{
- zigStart = (int)this.temp[1 + (2 * lnComp)];
- zigEnd = (int)this.temp[2 + (2 * lnComp)];
- ah = (int)(this.temp[3 + (2 * lnComp)] >> 4);
- al = (int)(this.temp[3 + (2 * lnComp)] & 0x0f);
+ zigStart = this.temp[1 + (2 * scanComponentCount)];
+ zigEnd = this.temp[2 + (2 * scanComponentCount)];
+ ah = this.temp[3 + (2 * scanComponentCount)] >> 4;
+ al = this.temp[3 + (2 * scanComponentCount)] & 0x0f;
if ((zigStart == 0 && zigEnd != 0) || zigStart > zigEnd || Block.BlockSize <= zigEnd)
{
throw new ImageFormatException("Bad spectral selection bounds");
}
- if (zigStart != 0 && lnComp != 1)
+ if (zigStart != 0 && scanComponentCount != 1)
{
throw new ImageFormatException("Progressive AC coefficients for more than one component");
}
@@ -1566,7 +1598,7 @@ namespace ImageSharp.Formats
if (this.isProgressive)
{
- for (int i = 0; i < lnComp; i++)
+ for (int i = 0; i < scanComponentCount; i++)
{
int compIndex = scan[i].Index;
if (this.progCoeffs[compIndex] == null)
@@ -1586,7 +1618,7 @@ namespace ImageSharp.Formats
int mcu = 0;
byte expectedRst = JpegConstants.Markers.RST0;
- // b is the decoded coefficients, in natural (not zig-zag) order.
+ // b is the decoded coefficients block, in natural (not zig-zag) order.
Block b;
int[] dc = new int[MaxComponents];
@@ -1598,7 +1630,7 @@ namespace ImageSharp.Formats
{
for (int mx = 0; mx < mxx; mx++)
{
- for (int i = 0; i < lnComp; i++)
+ for (int i = 0; i < scanComponentCount; i++)
{
int compIndex = scan[i].Index;
int hi = this.componentArray[compIndex].HorizontalFactor;
@@ -1612,7 +1644,7 @@ namespace ImageSharp.Formats
// For a baseline 32x16 pixel image, the Y blocks visiting order is:
// 0 1 4 5
// 2 3 6 7
- // For progressive images, the interleaved scans (those with nComp > 1)
+ // For progressive images, the interleaved scans (those with component count > 1)
// are traversed as above, but non-interleaved scans are traversed left
// to right, top to bottom:
// 0 1 2 3
@@ -1629,7 +1661,7 @@ namespace ImageSharp.Formats
// The non-interleaved scans will process only 6 Y blocks:
// 0 1 2
// 3 4 5
- if (lnComp != 1)
+ if (scanComponentCount != 1)
{
bx = (hi * mx) + (j % hi);
by = (vi * my) + (j / hi);
@@ -1651,7 +1683,7 @@ namespace ImageSharp.Formats
if (ah != 0)
{
- this.Refine(b, this.huffmanTrees[acTable, scan[i].AcTableSelector], zigStart, zigEnd, 1 << al);
+ this.Refine(b, this.huffmanTrees[AcTable, scan[i].AcTableSelector], zigStart, zigEnd, 1 << al);
}
else
{
@@ -1661,14 +1693,14 @@ namespace ImageSharp.Formats
zig++;
// Decode the DC coefficient, as specified in section F.2.2.1.
- byte value = this.DecodeHuffman(this.huffmanTrees[dcTable, scan[i].DcTableSelector]);
+ byte value = this.DecodeHuffman(this.huffmanTrees[DcTable, scan[i].DcTableSelector]);
if (value > 16)
{
throw new ImageFormatException("Excessive DC component");
}
- int dcDelta = this.ReceiveExtend(value);
- dc[compIndex] += dcDelta;
+ int deltaDC = this.ReceiveExtend(value);
+ dc[compIndex] += deltaDC;
b[0] = dc[compIndex] << al;
}
@@ -1679,7 +1711,7 @@ namespace ImageSharp.Formats
else
{
// Decode the AC coefficients, as specified in section F.2.2.2.
- Huffman huffv = this.huffmanTrees[acTable, scan[i].AcTableSelector];
+ Huffman huffv = this.huffmanTrees[AcTable, scan[i].AcTableSelector];
for (; zig <= zigEnd; zig++)
{
byte value = this.DecodeHuffman(huffv);
@@ -1853,11 +1885,11 @@ namespace ImageSharp.Formats
///
/// Decodes a successive approximation refinement block, as specified in section G.1.2.
///
- ///
- ///
- ///
- ///
- ///
+ /// The block of coefficients
+ /// The Huffman tree
+ /// The zig-zag start index
+ /// The zig-zag end index
+ /// The low transform offset
private void Refine(Block b, Huffman h, int zigStart, int zigEnd, int delta)
{
// Refining a DC component is trivial.
@@ -1897,8 +1929,7 @@ namespace ImageSharp.Formats
this.eobRun = (ushort)(1 << val0);
if (val0 != 0)
{
- uint bits = this.DecodeBits(val0);
- this.eobRun |= (ushort)bits;
+ this.eobRun |= (ushort)this.DecodeBits(val0);
}
done = true;
@@ -1943,8 +1974,16 @@ namespace ImageSharp.Formats
}
}
- // refineNonZeroes refines non-zero entries of b in zig-zag order. If nz >= 0,
- // the first nz zero entries are skipped over.
+ ///
+ /// Refines non-zero entries of b in zig-zag order.
+ /// If >= 0, the first zero entries are skipped over.
+ ///
+ /// The block of coefficients
+ /// The zig-zag start index
+ /// The zig-zag end index
+ /// The non-zero entry
+ /// The low transform offset
+ /// The
private int RefineNonZeroes(Block b, int zig, int zigEnd, int nz, int delta)
{
for (; zig <= zigEnd; zig++)
@@ -1983,14 +2022,14 @@ namespace ImageSharp.Formats
///
/// Makes the image from the buffer.
///
- ///
- ///
+ /// The horizontal MCU count
+ /// The vertical MCU count
private void MakeImage(int mxx, int myy)
{
if (this.componentCount == 1)
{
- GrayImage m = new GrayImage(8 * mxx, 8 * myy);
- this.grayImage = m.Subimage(0, 0, this.imageWidth, this.imageHeight);
+ GrayImage gray = new GrayImage(8 * mxx, 8 * myy);
+ this.grayImage = gray.Subimage(0, 0, this.imageWidth, this.imageHeight);
}
else
{
@@ -2022,8 +2061,8 @@ namespace ImageSharp.Formats
break;
}
- YCbCrImage m = new YCbCrImage(8 * h0 * mxx, 8 * v0 * myy, ratio);
- this.ycbcrImage = m.Subimage(0, 0, this.imageWidth, this.imageHeight);
+ YCbCrImage ycbcr = new YCbCrImage(8 * h0 * mxx, 8 * v0 * myy, ratio);
+ this.ycbcrImage = ycbcr.Subimage(0, 0, this.imageWidth, this.imageHeight);
if (this.componentCount == 4)
{
@@ -2093,6 +2132,10 @@ namespace ImageSharp.Formats
{
}
+ ///
+ /// The EOF (End of File exception).
+ /// Thrown when the decoder encounters an EOF marker without a proceeding EOI (End Of Image) marker
+ ///
private class EOFException : Exception
{
}
diff --git a/src/ImageSharp/Formats/Jpg/JpegEncoderCore.cs b/src/ImageSharp/Formats/Jpg/JpegEncoderCore.cs
index a5c9be547..4e35ed8de 100644
--- a/src/ImageSharp/Formats/Jpg/JpegEncoderCore.cs
+++ b/src/ImageSharp/Formats/Jpg/JpegEncoderCore.cs
@@ -348,7 +348,7 @@ namespace ImageSharp.Formats
this.WriteProfiles(image);
// Write the quantization tables.
- this.WriteDescreteQuantizationTables();
+ this.WriteDefineQuantizationTables();
// Write the image dimensions.
this.WriteStartOfFrame(image.Width, image.Height, componentCount);
@@ -661,9 +661,9 @@ namespace ImageSharp.Formats
}
///
- /// Writes the Define Quantization Marker and tables.
+ /// Writes the Define Quantization Marker and tables.
///
- private void WriteDescreteQuantizationTables()
+ private void WriteDefineQuantizationTables()
{
int markerlen = 2 + (NQuantIndex * (1 + Block.BlockSize));
this.WriteMarkerHeader(JpegConstants.Markers.DQT, markerlen);
diff --git a/tests/ImageSharp.Tests/FileTestBase.cs b/tests/ImageSharp.Tests/FileTestBase.cs
index 855c3a7af..2b53d0253 100644
--- a/tests/ImageSharp.Tests/FileTestBase.cs
+++ b/tests/ImageSharp.Tests/FileTestBase.cs
@@ -22,7 +22,7 @@ namespace ImageSharp.Tests
//new TestFile(TestImages.Png.Pd),
new TestFile(TestImages.Jpeg.Floorplan), // Perf: Enable for local testing only
new TestFile(TestImages.Jpeg.Calliphora),
- //new TestFile(TestImages.Jpeg.Cmyk), // Perf: Enable for local testing only
+ new TestFile(TestImages.Jpeg.Cmyk), // Perf: Enable for local testing only
new TestFile(TestImages.Jpeg.Turtle),
//new TestFile(TestImages.Jpeg.Fb), // Perf: Enable for local testing only
//new TestFile(TestImages.Jpeg.Progress), // Perf: Enable for local testing only