diff --git a/src/ImageProcessorCore/Formats/Png/GrayscaleReader.cs b/src/ImageProcessorCore/Formats/Png/GrayscaleReader.cs
deleted file mode 100644
index cc813a6eb..000000000
--- a/src/ImageProcessorCore/Formats/Png/GrayscaleReader.cs
+++ /dev/null
@@ -1,76 +0,0 @@
-//
-// Copyright (c) James Jackson-South and contributors.
-// Licensed under the Apache License, Version 2.0.
-//
-
-namespace ImageProcessorCore.Formats
-{
- ///
- /// Color reader for reading grayscale colors from a png file.
- ///
- internal sealed class GrayscaleReader : IColorReader
- {
- ///
- /// Whether t also read the alpha channel.
- ///
- private readonly bool useAlpha;
-
- ///
- /// The current row.
- ///
- private int row;
-
- ///
- /// Initializes a new instance of the class.
- ///
- ///
- /// If set to true the color reader will also read the
- /// alpha channel from the scanline.
- ///
- public GrayscaleReader(bool useAlpha)
- {
- this.useAlpha = useAlpha;
- }
-
- ///
- public void ReadScanline(byte[] scanline, T[] pixels, PngHeader header)
- where T : IPackedVector
- where TP : struct
- {
- int offset;
-
- byte[] newScanline = scanline.ToArrayByBitsLength(header.BitDepth);
-
- // Stored in r-> g-> b-> a order.
- if (this.useAlpha)
- {
- for (int x = 0; x < header.Width / 2; x++)
- {
- offset = (this.row * header.Width) + x;
-
- byte rgb = newScanline[x * 2];
- byte a = newScanline[(x * 2) + 1];
-
- T color = default(T);
- color.PackFromBytes(rgb, rgb, rgb, a);
- pixels[offset] = color;
- }
- }
- else
- {
- for (int x = 0; x < header.Width; x++)
- {
- offset = (this.row * header.Width) + x;
- byte rgb = newScanline[x];
-
- T color = default(T);
- color.PackFromBytes(rgb, rgb, rgb, 255);
-
- pixels[offset] = color;
- }
- }
-
- this.row++;
- }
- }
-}
diff --git a/src/ImageProcessorCore/Formats/Png/IColorReader.cs b/src/ImageProcessorCore/Formats/Png/IColorReader.cs
deleted file mode 100644
index 88ce0d4d2..000000000
--- a/src/ImageProcessorCore/Formats/Png/IColorReader.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-//
-// Copyright (c) James Jackson-South and contributors.
-// Licensed under the Apache License, Version 2.0.
-//
-
-namespace ImageProcessorCore.Formats
-{
- ///
- /// Encapsulates methods for color readers, which are responsible for reading
- /// different color formats from a png file.
- ///
- public interface IColorReader
- {
- ///
- /// Reads the specified scanline.
- ///
- /// The pixel format.
- /// The packed format. long, float.
- /// The scanline.
- /// The pixels to read the image row to.
- ///
- /// The header, which contains information about the png file, like
- /// the width of the image and the height.
- ///
- void ReadScanline(byte[] scanline, T[] pixels, PngHeader header)
- where T : IPackedVector
- where TP : struct;
- }
-}
diff --git a/src/ImageProcessorCore/Formats/Png/PaletteIndexReader.cs b/src/ImageProcessorCore/Formats/Png/PaletteIndexReader.cs
deleted file mode 100644
index 52d88e022..000000000
--- a/src/ImageProcessorCore/Formats/Png/PaletteIndexReader.cs
+++ /dev/null
@@ -1,95 +0,0 @@
-//
-// Copyright (c) James Jackson-South and contributors.
-// Licensed under the Apache License, Version 2.0.
-//
-
-namespace ImageProcessorCore.Formats
-{
- ///
- /// A color reader for reading palette indices from the png file.
- ///
- internal sealed class PaletteIndexReader : IColorReader
- {
- ///
- /// The palette.
- ///
- private readonly byte[] palette;
-
- ///
- /// The alpha palette.
- ///
- private readonly byte[] paletteAlpha;
-
- ///
- /// The current row.
- ///
- private int row;
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The palette as simple byte array. It will contains 3 values for each
- /// color, which represents the red-, the green- and the blue channel.
- /// The alpha palette. Can be null, if the image does not have an
- /// alpha channel and can contain less entries than the number of colors in the palette.
- public PaletteIndexReader(byte[] palette, byte[] paletteAlpha)
- {
- this.palette = palette;
- this.paletteAlpha = paletteAlpha;
- }
-
- ///
- public void ReadScanline(byte[] scanline, T[] pixels, PngHeader header)
- where T : IPackedVector
- where TP : struct
- {
- byte[] newScanline = scanline.ToArrayByBitsLength(header.BitDepth);
- int offset, index;
-
- if (this.paletteAlpha != null && this.paletteAlpha.Length > 0)
- {
- // If the alpha palette is not null and does one or
- // more entries, this means, that the image contains and alpha
- // channel and we should try to read it.
- for (int i = 0; i < header.Width; i++)
- {
- index = newScanline[i];
-
- offset = (this.row * header.Width) + i;
- int pixelOffset = index * 3;
-
- byte r = this.palette[pixelOffset];
- byte g = this.palette[pixelOffset + 1];
- byte b = this.palette[pixelOffset + 2];
- byte a = this.paletteAlpha.Length > index
- ? this.paletteAlpha[index]
- : (byte)255;
-
- T color = default(T);
- color.PackFromBytes(r, g, b, a);
- pixels[offset] = color;
- }
- }
- else
- {
- for (int i = 0; i < header.Width; i++)
- {
- index = newScanline[i];
-
- offset = (this.row * header.Width) + i;
- int pixelOffset = index * 3;
-
- byte r = this.palette[pixelOffset];
- byte g = this.palette[pixelOffset + 1];
- byte b = this.palette[pixelOffset + 2];
-
- T color = default(T);
- color.PackFromBytes(r, g, b, 255);
- pixels[offset] = color;
- }
- }
-
- this.row++;
- }
- }
-}
diff --git a/src/ImageProcessorCore/Formats/Png/PngColorTypeInformation.cs b/src/ImageProcessorCore/Formats/Png/PngColorTypeInformation.cs
deleted file mode 100644
index 9909cf47c..000000000
--- a/src/ImageProcessorCore/Formats/Png/PngColorTypeInformation.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-//
-// Copyright (c) James Jackson-South and contributors.
-// Licensed under the Apache License, Version 2.0.
-//
-
-namespace ImageProcessorCore.Formats
-{
- using System;
-
- ///
- /// Contains information that are required when loading a png with a specific color type.
- ///
- internal sealed class PngColorTypeInformation
- {
- ///
- /// Initializes a new instance of the class with
- /// the scanline factory, the function to create the color reader and the supported bit depths.
- ///
- /// The scanline factor.
- /// The supported bit depths.
- /// The factory to create the color reader.
- public PngColorTypeInformation(int scanlineFactor, int[] supportedBitDepths, Func scanlineReaderFactory)
- {
- this.ChannelsPerColor = scanlineFactor;
- this.ScanlineReaderFactory = scanlineReaderFactory;
- this.SupportedBitDepths = supportedBitDepths;
- }
-
- ///
- /// Gets an array with the bit depths that are supported for the color type
- /// where this object is created for.
- ///
- /// The supported bit depths that can be used in combination with this color type.
- public int[] SupportedBitDepths { get; private set; }
-
- ///
- /// Gets a function that is used the create the color reader for the color type where
- /// this object is created for.
- ///
- /// The factory function to create the color type.
- public Func ScanlineReaderFactory { get; private set; }
-
- ///
- /// Gets a factor that is used when iterating through the scan lines.
- ///
- /// The scanline factor.
- public int ChannelsPerColor { get; private set; }
-
- ///
- /// Creates the color reader for the color type where this object is create for.
- ///
- /// The palette of the image. Can be null when no palette is used.
- /// The alpha palette of the image. Can be null when
- /// no palette is used for the image or when the image has no alpha.
- /// The color reader for the image.
- public IColorReader CreateColorReader(byte[] palette, byte[] paletteAlpha)
- {
- return this.ScanlineReaderFactory(palette, paletteAlpha);
- }
- }
-}
diff --git a/src/ImageProcessorCore/Formats/Png/PngDecoderCore.cs b/src/ImageProcessorCore/Formats/Png/PngDecoderCore.cs
index f97e085d5..2e8f81c19 100644
--- a/src/ImageProcessorCore/Formats/Png/PngDecoderCore.cs
+++ b/src/ImageProcessorCore/Formats/Png/PngDecoderCore.cs
@@ -16,11 +16,10 @@ namespace ImageProcessorCore.Formats
///
internal class PngDecoderCore
{
- ///
- /// The dictionary of available color types.
- ///
- private static readonly Dictionary ColorTypes
- = new Dictionary();
+ /////
+ ///// The dictionary of available color types.
+ /////
+ private static readonly Dictionary ColorTypes = new Dictionary();
///
/// The stream to decode from.
@@ -32,29 +31,50 @@ namespace ImageProcessorCore.Formats
///
private PngHeader header;
+ ///
+ /// The number of bytes per pixel.
+ ///
+ private int bytesPerPixel;
+
+ ///
+ /// The number of bytes per sample
+ ///
+ private int bytesPerSample;
+
+ ///
+ /// The number of bytes per scanline
+ ///
+ private int bytesPerScanline;
+
+ ///
+ /// The palette containing color information for indexed pngs
+ ///
+ private byte[] palette;
+
+ ///
+ /// The palette containing alpha channel color information for indexed pngs
+ ///
+ private byte[] paletteAlpha;
+
+ ///
+ /// Gets or sets the png color type
+ ///
+ public PngColorType PngColorType { get; set; }
+
///
/// Initializes static members of the class.
///
static PngDecoderCore()
{
- ColorTypes.Add(
- 0,
- new PngColorTypeInformation(1, new[] { 1, 2, 4, 8 }, (p, a) => new GrayscaleReader(false)));
+ ColorTypes.Add((int)PngColorType.Grayscale, new byte[] { 1, 2, 4, 8 });
- ColorTypes.Add(
- 2,
- new PngColorTypeInformation(3, new[] { 8 }, (p, a) => new TrueColorReader(false)));
+ ColorTypes.Add((int)PngColorType.Rgb, new byte[] { 8 });
- ColorTypes.Add(
- 3,
- new PngColorTypeInformation(1, new[] { 1, 2, 4, 8 }, (p, a) => new PaletteIndexReader(p, a)));
+ ColorTypes.Add((int)PngColorType.Palette, new byte[] { 1, 2, 4, 8 });
- ColorTypes.Add(
- 4,
- new PngColorTypeInformation(2, new[] { 8 }, (p, a) => new GrayscaleReader(true)));
+ ColorTypes.Add((int)PngColorType.GrayscaleWithAlpha, new byte[] { 8 });
- ColorTypes.Add(6,
- new PngColorTypeInformation(4, new[] { 8 }, (p, a) => new TrueColorReader(true)));
+ ColorTypes.Add((int)PngColorType.RgbWithAlpha, new byte[] { 8 });
}
///
@@ -80,9 +100,6 @@ namespace ImageProcessorCore.Formats
bool isEndChunkReached = false;
- byte[] palette = null;
- byte[] paletteAlpha = null;
-
using (MemoryStream dataStream = new MemoryStream())
{
PngChunk currentChunk;
@@ -108,11 +125,12 @@ namespace ImageProcessorCore.Formats
}
else if (currentChunk.Type == PngChunkTypes.Palette)
{
- palette = currentChunk.Data;
+ this.palette = currentChunk.Data;
+ image.Quality = this.palette.Length / 3;
}
else if (currentChunk.Type == PngChunkTypes.PaletteAlpha)
{
- paletteAlpha = currentChunk.Data;
+ this.paletteAlpha = currentChunk.Data;
}
else if (currentChunk.Type == PngChunkTypes.Text)
{
@@ -133,54 +151,14 @@ namespace ImageProcessorCore.Formats
T[] pixels = new T[this.header.Width * this.header.Height];
- PngColorTypeInformation colorTypeInformation = ColorTypes[this.header.ColorType];
- if (colorTypeInformation != null)
- {
- IColorReader colorReader = colorTypeInformation.CreateColorReader(palette, paletteAlpha);
+ this.ReadScanlines(dataStream, pixels);
- this.ReadScanlines(dataStream, pixels, colorReader, colorTypeInformation);
- }
image.SetPixels(this.header.Width, this.header.Height, pixels);
}
}
- ///
- /// Computes a simple linear function of the three neighboring pixels (left, above, upper left), then chooses
- /// as predictor the neighboring pixel closest to the computed value.
- ///
- /// The left neighbour pixel.
- /// The above neighbour pixel.
- /// The upper left neighbour pixel.
- ///
- /// The .
- ///
- private static byte PaethPredicator(byte left, byte above, byte upperLeft)
- {
- byte predicator;
-
- int p = left + above - upperLeft;
- int pa = Math.Abs(p - left);
- int pb = Math.Abs(p - above);
- int pc = Math.Abs(p - upperLeft);
-
- if (pa <= pb && pa <= pc)
- {
- predicator = left;
- }
- else if (pb <= pc)
- {
- predicator = above;
- }
- else
- {
- predicator = upperLeft;
- }
-
- return predicator;
- }
-
///
/// Reads the data chunk containing physical dimension data.
///
@@ -200,14 +178,41 @@ namespace ImageProcessorCore.Formats
image.VerticalResolution = BitConverter.ToInt32(data, 4) / 39.3700787d;
}
+ ///
+ /// Calculates the correct number of bytes per pixel for the given color type.
+ ///
+ /// The
+ private int CalculateBytesPerPixel()
+ {
+ switch (this.PngColorType)
+ {
+ case PngColorType.Grayscale:
+ return 1;
+
+ case PngColorType.GrayscaleWithAlpha:
+ return 2;
+
+ case PngColorType.Palette:
+ return 1;
+
+ case PngColorType.Rgb:
+ return 3;
+
+ // PngColorType.RgbWithAlpha
+ // TODO: Maybe figure out a way to detect if there are any transparent
+ // pixels and encode RGB if none.
+ default:
+ return 4;
+ }
+ }
+
///
/// Calculates the scanline length.
///
- /// The color type information.
/// The representing the length.
- private int CalculateScanlineLength(PngColorTypeInformation colorTypeInformation)
+ private int CalculateScanlineLength()
{
- int scanlineLength = this.header.Width * this.header.BitDepth * colorTypeInformation.ChannelsPerColor;
+ int scanlineLength = this.header.Width * this.header.BitDepth * this.bytesPerPixel;
int amount = scanlineLength % 8;
if (amount != 0)
@@ -219,103 +224,227 @@ namespace ImageProcessorCore.Formats
}
///
- /// Calculates a scanline step.
+ /// Reads the scanlines within the image.
///
- /// The color type information.
- /// The representing the length of each step.
- private int CalculateScanlineStep(PngColorTypeInformation colorTypeInformation)
+ /// The containing data.
+ ///
+ /// The containing pixel data.
+ private void ReadScanlines(MemoryStream dataStream, T[] pixels)
+ where T : IPackedVector
+ where TP : struct
{
- int scanlineStep = 1;
-
+ this.bytesPerPixel = this.CalculateBytesPerPixel();
+ this.bytesPerScanline = this.CalculateScanlineLength() + 1;
+ this.bytesPerSample = 1;
if (this.header.BitDepth >= 8)
{
- scanlineStep = (colorTypeInformation.ChannelsPerColor * this.header.BitDepth) / 8;
+ this.bytesPerSample = (this.header.BitDepth) / 8;
}
- return scanlineStep;
+ dataStream.Position = 0;
+ using (ZlibInflateStream compressedStream = new ZlibInflateStream(dataStream))
+ {
+ using (MemoryStream decompressedStream = new MemoryStream())
+ {
+ compressedStream.CopyTo(decompressedStream);
+ decompressedStream.Flush();
+
+ byte[] decompressedBytes = decompressedStream.ToArray();
+ DecodePixelData(decompressedBytes, pixels);
+ }
+ }
}
///
- /// Reads the scanlines within the image.
+ /// Decodes the raw pixel data row by row
///
- /// The containing data.
- ///
- /// The containing pixel data.
- /// The color reader.
- /// The color type information.
- private void ReadScanlines(MemoryStream dataStream, T[] pixels, IColorReader colorReader, PngColorTypeInformation colorTypeInformation)
+ /// The pixel format.
+ /// The packed format. long, float.
+ /// The pixel data.
+ /// The image pixels.
+ private void DecodePixelData(byte[] pixelData, T[] pixels)
where T : IPackedVector
where TP : struct
{
- dataStream.Position = 0;
+ byte[] previousScanline = new byte[this.bytesPerScanline];
- int scanlineLength = this.CalculateScanlineLength(colorTypeInformation);
- int scanlineStep = this.CalculateScanlineStep(colorTypeInformation);
+ for (int y = 0; y < this.header.Height; y++)
+ {
+ byte[] scanline = new byte[this.bytesPerScanline];
+ Array.Copy(pixelData, y * this.bytesPerScanline, scanline, 0, this.bytesPerScanline);
+ FilterType filterType = (FilterType)scanline[0];
+ byte[] defilteredScanline;
- byte[] lastScanline = new byte[scanlineLength];
- byte[] currentScanline = new byte[scanlineLength];
- int filter = 0, column = -1;
+ switch (filterType)
+ {
+ case FilterType.None:
- using (ZlibInflateStream compressedStream = new ZlibInflateStream(dataStream))
+ defilteredScanline = NoneFilter.Decode(scanline);
+
+ break;
+
+ case FilterType.Sub:
+
+ defilteredScanline = SubFilter.Decode(scanline, bytesPerPixel);
+
+ break;
+
+ case FilterType.Up:
+
+ defilteredScanline = UpFilter.Decode(scanline, previousScanline);
+
+ break;
+
+ case FilterType.Average:
+
+ defilteredScanline = AverageFilter.Decode(scanline, previousScanline, bytesPerPixel);
+
+ break;
+
+ case FilterType.Paeth:
+
+ defilteredScanline = PaethFilter.Decode(scanline, previousScanline, bytesPerPixel);
+
+ break;
+
+ default:
+ throw new ImageFormatException("Unknown filter type.");
+ }
+
+ previousScanline = defilteredScanline;
+ ProcessDefilteredScanline(defilteredScanline, y, pixels);
+ }
+ }
+
+ ///
+ /// Processes the defiltered scanline filling the image pixel data
+ ///
+ /// The pixel format.
+ /// The packed format. long, float.
+ ///
+ /// The current image row.
+ /// The image pixels
+ private void ProcessDefilteredScanline(byte[] defilteredScanline, int row, T[] pixels)
+ where T : IPackedVector
+ where TP : struct
+ {
+ switch (this.PngColorType)
{
- int readByte;
- while ((readByte = compressedStream.ReadByte()) >= 0)
- {
- if (column == -1)
+ case PngColorType.Grayscale:
+
+ for (int x = 0; x < this.header.Width; x++)
{
- filter = readByte;
+ int offset = 1 + (x * bytesPerPixel);
+
+ byte intensity = defilteredScanline[offset];
- column++;
+ T color = default(T);
+ color.PackFromBytes(intensity, intensity, intensity, 255);
+ pixels[(row * this.header.Width) + x] = color;
}
- else
+
+ break;
+
+ case PngColorType.GrayscaleWithAlpha:
+
+ for (int x = 0; x < this.header.Width; x++)
{
- currentScanline[column] = (byte)readByte;
+ int offset = 1 + (x * bytesPerPixel);
- byte a;
- byte b;
- byte c;
+ byte intensity = defilteredScanline[offset];
+ byte alpha = defilteredScanline[offset + bytesPerSample];
- if (column >= scanlineStep)
- {
- a = currentScanline[column - scanlineStep];
- c = lastScanline[column - scanlineStep];
- }
- else
- {
- a = 0;
- c = 0;
- }
+ T color = default(T);
+ color.PackFromBytes(intensity, intensity, intensity, alpha);
+ pixels[(row * this.header.Width) + x] = color;
+ }
- b = lastScanline[column];
+ break;
- if (filter == 1)
- {
- currentScanline[column] = (byte)(currentScanline[column] + a);
- }
- else if (filter == 2)
- {
- currentScanline[column] = (byte)(currentScanline[column] + b);
- }
- else if (filter == 3)
+ case PngColorType.Palette:
+
+ byte[] newScanline = defilteredScanline.ToArrayByBitsLength(header.BitDepth);
+
+ if (this.paletteAlpha != null && this.paletteAlpha.Length > 0)
+ {
+ // If the alpha palette is not null and has one or more entries, this means, that the image contains an alpha
+ // channel and we should try to read it.
+ for (int i = 0; i < header.Width; i++)
{
- currentScanline[column] = (byte)(currentScanline[column] + (byte)((a + b) / 2));
+ int index = newScanline[i];
+ int offset = (row * header.Width) + i;
+ int pixelOffset = index * 3;
+
+ byte a = this.paletteAlpha.Length > index ? this.paletteAlpha[index] : (byte)255;
+ T color = default(T);
+ if (a > 0)
+ {
+ byte r = this.palette[pixelOffset];
+ byte g = this.palette[pixelOffset + 1];
+ byte b = this.palette[pixelOffset + 2];
+ color.PackFromBytes(r, g, b, a);
+ }
+
+ pixels[offset] = color;
}
- else if (filter == 4)
+ }
+ else
+ {
+ for (int i = 0; i < header.Width; i++)
{
- currentScanline[column] = (byte)(currentScanline[column] + PaethPredicator(a, b, c));
+ int index = newScanline[i];
+ int offset = (row * header.Width) + i;
+ int pixelOffset = index * 3;
+
+ byte r = this.palette[pixelOffset];
+ byte g = this.palette[pixelOffset + 1];
+ byte b = this.palette[pixelOffset + 2];
+
+ T color = default(T);
+ color.PackFromBytes(r, g, b, 255);
+ pixels[offset] = color;
}
+ }
- column++;
+ break;
- if (column == scanlineLength)
- {
- colorReader.ReadScanline(currentScanline, pixels, this.header);
- column = -1;
+ case PngColorType.Rgb:
- this.Swap(ref currentScanline, ref lastScanline);
- }
+ for (int x = 0; x < this.header.Width; x++)
+ {
+ int offset = 1 + (x * bytesPerPixel);
+
+ byte r = defilteredScanline[offset];
+ byte g = defilteredScanline[offset + bytesPerSample];
+ byte b = defilteredScanline[offset + 2 * bytesPerSample];
+
+ T color = default(T);
+ color.PackFromBytes(r, g, b, 255);
+ pixels[(row * this.header.Width) + x] = color;
}
- }
+
+ break;
+
+ case PngColorType.RgbWithAlpha:
+
+ for (int x = 0; x < this.header.Width; x++)
+ {
+ int offset = 1 + (x * bytesPerPixel);
+
+ byte r = defilteredScanline[offset];
+ byte g = defilteredScanline[offset + bytesPerSample];
+ byte b = defilteredScanline[offset + 2 * bytesPerSample];
+ byte a = defilteredScanline[offset + 3 * bytesPerSample];
+
+ T color = default(T);
+ color.PackFromBytes(r, g, b, a);
+ pixels[(row * this.header.Width) + x] = color;
+ }
+
+ break;
+
+ default:
+ break;
}
}
@@ -381,7 +510,7 @@ namespace ImageProcessorCore.Formats
throw new NotSupportedException("Color type is not supported or not valid.");
}
- if (!ColorTypes[this.header.ColorType].SupportedBitDepths.Contains(this.header.BitDepth))
+ if (!ColorTypes[this.header.ColorType].Contains(this.header.BitDepth))
{
throw new NotSupportedException("Bit depth is not supported or not valid.");
}
@@ -396,6 +525,8 @@ namespace ImageProcessorCore.Formats
// TODO: Support interlacing
throw new NotSupportedException("Interlacing is not supported.");
}
+
+ this.PngColorType = (PngColorType)this.header.ColorType;
}
///
@@ -525,20 +656,5 @@ namespace ImageProcessorCore.Formats
return numBytes;
}
-
- ///
- /// Swaps two references.
- ///
- /// The type of the references to swap.
- /// The first reference.
- /// The second reference.
- private void Swap(ref TRef lhs, ref TRef rhs)
- where TRef : class
- {
- TRef tmp = lhs;
-
- lhs = rhs;
- rhs = tmp;
- }
}
}
diff --git a/src/ImageProcessorCore/Formats/Png/PngEncoderCore.cs b/src/ImageProcessorCore/Formats/Png/PngEncoderCore.cs
index 2381ae44c..97ab62dff 100644
--- a/src/ImageProcessorCore/Formats/Png/PngEncoderCore.cs
+++ b/src/ImageProcessorCore/Formats/Png/PngEncoderCore.cs
@@ -126,7 +126,7 @@ namespace ImageProcessorCore.Formats
this.Quality = quality > 0 ? quality.Clamp(1, int.MaxValue) : int.MaxValue;
// Set correct color type if the color count is 256 or less.
- if (Quality <= 256)
+ if (this.Quality <= 256)
{
this.PngColorType = PngColorType.Palette;
}
diff --git a/src/ImageProcessorCore/Formats/Png/TrueColorReader.cs b/src/ImageProcessorCore/Formats/Png/TrueColorReader.cs
deleted file mode 100644
index 86ac7db38..000000000
--- a/src/ImageProcessorCore/Formats/Png/TrueColorReader.cs
+++ /dev/null
@@ -1,81 +0,0 @@
-//
-// Copyright (c) James Jackson-South and contributors.
-// Licensed under the Apache License, Version 2.0.
-//
-
-namespace ImageProcessorCore.Formats
-{
- ///
- /// Color reader for reading true colors from a png file. Only colors
- /// with 24 or 32 bit (3 or 4 bytes) per pixel are supported at the moment.
- ///
- internal sealed class TrueColorReader : IColorReader
- {
- ///
- /// Whether t also read the alpha channel.
- ///
- private readonly bool useAlpha;
-
- ///
- /// The current row.
- ///
- private int row;
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// if set to true the color reader will also read the
- /// alpha channel from the scanline.
- public TrueColorReader(bool useAlpha)
- {
- this.useAlpha = useAlpha;
- }
-
- ///
- public void ReadScanline(byte[] scanline, T[] pixels, PngHeader header)
- where T : IPackedVector
- where TP : struct
- {
- int offset;
-
- byte[] newScanline = scanline.ToArrayByBitsLength(header.BitDepth);
-
- if (this.useAlpha)
- {
- for (int x = 0; x < newScanline.Length; x += 4)
- {
- offset = (this.row * header.Width) + (x >> 2);
-
- // We want to convert to premultiplied alpha here.
- byte r = newScanline[x];
- byte g = newScanline[x + 1];
- byte b = newScanline[x + 2];
- byte a = newScanline[x + 3];
-
- T color = default(T);
- color.PackFromBytes(r, g, b, a);
-
- pixels[offset] = color;
- }
- }
- else
- {
- for (int x = 0; x < newScanline.Length / 3; x++)
- {
- offset = (this.row * header.Width) + x;
- int pixelOffset = x * 3;
-
- byte r = newScanline[pixelOffset];
- byte g = newScanline[pixelOffset + 1];
- byte b = newScanline[pixelOffset + 2];
-
- T color = default(T);
- color.PackFromBytes(r, g, b, 255);
- pixels[offset] = color;
- }
- }
-
- this.row++;
- }
- }
-}