diff --git a/src/ImageProcessor/Colors/Color.cs b/src/ImageProcessor/Colors/Color.cs
index e2bff3e03..58bfd4040 100644
--- a/src/ImageProcessor/Colors/Color.cs
+++ b/src/ImageProcessor/Colors/Color.cs
@@ -31,18 +31,10 @@ namespace ImageProcessor
///
/// Initializes a new instance of the struct.
///
- ///
- /// The red component of this .
- ///
- ///
- /// The green component of this .
- ///
- ///
- /// The blue component of this .
- ///
- ///
- /// The alpha component of this .
- ///
+ /// The red component of this .
+ /// The green component of this .
+ /// The blue component of this .
+ /// The alpha component of this .
public Color(float r, float g, float b, float a)
: this()
{
diff --git a/src/ImageProcessor/Formats/Bmp/BmpDecoderCore.cs b/src/ImageProcessor/Formats/Bmp/BmpDecoderCore.cs
index fe4a7c889..fa434da84 100644
--- a/src/ImageProcessor/Formats/Bmp/BmpDecoderCore.cs
+++ b/src/ImageProcessor/Formats/Bmp/BmpDecoderCore.cs
@@ -1,12 +1,7 @@
-// --------------------------------------------------------------------------------------------------------------------
-//
-// Copyright (c) James South and contributors.
-// Licensed under the Apache License, Version 2.0.
+//
+// Copyright (c) James South and contributors.
+// Licensed under the Apache License, Version 2.0.
//
-//
-// Performs the bmp decoding operation.
-//
-// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Formats
{
@@ -109,7 +104,7 @@ namespace ImageProcessor.Formats
+ $"bigger then the max allowed size '{ImageBase.MaxWidth}x{ImageBase.MaxHeight}'");
}
- byte[] imageData = new byte[this.infoHeader.Width * this.infoHeader.Height * 4];
+ float[] imageData = new float[this.infoHeader.Width * this.infoHeader.Height * 4];
switch (this.infoHeader.Compression)
{
@@ -180,12 +175,12 @@ namespace ImageProcessor.Formats
///
/// Reads the color palette from the stream.
///
- /// The image data to assign the palette to.
+ /// The image data to assign the palette to.
/// The containing the colors.
/// The width of the bitmap.
/// The height of the bitmap.
/// The number of bits per pixel.
- private void ReadRgbPalette(byte[] imageData, byte[] colors, int width, int height, int bits)
+ private void ReadRgbPalette(float[] imageData, byte[] colors, int width, int height, int bits)
{
// Pixels per byte (bits per pixel)
int ppb = 8 / bits;
@@ -224,13 +219,15 @@ namespace ImageProcessor.Formats
for (int shift = 0; shift < ppb && (colOffset + shift) < width; shift++)
{
- int colorIndex = (data[offset] >> (8 - bits - (shift * bits))) & mask;
-
+ int colorIndex = ((data[offset] >> (8 - bits - (shift * bits))) & mask) * 4;
int arrayOffset = ((row * width) + (colOffset + shift)) * 4;
- imageData[arrayOffset + 0] = colors[colorIndex * 4];
- imageData[arrayOffset + 1] = colors[(colorIndex * 4) + 1];
- imageData[arrayOffset + 2] = colors[(colorIndex * 4) + 2];
- imageData[arrayOffset + 3] = 255;
+
+ // We divide by 255 as we will store the colors in our floating point format.
+ // Stored in r-> g-> b-> a order.
+ imageData[arrayOffset] = colors[colorIndex + 2] / 255f; // r
+ imageData[arrayOffset + 1] = colors[colorIndex + 1] / 255f; // g
+ imageData[arrayOffset + 2] = colors[colorIndex] / 255f; // b
+ imageData[arrayOffset + 3] = 1; // a
}
}
});
@@ -239,13 +236,14 @@ namespace ImageProcessor.Formats
///
/// Reads the 16 bit color palette from the stream
///
- /// The image data to assign the palette to.
+ /// The image data to assign the palette to.
/// The width of the bitmap.
/// The height of the bitmap.
- private void ReadRgb16(byte[] imageData, int width, int height)
+ private void ReadRgb16(float[] imageData, int width, int height)
{
- const int ScaleR = 256 / 32;
- const int ScaleG = 256 / 64;
+ // We divide here as we will store the colors in our floating point format.
+ const int ScaleR = (256 / 32) / 32;
+ const int ScaleG = (256 / 64) / 64;
int alignment;
byte[] data = this.GetImageArray(width, height, 2, out alignment);
@@ -266,16 +264,17 @@ namespace ImageProcessor.Formats
short temp = BitConverter.ToInt16(data, offset);
- byte r = (byte)(((temp & Rgb16RMask) >> 11) * ScaleR);
- byte g = (byte)(((temp & Rgb16GMask) >> 5) * ScaleG);
- byte b = (byte)((temp & Rgb16BMask) * ScaleR);
+ float r = ((temp & Rgb16RMask) >> 11) * ScaleR;
+ float g = ((temp & Rgb16GMask) >> 5) * ScaleG;
+ float b = (temp & Rgb16BMask) * ScaleR;
int arrayOffset = ((row * width) + x) * 4;
- imageData[arrayOffset + 0] = b;
+ // Stored in r-> g-> b-> a order.
+ imageData[arrayOffset] = r;
imageData[arrayOffset + 1] = g;
- imageData[arrayOffset + 2] = r;
- imageData[arrayOffset + 3] = 255;
+ imageData[arrayOffset + 2] = b;
+ imageData[arrayOffset + 3] = 1;
}
});
}
@@ -283,10 +282,10 @@ namespace ImageProcessor.Formats
///
/// Reads the 24 bit color palette from the stream
///
- /// The image data to assign the palette to.
+ /// The image data to assign the palette to.
/// The width of the bitmap.
/// The height of the bitmap.
- private void ReadRgb24(byte[] imageData, int width, int height)
+ private void ReadRgb24(float[] imageData, int width, int height)
{
int alignment;
byte[] data = this.GetImageArray(width, height, 3, out alignment);
@@ -306,10 +305,12 @@ namespace ImageProcessor.Formats
int offset = rowOffset + (x * 3);
int arrayOffset = ((row * width) + x) * 4;
- imageData[arrayOffset + 0] = data[offset + 0];
- imageData[arrayOffset + 1] = data[offset + 1];
- imageData[arrayOffset + 2] = data[offset + 2];
- imageData[arrayOffset + 3] = 255;
+ // We divide by 255 as we will store the colors in our floating point format.
+ // Stored in r-> g-> b-> a order.
+ imageData[arrayOffset] = data[offset + 2] / 255f;
+ imageData[arrayOffset + 1] = data[offset + 1] / 255f;
+ imageData[arrayOffset + 2] = data[offset] / 255f;
+ imageData[arrayOffset + 3] = 1;
}
});
}
@@ -317,10 +318,10 @@ namespace ImageProcessor.Formats
///
/// Reads the 32 bit color palette from the stream
///
- /// The image data to assign the palette to.
+ /// The image data to assign the palette to.
/// The width of the bitmap.
/// The height of the bitmap.
- private void ReadRgb32(byte[] imageData, int width, int height)
+ private void ReadRgb32(float[] imageData, int width, int height)
{
int alignment;
byte[] data = this.GetImageArray(width, height, 4, out alignment);
@@ -338,12 +339,14 @@ namespace ImageProcessor.Formats
for (int x = 0; x < width; x++)
{
int offset = rowOffset + (x * 4);
+ int arrayOffset = ((row * width) + x) * 4;
- var arrayOffset = ((row * width) + x) * 4;
- imageData[arrayOffset + 0] = data[offset + 0];
- imageData[arrayOffset + 1] = data[offset + 1];
- imageData[arrayOffset + 2] = data[offset + 2];
- imageData[arrayOffset + 3] = 255; // Can we get alpha here?
+ // We divide by 255 as we will store the colors in our floating point format.
+ // Stored in r-> g-> b-> a order.
+ imageData[arrayOffset] = data[offset + 2] / 255f;
+ imageData[arrayOffset + 1] = data[offset + 1] / 255f;
+ imageData[arrayOffset + 2] = data[offset] / 255f;
+ imageData[arrayOffset + 3] = 1; // TODO: Can we use our real alpha here?
}
});
}
diff --git a/src/ImageProcessor/Formats/Bmp/BmpEncoder.cs b/src/ImageProcessor/Formats/Bmp/BmpEncoder.cs
index ed833bf62..c37809635 100644
--- a/src/ImageProcessor/Formats/Bmp/BmpEncoder.cs
+++ b/src/ImageProcessor/Formats/Bmp/BmpEncoder.cs
@@ -100,7 +100,7 @@ namespace ImageProcessor.Formats
amount = 4 - amount;
}
- byte[] data = image.Pixels;
+ float[] data = image.Pixels;
for (int y = image.Height - 1; y >= 0; y--)
{
@@ -108,9 +108,11 @@ namespace ImageProcessor.Formats
{
int offset = ((y * image.Width) + x) * 4;
- writer.Write(data[offset + 0]);
- writer.Write(data[offset + 1]);
- writer.Write(data[offset + 2]);
+ // Limit the output range and multiply out from our floating point.
+ // Convert back to b-> g-> r-> a order.
+ writer.Write((byte)(data[offset + 2].Clamp(0, 1) * 255));
+ writer.Write((byte)(data[offset + 1].Clamp(0, 1) * 255));
+ writer.Write((byte)(data[offset].Clamp(0, 1) * 255));
}
for (int i = 0; i < amount; i++)
diff --git a/src/ImageProcessor/Formats/Gif/GifDecoderCore.cs b/src/ImageProcessor/Formats/Gif/GifDecoderCore.cs
index ae91b3d03..8675cbc7a 100644
--- a/src/ImageProcessor/Formats/Gif/GifDecoderCore.cs
+++ b/src/ImageProcessor/Formats/Gif/GifDecoderCore.cs
@@ -31,7 +31,7 @@ namespace ImageProcessor.Formats
///
/// The current frame.
///
- private byte[] currentFrame;
+ private float[] currentFrame;
///
/// The logical screen descriptor.
@@ -288,15 +288,15 @@ namespace ImageProcessor.Formats
if (this.currentFrame == null)
{
- this.currentFrame = new byte[imageWidth * imageHeight * 4];
+ this.currentFrame = new float[imageWidth * imageHeight * 4];
}
- byte[] lastFrame = null;
+ float[] lastFrame = null;
if (this.graphicsControlExtension != null &&
this.graphicsControlExtension.DisposalMethod == DisposalMethod.RestoreToPrevious)
{
- lastFrame = new byte[imageWidth * imageHeight * 4];
+ lastFrame = new float[imageWidth * imageHeight * 4];
Array.Copy(this.currentFrame, lastFrame, lastFrame.Length);
}
@@ -352,18 +352,20 @@ namespace ImageProcessor.Formats
this.graphicsControlExtension.TransparencyFlag == false ||
this.graphicsControlExtension.TransparencyIndex != index)
{
+ // We divide by 255 as we will store the colors in our floating point format.
+ // Stored in r-> g-> b-> a order.
int indexOffset = index * 3;
- this.currentFrame[offset + 0] = colorTable[indexOffset + 2];
- this.currentFrame[offset + 1] = colorTable[indexOffset + 1];
- this.currentFrame[offset + 2] = colorTable[indexOffset + 0];
- this.currentFrame[offset + 3] = 255;
+ this.currentFrame[offset + 0] = colorTable[indexOffset] / 255f; // r
+ this.currentFrame[offset + 1] = colorTable[indexOffset + 1] / 255f; // g
+ this.currentFrame[offset + 2] = colorTable[indexOffset + 2] / 255f; // b
+ this.currentFrame[offset + 3] = 1; // a
}
i++;
}
}
- byte[] pixels = new byte[imageWidth * imageHeight * 4];
+ float[] pixels = new float[imageWidth * imageHeight * 4];
Array.Copy(this.currentFrame, pixels, pixels.Length);
@@ -406,6 +408,7 @@ namespace ImageProcessor.Formats
{
offset = ((y * imageWidth) + x) * 4;
+ // Stored in r-> g-> b-> a order.
this.currentFrame[offset + 0] = 0;
this.currentFrame[offset + 1] = 0;
this.currentFrame[offset + 2] = 0;
diff --git a/src/ImageProcessor/Formats/Gif/Quantizer/OctreeQuantizer.cs b/src/ImageProcessor/Formats/Gif/Quantizer/OctreeQuantizer.cs
index 1b08f16d7..6efdae1be 100644
--- a/src/ImageProcessor/Formats/Gif/Quantizer/OctreeQuantizer.cs
+++ b/src/ImageProcessor/Formats/Gif/Quantizer/OctreeQuantizer.cs
@@ -199,7 +199,7 @@ namespace ImageProcessor.Formats
{
// If so, check if I have a previous node setup. This will only occur if the first color in the image
// happens to be black, with an alpha component of zero.
- if (null == this.previousNode)
+ if (this.previousNode == null)
{
this.previousColor = pixel.BGRA;
this.root.AddColor(pixel, this.maxColorBits, 0, this);
@@ -274,7 +274,7 @@ namespace ImageProcessor.Formats
{
// Find the deepest level containing at least one reducible node
int index = this.maxColorBits - 1;
- while ((index > 0) && (null == this.reducibleNodes[index]))
+ while ((index > 0) && (this.reducibleNodes[index] == null))
{
index--;
}
@@ -407,7 +407,7 @@ namespace ImageProcessor.Formats
OctreeNode child = this.children[index];
- if (null == child)
+ if (child == null)
{
// Create a new child node and store it in the array
child = new OctreeNode(level + 1, colorBits, octree);
@@ -431,7 +431,7 @@ namespace ImageProcessor.Formats
// Loop through all children and add their information to this node
for (int index = 0; index < 8; index++)
{
- if (null != this.children[index])
+ if (this.children[index] != null)
{
this.red += this.children[index].red;
this.green += this.children[index].green;
@@ -477,7 +477,7 @@ namespace ImageProcessor.Formats
// Loop through children looking for leaves
for (int i = 0; i < 8; i++)
{
- if (null != this.children[i])
+ if (this.children[i] != null)
{
this.children[i].ConstructPalette(palette, ref index);
}
@@ -508,7 +508,7 @@ namespace ImageProcessor.Formats
((pixel.G & Mask[level]) >> (shift - 1)) |
((pixel.B & Mask[level]) >> shift);
- if (null != this.children[pixelIndex])
+ if (this.children[pixelIndex] != null)
{
index = this.children[pixelIndex].GetPaletteIndex(pixel, level + 1);
}
diff --git a/src/ImageProcessor/Formats/Gif/Quantizer/QuantizedImage.cs b/src/ImageProcessor/Formats/Gif/Quantizer/QuantizedImage.cs
index da55ff020..5bb8f9ec6 100644
--- a/src/ImageProcessor/Formats/Gif/Quantizer/QuantizedImage.cs
+++ b/src/ImageProcessor/Formats/Gif/Quantizer/QuantizedImage.cs
@@ -69,7 +69,7 @@ namespace ImageProcessor.Formats
Image image = new Image();
int pixelCount = this.Pixels.Length;
- byte[] bgraPixels = new byte[pixelCount * 4];
+ float[] bgraPixels = new float[pixelCount * 4];
for (int i = 0; i < pixelCount; i++)
{
diff --git a/src/ImageProcessor/Formats/Gif/Quantizer/Quantizer.cs b/src/ImageProcessor/Formats/Gif/Quantizer/Quantizer.cs
index a374ae3b5..c35a9f7f4 100644
--- a/src/ImageProcessor/Formats/Gif/Quantizer/Quantizer.cs
+++ b/src/ImageProcessor/Formats/Gif/Quantizer/Quantizer.cs
@@ -18,7 +18,7 @@ namespace ImageProcessor.Formats
private readonly bool singlePass;
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
///
/// If true, the quantization only needs to loop through the source pixels once
@@ -56,6 +56,7 @@ namespace ImageProcessor.Formats
byte[] quantizedPixels = new byte[width * height];
+ // Get the pallete
List palette = this.GetPalette();
this.SecondPass(imageBase, quantizedPixels, width, height);
@@ -94,7 +95,8 @@ namespace ImageProcessor.Formats
{
int i = 0;
- // Convert the first pixel, so that I have values going into the loop
+ // Convert the first pixel, so that I have values going into the loop.
+ // Implicit cast here from Color.
Bgra32 previousPixel = source[0, 0];
byte pixelValue = this.QuantizePixel(previousPixel);
@@ -104,6 +106,7 @@ namespace ImageProcessor.Formats
{
for (int x = 0; x < width; x++)
{
+ // Implicit cast here from Color.
Bgra32 sourcePixel = source[x, y];
// Check if this is the same as the last pixel. If so use that value
diff --git a/src/ImageProcessor/Formats/Jpg/JpegDecoder.cs b/src/ImageProcessor/Formats/Jpg/JpegDecoder.cs
index 587a1bf18..541400a4e 100644
--- a/src/ImageProcessor/Formats/Jpg/JpegDecoder.cs
+++ b/src/ImageProcessor/Formats/Jpg/JpegDecoder.cs
@@ -99,7 +99,7 @@ namespace ImageProcessor.Formats
int pixelWidth = jpg.Width;
int pixelHeight = jpg.Height;
- byte[] pixels = new byte[pixelWidth * pixelHeight * 4];
+ float[] pixels = new float[pixelWidth * pixelHeight * 4];
if (!(jpg.Colorspace == Colorspace.RGB && jpg.BitsPerComponent == 8))
{
@@ -119,10 +119,10 @@ namespace ImageProcessor.Formats
int offset = ((y * pixelWidth) + x) * 4;
- pixels[offset + 0] = (byte)sample[2];
- pixels[offset + 1] = (byte)sample[1];
- pixels[offset + 2] = (byte)sample[0];
- pixels[offset + 3] = 255;
+ pixels[offset + 0] = sample[0] / 255f;
+ pixels[offset + 1] = sample[1] / 255f;
+ pixels[offset + 2] = sample[2] / 255f;
+ pixels[offset + 3] = 1;
}
});
diff --git a/src/ImageProcessor/Formats/Jpg/JpegEncoder.cs b/src/ImageProcessor/Formats/Jpg/JpegEncoder.cs
index 60971697c..84ce9c423 100644
--- a/src/ImageProcessor/Formats/Jpg/JpegEncoder.cs
+++ b/src/ImageProcessor/Formats/Jpg/JpegEncoder.cs
@@ -89,7 +89,7 @@ namespace ImageProcessor.Formats
int pixelWidth = image.Width;
int pixelHeight = image.Height;
- byte[] sourcePixels = image.Pixels;
+ float[] sourcePixels = image.Pixels;
SampleRow[] rows = new SampleRow[pixelHeight];
@@ -105,9 +105,9 @@ namespace ImageProcessor.Formats
int start = x * 3;
int source = ((y * pixelWidth) + x) * 4;
- samples[start] = sourcePixels[source + 2];
- samples[start + 1] = sourcePixels[source + 1];
- samples[start + 2] = sourcePixels[source];
+ samples[start] = (byte)(sourcePixels[source].Clamp(0, 1) * 255);
+ samples[start + 1] = (byte)(sourcePixels[source + 1].Clamp(0, 1) * 255);
+ samples[start + 2] = (byte)(sourcePixels[source + 2].Clamp(0, 1) * 255);
}
rows[y] = new SampleRow(samples, pixelWidth, 8, 3);
diff --git a/src/ImageProcessor/Formats/Png/GrayscaleReader.cs b/src/ImageProcessor/Formats/Png/GrayscaleReader.cs
index 552776a67..244c0e8c0 100644
--- a/src/ImageProcessor/Formats/Png/GrayscaleReader.cs
+++ b/src/ImageProcessor/Formats/Png/GrayscaleReader.cs
@@ -1,12 +1,7 @@
-// --------------------------------------------------------------------------------------------------------------------
-//
-// Copyright (c) James South and contributors.
-// Licensed under the Apache License, Version 2.0.
+//
+// Copyright (c) James South and contributors.
+// Licensed under the Apache License, Version 2.0.
//
-//
-// Color reader for reading grayscale colors from a png file.
-//
-// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Formats
{
@@ -37,31 +32,25 @@ namespace ImageProcessor.Formats
this.useAlpha = useAlpha;
}
- ///
- /// Reads the specified scanline.
- ///
- /// The scanline.
- /// The pixels, where the colors should be stored in BGRA format.
- ///
- /// The header, which contains information about the png file, like
- /// the width of the image and the height.
- ///
- public void ReadScanline(byte[] scanline, byte[] pixels, PngHeader header)
+ ///
+ public void ReadScanline(byte[] scanline, float[] pixels, PngHeader header)
{
int offset;
byte[] newScanline = scanline.ToArrayByBitsLength(header.BitDepth);
+ // We divide by 255 as we will store the colors in our floating point format.
+ // 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) * 4;
- pixels[offset + 0] = newScanline[x * 2];
- pixels[offset + 1] = newScanline[x * 2];
- pixels[offset + 2] = newScanline[x * 2];
- pixels[offset + 3] = newScanline[(x * 2) + 1];
+ pixels[offset] = newScanline[x * 2] / 255f;
+ pixels[offset + 1] = newScanline[x * 2] / 255f;
+ pixels[offset + 2] = newScanline[x * 2] / 255f;
+ pixels[offset + 3] = newScanline[(x * 2) + 1] / 255f;
}
}
else
@@ -70,10 +59,10 @@ namespace ImageProcessor.Formats
{
offset = ((this.row * header.Width) + x) * 4;
- pixels[offset + 0] = newScanline[x];
- pixels[offset + 1] = newScanline[x];
- pixels[offset + 2] = newScanline[x];
- pixels[offset + 3] = 255;
+ pixels[offset] = newScanline[x] / 255f;
+ pixels[offset + 1] = newScanline[x] / 255f;
+ pixels[offset + 2] = newScanline[x] / 255f;
+ pixels[offset + 3] = 1;
}
}
diff --git a/src/ImageProcessor/Formats/Png/IColorReader.cs b/src/ImageProcessor/Formats/Png/IColorReader.cs
index 40c14d6ec..0d7ff27e3 100644
--- a/src/ImageProcessor/Formats/Png/IColorReader.cs
+++ b/src/ImageProcessor/Formats/Png/IColorReader.cs
@@ -1,18 +1,12 @@
-// --------------------------------------------------------------------------------------------------------------------
-//
-// Copyright (c) James South and contributors.
-// Licensed under the Apache License, Version 2.0.
+//
+// Copyright (c) James South and contributors.
+// Licensed under the Apache License, Version 2.0.
//
-//
-// Encapsulates methods for color readers, which are responsible for reading
-// different color formats from a png file.
-//
-// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Formats
{
///
- /// Encapsulates methods for color readers, which are responsible for reading
+ /// Encapsulates methods for color readers, which are responsible for reading
/// different color formats from a png file.
///
public interface IColorReader
@@ -26,6 +20,6 @@ namespace ImageProcessor.Formats
/// The header, which contains information about the png file, like
/// the width of the image and the height.
///
- void ReadScanline(byte[] scanline, byte[] pixels, PngHeader header);
+ void ReadScanline(byte[] scanline, float[] pixels, PngHeader header);
}
}
diff --git a/src/ImageProcessor/Formats/Png/PaletteIndexReader.cs b/src/ImageProcessor/Formats/Png/PaletteIndexReader.cs
index a44d34c29..550ac358b 100644
--- a/src/ImageProcessor/Formats/Png/PaletteIndexReader.cs
+++ b/src/ImageProcessor/Formats/Png/PaletteIndexReader.cs
@@ -1,12 +1,7 @@
-// --------------------------------------------------------------------------------------------------------------------
-//
-// Copyright (c) James South and contributors.
-// Licensed under the Apache License, Version 2.0.
+//
+// Copyright (c) James South and contributors.
+// Licensed under the Apache License, Version 2.0.
//
-//
-// A color reader for reading palette indices from the png file.
-//
-// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Formats
{
@@ -43,14 +38,8 @@ namespace ImageProcessor.Formats
this.paletteAlpha = paletteAlpha;
}
- ///
- /// Reads the specified scanline.
- ///
- /// The scanline.
- /// The pixels, where the colors should be stored in BGRA format.
- /// The header, which contains information about the png file, like
- /// the width of the image and the height.
- public void ReadScanline(byte[] scanline, byte[] pixels, PngHeader header)
+ ///
+ public void ReadScanline(byte[] scanline, float[] pixels, PngHeader header)
{
byte[] newScanline = scanline.ToArrayByBitsLength(header.BitDepth);
int offset, index;
@@ -65,13 +54,14 @@ namespace ImageProcessor.Formats
index = newScanline[i];
offset = ((this.row * header.Width) + i) * 4;
+ int pixelOffset = index * 3;
- pixels[offset + 0] = this.palette[(index * 3) + 2];
- pixels[offset + 1] = this.palette[(index * 3) + 1];
- pixels[offset + 2] = this.palette[(index * 3) + 0];
+ pixels[offset] = this.palette[pixelOffset] / 255f;
+ pixels[offset + 1] = this.palette[pixelOffset + 1] / 255f;
+ pixels[offset + 2] = this.palette[pixelOffset + 2] / 255f;
pixels[offset + 3] = this.paletteAlpha.Length > index
- ? this.paletteAlpha[index]
- : (byte)255;
+ ? this.paletteAlpha[index] / 255f
+ : 1;
}
}
else
@@ -81,11 +71,12 @@ namespace ImageProcessor.Formats
index = newScanline[i];
offset = ((this.row * header.Width) + i) * 4;
+ int pixelOffset = index * 3;
- pixels[offset + 0] = this.palette[(index * 3) + 2];
- pixels[offset + 1] = this.palette[(index * 3) + 1];
- pixels[offset + 2] = this.palette[(index * 3) + 0];
- pixels[offset + 3] = 255;
+ pixels[offset] = this.palette[pixelOffset] / 255f;
+ pixels[offset + 1] = this.palette[pixelOffset + 1] / 255f;
+ pixels[offset + 2] = this.palette[pixelOffset + 2] / 255f;
+ pixels[offset + 3] = 1;
}
}
diff --git a/src/ImageProcessor/Formats/Png/PngDecoderCore.cs b/src/ImageProcessor/Formats/Png/PngDecoderCore.cs
index 9f837a6bf..1bf8e7740 100644
--- a/src/ImageProcessor/Formats/Png/PngDecoderCore.cs
+++ b/src/ImageProcessor/Formats/Png/PngDecoderCore.cs
@@ -16,9 +16,6 @@ namespace ImageProcessor.Formats
using System.Linq;
using System.Text;
- //using ICSharpCode.SharpZipLib.Checksums;
- //using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
-
///
/// Performs the png decoding operation.
///
@@ -145,7 +142,7 @@ namespace ImageProcessor.Formats
+ $"max allowed size '{ImageBase.MaxWidth}x{ImageBase.MaxHeight}'");
}
- byte[] pixels = new byte[this.header.Width * this.header.Height * 4];
+ float[] pixels = new float[this.header.Width * this.header.Height * 4];
PngColorTypeInformation colorTypeInformation = ColorTypes[this.header.ColorType];
@@ -248,10 +245,10 @@ namespace ImageProcessor.Formats
///
/// The containing data.
///
- /// The containing pixel data.
+ /// The containing pixel data.
/// The color reader.
/// The color type information.
- private void ReadScanlines(MemoryStream dataStream, byte[] pixels, IColorReader colorReader, PngColorTypeInformation colorTypeInformation)
+ private void ReadScanlines(MemoryStream dataStream, float[] pixels, IColorReader colorReader, PngColorTypeInformation colorTypeInformation)
{
dataStream.Position = 0;
diff --git a/src/ImageProcessor/Formats/Png/PngEncoder.cs b/src/ImageProcessor/Formats/Png/PngEncoder.cs
index 14a312220..fd3c531d0 100644
--- a/src/ImageProcessor/Formats/Png/PngEncoder.cs
+++ b/src/ImageProcessor/Formats/Png/PngEncoder.cs
@@ -8,9 +8,6 @@ namespace ImageProcessor.Formats
using System;
using System.IO;
- //using ICSharpCode.SharpZipLib.Checksums;
- //using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
-
///
/// Image encoder for writing image data to a stream in png format.
///
@@ -36,7 +33,7 @@ namespace ImageProcessor.Formats
public int Quality { get; set; }
///
- public string MimeType => "image/jpepngg";
+ public string MimeType => "image/png";
///
public string Extension => "png";
@@ -225,7 +222,7 @@ namespace ImageProcessor.Formats
/// The image base.
private void WriteDataChunksFast(Stream stream, ImageBase imageBase)
{
- byte[] pixels = imageBase.Pixels;
+ float[] pixels = imageBase.Pixels;
// Convert the pixel array to a new array for adding
// the filter byte.
@@ -297,7 +294,7 @@ namespace ImageProcessor.Formats
/// The image base.
private void WriteDataChunks(Stream stream, ImageBase imageBase)
{
- byte[] pixels = imageBase.Pixels;
+ float[] pixels = imageBase.Pixels;
byte[] data = new byte[(imageBase.Width * imageBase.Height * 4) + imageBase.Height];
@@ -321,19 +318,19 @@ namespace ImageProcessor.Formats
// Calculate the offset for the original pixel array.
int pixelOffset = ((y * imageBase.Width) + x) * 4;
- data[dataOffset + 0] = pixels[pixelOffset + 2];
- data[dataOffset + 1] = pixels[pixelOffset + 1];
- data[dataOffset + 2] = pixels[pixelOffset + 0];
- data[dataOffset + 3] = pixels[pixelOffset + 3];
+ data[dataOffset] = (byte)(pixels[pixelOffset].Clamp(0, 1) * 255);
+ data[dataOffset + 1] = (byte)(pixels[pixelOffset + 1].Clamp(0, 1) * 255);
+ data[dataOffset + 2] = (byte)(pixels[pixelOffset + 2].Clamp(0, 1) * 255);
+ data[dataOffset + 3] = (byte)(pixels[pixelOffset + 3].Clamp(0, 1) * 255);
if (y > 0)
{
int lastOffset = (((y - 1) * imageBase.Width) + x) * 4;
- data[dataOffset + 0] -= pixels[lastOffset + 2];
- data[dataOffset + 1] -= pixels[lastOffset + 1];
- data[dataOffset + 2] -= pixels[lastOffset + 0];
- data[dataOffset + 3] -= pixels[lastOffset + 3];
+ data[dataOffset] -= (byte)(pixels[lastOffset].Clamp(0, 1) * 255);
+ data[dataOffset + 1] -= (byte)(pixels[lastOffset + 1].Clamp(0, 1) * 255);
+ data[dataOffset + 2] -= (byte)(pixels[lastOffset + 2].Clamp(0, 1) * 255);
+ data[dataOffset + 3] -= (byte)(pixels[lastOffset + 3].Clamp(0, 1) * 255);
}
}
}
diff --git a/src/ImageProcessor/Formats/Png/TrueColorReader.cs b/src/ImageProcessor/Formats/Png/TrueColorReader.cs
index c60e68306..0ce755a3f 100644
--- a/src/ImageProcessor/Formats/Png/TrueColorReader.cs
+++ b/src/ImageProcessor/Formats/Png/TrueColorReader.cs
@@ -1,13 +1,7 @@
-// --------------------------------------------------------------------------------------------------------------------
-//
-// Copyright (c) James South and contributors.
-// Licensed under the Apache License, Version 2.0.
+//
+// Copyright (c) James South and contributors.
+// Licensed under the Apache License, Version 2.0.
//
-//
-// 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.
-//
-// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Formats
{
@@ -37,14 +31,8 @@ namespace ImageProcessor.Formats
this.useAlpha = useAlpha;
}
- ///
- /// Reads the specified scanline.
- ///
- /// The scanline.
- /// The pixels, where the colors should be stored in BGRA format.
- /// The header, which contains information about the png file, like
- /// the width of the image and the height.
- public void ReadScanline(byte[] scanline, byte[] pixels, PngHeader header)
+ ///
+ public void ReadScanline(byte[] scanline, float[] pixels, PngHeader header)
{
int offset;
@@ -56,10 +44,10 @@ namespace ImageProcessor.Formats
{
offset = ((this.row * header.Width) + (x >> 2)) * 4;
- pixels[offset + 0] = newScanline[x + 2];
- pixels[offset + 1] = newScanline[x + 1];
- pixels[offset + 2] = newScanline[x + 0];
- pixels[offset + 3] = newScanline[x + 3];
+ pixels[offset + 0] = newScanline[x] / 255f;
+ pixels[offset + 1] = newScanline[x + 1] / 255f;
+ pixels[offset + 2] = newScanline[x + 2] / 255f;
+ pixels[offset + 3] = newScanline[x + 3] / 255f;
}
}
else
@@ -67,11 +55,12 @@ namespace ImageProcessor.Formats
for (int x = 0; x < newScanline.Length / 3; x++)
{
offset = ((this.row * header.Width) + x) * 4;
+ int pixelOffset = x * 3;
- pixels[offset + 0] = newScanline[(x * 3) + 2];
- pixels[offset + 1] = newScanline[(x * 3) + 1];
- pixels[offset + 2] = newScanline[(x * 3) + 0];
- pixels[offset + 3] = 255;
+ pixels[offset + 0] = newScanline[pixelOffset] / 255f;
+ pixels[offset + 1] = newScanline[pixelOffset + 1] / 255f;
+ pixels[offset + 2] = newScanline[pixelOffset + 2] / 255f;
+ pixels[offset + 3] = 1;
}
}
diff --git a/src/ImageProcessor/IImageBase.cs b/src/ImageProcessor/IImageBase.cs
index a4ee9e04f..cdbe2104a 100644
--- a/src/ImageProcessor/IImageBase.cs
+++ b/src/ImageProcessor/IImageBase.cs
@@ -20,7 +20,7 @@ namespace ImageProcessor
/// and stores the blue, the green, the red and the alpha value for
/// each pixel in this order.
///
- byte[] Pixels { get; }
+ float[] Pixels { get; }
///
/// Gets the width in pixels.
@@ -66,8 +66,8 @@ namespace ImageProcessor
/// The y-coordinate of the pixel. Must be greater
/// than zero and smaller than the width of the pixel.
///
- /// The at the specified position.
- Bgra32 this[int x, int y] { get; set; }
+ /// The at the specified position.
+ Color this[int x, int y] { get; set; }
///
/// Sets the pixel array of the image.
@@ -85,6 +85,6 @@ namespace ImageProcessor
///
/// Thrown if the length is not equal to Width * Height * 4.
///
- void SetPixels(int width, int height, byte[] pixels);
+ void SetPixels(int width, int height, float[] pixels);
}
}
diff --git a/src/ImageProcessor/ImageBase.cs b/src/ImageProcessor/ImageBase.cs
index f7c410b82..805ee76d0 100644
--- a/src/ImageProcessor/ImageBase.cs
+++ b/src/ImageProcessor/ImageBase.cs
@@ -40,7 +40,7 @@ namespace ImageProcessor
this.Width = width;
this.Height = height;
- this.Pixels = new byte[width * height * 4];
+ this.Pixels = new float[width * height * 4];
}
///
@@ -56,13 +56,13 @@ namespace ImageProcessor
{
Guard.NotNull(other, nameof(other), "Other image cannot be null.");
- byte[] pixels = other.Pixels;
+ float[] pixels = other.Pixels;
this.Width = other.Width;
this.Height = other.Height;
this.Quality = other.Quality;
this.FrameDelay = other.FrameDelay;
- this.Pixels = new byte[pixels.Length];
+ this.Pixels = new float[pixels.Length];
Array.Copy(pixels, this.Pixels, pixels.Length);
}
@@ -84,7 +84,7 @@ namespace ImageProcessor
/// and stores the blue, the green, the red and the alpha value for
/// each pixel in this order.
///
- public byte[] Pixels { get; private set; }
+ public float[] Pixels { get; private set; }
///
/// Gets the width in pixels.
@@ -106,9 +106,7 @@ namespace ImageProcessor
///
public Rectangle Bounds => new Rectangle(0, 0, this.Width, this.Height);
- ///
- /// Gets or sets th quality of the image. This affects the output quality of lossy image formats.
- ///
+ ///
public int Quality { get; set; }
///
@@ -119,19 +117,8 @@ namespace ImageProcessor
///
public int FrameDelay { get; set; }
- ///
- /// Gets or sets the color of a pixel at the specified position.
- ///
- ///
- /// The x-coordinate of the pixel. Must be greater
- /// than zero and smaller than the width of the pixel.
- ///
- ///
- /// The y-coordinate of the pixel. Must be greater
- /// than zero and smaller than the width of the pixel.
- ///
- /// The at the specified position.
- public Bgra32 this[int x, int y]
+ ///
+ public Color this[int x, int y]
{
get
{
@@ -148,7 +135,7 @@ namespace ImageProcessor
#endif
int start = ((y * this.Width) + x) * 4;
- return new Bgra32(this.Pixels[start], this.Pixels[start + 1], this.Pixels[start + 2], this.Pixels[start + 3]);
+ return new Color(this.Pixels[start], this.Pixels[start + 1], this.Pixels[start + 2], this.Pixels[start + 3]);
}
set
@@ -166,30 +153,15 @@ namespace ImageProcessor
#endif
int start = ((y * this.Width) + x) * 4;
- this.Pixels[start + 0] = value.B;
+ this.Pixels[start + 0] = value.R;
this.Pixels[start + 1] = value.G;
- this.Pixels[start + 2] = value.R;
+ this.Pixels[start + 2] = value.B;
this.Pixels[start + 3] = value.A;
}
}
- ///
- /// Sets the pixel array of the image.
- ///
- ///
- /// The new width of the image. Must be greater than zero.
- /// The new height of the image. Must be greater than zero.
- ///
- /// The array with colors. Must be a multiple
- /// of four, width and height.
- ///
- ///
- /// Thrown if either or are less than or equal to 0.
- ///
- ///
- /// Thrown if the length is not equal to Width * Height * 4.
- ///
- public void SetPixels(int width, int height, byte[] pixels)
+ ///
+ public void SetPixels(int width, int height, float[] pixels)
{
if (width <= 0)
{
diff --git a/src/ImageProcessor/ParallelImageProcessor.cs b/src/ImageProcessor/ParallelImageProcessor.cs
index d84b3cdaf..843f40b9e 100644
--- a/src/ImageProcessor/ParallelImageProcessor.cs
+++ b/src/ImageProcessor/ParallelImageProcessor.cs
@@ -53,7 +53,7 @@ namespace ImageProcessor
///
public void Apply(ImageBase target, ImageBase source, int width, int height, Rectangle targetRectangle = default(Rectangle), Rectangle sourceRectangle = default(Rectangle))
{
- byte[] pixels = new byte[width * height * 4];
+ float[] pixels = new float[width * height * 4];
target.SetPixels(width, height, pixels);
if (targetRectangle == Rectangle.Empty)
diff --git a/tests/ImageProcessor.Tests/Processors/ProcessorTestBase.cs b/tests/ImageProcessor.Tests/Processors/ProcessorTestBase.cs
index 15c073b19..d7e0c58db 100644
--- a/tests/ImageProcessor.Tests/Processors/ProcessorTestBase.cs
+++ b/tests/ImageProcessor.Tests/Processors/ProcessorTestBase.cs
@@ -19,16 +19,17 @@ namespace ImageProcessor.Tests
///
public static readonly List Files = new List
{
- //"../../TestImages/Formats/Jpg/Backdrop.jpg",
- //"../../TestImages/Formats/Jpg/Calliphora.jpg",
- //"../../TestImages/Formats/Jpg/gamma_dalai_lama_gray.jpg",
- //"../../TestImages/Formats/Jpg/greyscale.jpg",
- //"../../TestImages/Formats/Bmp/Car.bmp",
- //"../../TestImages/Formats/Png/cmyk.png",
- //"../../TestImages/Formats/Png/gamma-1.0-or-2.2.png",
- //"../../TestImages/Formats/Gif/leaf.gif",
- //"../../TestImages/Formats/Gif/rings.gif",
- //"../../TestImages/Formats/Gif/ani2.gif" ,
+ "../../TestImages/Formats/Jpg/Backdrop.jpg",
+ "../../TestImages/Formats/Jpg/Calliphora.jpg",
+ "../../TestImages/Formats/Jpg/gamma_dalai_lama_gray.jpg",
+ "../../TestImages/Formats/Jpg/greyscale.jpg",
+ "../../TestImages/Formats/Bmp/Car.bmp",
+ "../../TestImages/Formats/Png/cmyk.png",
+ "../../TestImages/Formats/Png/gamma-1.0-or-2.2.png",
+ "../../TestImages/Formats/Png/splash.png",
+ "../../TestImages/Formats/Gif/leaf.gif",
+ "../../TestImages/Formats/Gif/rings.gif",
+ "../../TestImages/Formats/Gif/ani2.gif" ,
"../../TestImages/Formats/Gif/giphy.gif"
};
}
diff --git a/tests/ImageProcessor.Tests/TestImages/Formats/Png/splash.png.REMOVED.git-id b/tests/ImageProcessor.Tests/TestImages/Formats/Png/splash.png.REMOVED.git-id
new file mode 100644
index 000000000..73f27bfe6
--- /dev/null
+++ b/tests/ImageProcessor.Tests/TestImages/Formats/Png/splash.png.REMOVED.git-id
@@ -0,0 +1 @@
+e37d569208ff9490b77b4131330feb323e367fd3
\ No newline at end of file