diff --git a/src/ImageProcessor/Colors/Color.cs b/src/ImageProcessor/Colors/Color.cs
index 3d04a0a41..44ed036e3 100644
--- a/src/ImageProcessor/Colors/Color.cs
+++ b/src/ImageProcessor/Colors/Color.cs
@@ -11,7 +11,7 @@ namespace ImageProcessor
///
/// Represents a four-component color using red, green, blue, and alpha data.
- /// Each component is stored in a linear premultiplied format multiplied by the alpha component.
+ /// Each component is stored in premultiplied format multiplied by the alpha component.
///
///
/// This struct is fully mutable. This is done (against the guidelines) for the sake of performance,
diff --git a/src/ImageProcessor/Colors/ColorDefinitions.cs b/src/ImageProcessor/Colors/ColorDefinitions.cs
index 78ea3fbca..061b509de 100644
--- a/src/ImageProcessor/Colors/ColorDefinitions.cs
+++ b/src/ImageProcessor/Colors/ColorDefinitions.cs
@@ -7,7 +7,7 @@ namespace ImageProcessor
{
///
/// Represents a four-component color using red, green, blue, and alpha data.
- /// Each component is stored in a linear premultiplied format multiplied by the alpha component.
+ /// Each component is stored in premultiplied format multiplied by the alpha component.
///
///
/// This struct is fully mutable. This is done (against the guidelines) for the sake of performance,
diff --git a/src/ImageProcessor/Colors/ColorTransforms.cs b/src/ImageProcessor/Colors/ColorTransforms.cs
index 9551222fb..43bc03251 100644
--- a/src/ImageProcessor/Colors/ColorTransforms.cs
+++ b/src/ImageProcessor/Colors/ColorTransforms.cs
@@ -9,7 +9,7 @@ namespace ImageProcessor
///
/// Represents a four-component color using red, green, blue, and alpha data.
- /// Each component is stored in a linear premultiplied format multiplied by the alpha component.
+ /// Each component is stored in premultiplied format multiplied by the alpha component.
///
///
/// This struct is fully mutable. This is done (against the guidelines) for the sake of performance,
diff --git a/src/ImageProcessor/Colors/ColorspaceTransforms.cs b/src/ImageProcessor/Colors/ColorspaceTransforms.cs
index ea08973fe..334c967fb 100644
--- a/src/ImageProcessor/Colors/ColorspaceTransforms.cs
+++ b/src/ImageProcessor/Colors/ColorspaceTransforms.cs
@@ -9,7 +9,7 @@ namespace ImageProcessor
///
/// Represents a four-component color using red, green, blue, and alpha data.
- /// Each component is stored in a linear premultiplied format multiplied by the alpha component.
+ /// Each component is stored in premultiplied format multiplied by the alpha component.
///
///
/// This struct is fully mutable. This is done (against the guidelines) for the sake of performance,
@@ -86,7 +86,7 @@ namespace ImageProcessor
float g = (x * -0.9689F) + (y * 1.8758F) + (z * 0.0415F);
float b = (x * 0.0557F) + (y * -0.2040F) + (z * 1.0570F);
- return new Color(r, g, b);
+ return Color.Compress(new Color(r, g, b));
}
///
@@ -226,7 +226,7 @@ namespace ImageProcessor
float g = (x * -0.9689F) + (y * 1.8758F) + (z * 0.0415F);
float b = (x * 0.0557F) + (y * -0.2040F) + (z * 1.0570F);
- return new Color(r, g, b);
+ return Color.Compress(new Color(r, g, b));
}
///
diff --git a/src/ImageProcessor/Colors/Colorspaces/CieLab.cs b/src/ImageProcessor/Colors/Colorspaces/CieLab.cs
index c1b64134d..d5875da07 100644
--- a/src/ImageProcessor/Colors/Colorspaces/CieLab.cs
+++ b/src/ImageProcessor/Colors/Colorspaces/CieLab.cs
@@ -79,6 +79,8 @@ namespace ImageProcessor
public static implicit operator CieLab(Color color)
{
// First convert to CIE XYZ
+ color = Color.Expand(color);
+
float x = (color.R * 0.4124F) + (color.G * 0.3576F) + (color.B * 0.1805F);
float y = (color.R * 0.2126F) + (color.G * 0.7152F) + (color.B * 0.0722F);
float z = (color.R * 0.0193F) + (color.G * 0.1192F) + (color.B * 0.9505F);
diff --git a/src/ImageProcessor/Colors/Colorspaces/CieXyz.cs b/src/ImageProcessor/Colors/Colorspaces/CieXyz.cs
index 8c609dc0d..ab63c868d 100644
--- a/src/ImageProcessor/Colors/Colorspaces/CieXyz.cs
+++ b/src/ImageProcessor/Colors/Colorspaces/CieXyz.cs
@@ -79,6 +79,8 @@ namespace ImageProcessor
///
public static implicit operator CieXyz(Color color)
{
+ color = Color.Expand(color);
+
float x = (color.R * 0.4124F) + (color.G * 0.3576F) + (color.B * 0.1805F);
float y = (color.R * 0.2126F) + (color.G * 0.7152F) + (color.B * 0.0722F);
float z = (color.R * 0.0193F) + (color.G * 0.1192F) + (color.B * 0.9505F);
diff --git a/src/ImageProcessor/Filters/Brightness.cs b/src/ImageProcessor/Filters/Brightness.cs
index 08165037c..6a5ae3985 100644
--- a/src/ImageProcessor/Filters/Brightness.cs
+++ b/src/ImageProcessor/Filters/Brightness.cs
@@ -50,12 +50,12 @@ namespace ImageProcessor.Filters
{
for (int x = startX; x < endX; x++)
{
- Color color = source[x, y];
+ Color color = Color.Expand(source[x, y]);
Vector3 vector3 = color.ToVector3();
vector3 += new Vector3(brightness);
- target[x, y] = new Color(vector3, color.A);
+ target[x, y] = Color.Compress(new Color(vector3, color.A));
}
}
});
diff --git a/src/ImageProcessor/Filters/ColorMatrix/ColorMatrixFilter.cs b/src/ImageProcessor/Filters/ColorMatrix/ColorMatrixFilter.cs
index 396d5cda1..d63732751 100644
--- a/src/ImageProcessor/Filters/ColorMatrix/ColorMatrixFilter.cs
+++ b/src/ImageProcessor/Filters/ColorMatrix/ColorMatrixFilter.cs
@@ -17,7 +17,7 @@ namespace ImageProcessor.Filters
public abstract Matrix4x4 Matrix { get; }
///
- public virtual bool Compand => false;
+ public virtual bool Compand => true;
///
protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
@@ -57,11 +57,11 @@ namespace ImageProcessor.Filters
if (compand)
{
- color = Color.Compress(color);
+ color = Color.Expand(color);
}
Vector3 transformed = Vector3.Transform(color.ToVector3(), matrix);
- return compand ? Color.Expand(new Color(transformed, color.A)) : new Color(transformed, color.A);
+ return compand ? Color.Compress(new Color(transformed, color.A)) : new Color(transformed, color.A);
}
}
}
diff --git a/src/ImageProcessor/Filters/ColorMatrix/Hue.cs b/src/ImageProcessor/Filters/ColorMatrix/Hue.cs
index 9acf9e3bb..a77f6ff09 100644
--- a/src/ImageProcessor/Filters/ColorMatrix/Hue.cs
+++ b/src/ImageProcessor/Filters/ColorMatrix/Hue.cs
@@ -37,7 +37,7 @@
public override Matrix4x4 Matrix => this.matrix;
///
- public override bool Compand => true;
+ public override bool Compand => false;
///
protected override void OnApply(ImageBase source, ImageBase target, Rectangle targetRectangle, Rectangle sourceRectangle)
diff --git a/src/ImageProcessor/Filters/ColorMatrix/Sepia.cs b/src/ImageProcessor/Filters/ColorMatrix/Sepia.cs
index db5020271..cab932b25 100644
--- a/src/ImageProcessor/Filters/ColorMatrix/Sepia.cs
+++ b/src/ImageProcessor/Filters/ColorMatrix/Sepia.cs
@@ -28,6 +28,6 @@ namespace ImageProcessor.Filters
};
///
- public override bool Compand => true;
+ public override bool Compand => false;
}
}
diff --git a/src/ImageProcessor/Filters/Contrast.cs b/src/ImageProcessor/Filters/Contrast.cs
index 97216f4cc..da55507ff 100644
--- a/src/ImageProcessor/Filters/Contrast.cs
+++ b/src/ImageProcessor/Filters/Contrast.cs
@@ -51,11 +51,11 @@ namespace ImageProcessor.Filters
{
for (int x = startX; x < endX; x++)
{
- Vector4 color = source[x, y].ToVector4();
+ Vector4 color = Color.Expand(source[x, y]).ToVector4();
color -= shiftVector;
color *= contrastVector;
color += shiftVector;
- target[x, y] = new Color(color);
+ target[x, y] = Color.Compress(new Color(color));
}
}
});
diff --git a/src/ImageProcessor/Formats/Bmp/BmpDecoderCore.cs b/src/ImageProcessor/Formats/Bmp/BmpDecoderCore.cs
index e058d48f0..c11f2d7c7 100644
--- a/src/ImageProcessor/Formats/Bmp/BmpDecoderCore.cs
+++ b/src/ImageProcessor/Formats/Bmp/BmpDecoderCore.cs
@@ -7,7 +7,6 @@ namespace ImageProcessor.Formats
{
using System;
using System.IO;
- using System.Numerics;
using System.Threading.Tasks;
///
@@ -224,17 +223,11 @@ namespace ImageProcessor.Formats
int arrayOffset = ((row * width) + (colOffset + shift)) * 4;
// We divide by 255 as we will store the colors in our floating point format.
- // Default colorspace is sRGB TODO: Check if we can detect this.
// Stored in r-> g-> b-> a order.
- // Expand from sRGB to linear RGB
- Color color =
- Color.Expand(
- new Color(new Vector3(colors[colorIndex + 2], colors[colorIndex + 1], colors[colorIndex]) / 255f));
-
- imageData[arrayOffset] = color.R; // r
- imageData[arrayOffset + 1] = color.G; // g
- imageData[arrayOffset + 2] = color.B; // b
- imageData[arrayOffset + 3] = color.A; // a
+ 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
}
}
});
@@ -277,14 +270,11 @@ namespace ImageProcessor.Formats
int arrayOffset = ((row * width) + x) * 4;
- // Expand from sRGB to linear RGB
- Color color = Color.Expand(new Color(r, g, b, 1));
-
// Stored in r-> g-> b-> a order.
- imageData[arrayOffset] = color.R;
- imageData[arrayOffset + 1] = color.G;
- imageData[arrayOffset + 2] = color.B;
- imageData[arrayOffset + 3] = color.A;
+ imageData[arrayOffset] = r;
+ imageData[arrayOffset + 1] = g;
+ imageData[arrayOffset + 2] = b;
+ imageData[arrayOffset + 3] = 1;
}
});
}
@@ -315,15 +305,12 @@ namespace ImageProcessor.Formats
int offset = rowOffset + (x * 3);
int arrayOffset = ((row * width) + x) * 4;
- // Expand from sRGB to linear RGB
- Color color = Color.Expand(new Color(new Vector3(data[offset + 2], data[offset + 1], data[offset]) / 255f, 1));
-
// We divide by 255 as we will store the colors in our floating point format.
// Stored in r-> g-> b-> a order.
- imageData[arrayOffset] = color.R;
- imageData[arrayOffset + 1] = color.G;
- imageData[arrayOffset + 2] = color.B;
- imageData[arrayOffset + 3] = color.A;
+ imageData[arrayOffset] = data[offset + 2] / 255f;
+ imageData[arrayOffset + 1] = data[offset + 1] / 255f;
+ imageData[arrayOffset + 2] = data[offset] / 255f;
+ imageData[arrayOffset + 3] = 1;
}
});
}
@@ -356,15 +343,10 @@ namespace ImageProcessor.Formats
// We divide by 255 as we will store the colors in our floating point format.
// Stored in r-> g-> b-> a order.
-
- // Expand from sRGB to linear RGB
- // TODO: Can we use our real alpha here?
- Color color = Color.Expand(new Color(new Vector3(data[offset + 2], data[offset + 1], data[offset]) / 255f, 1));
-
- imageData[arrayOffset] = color.R;
- imageData[arrayOffset + 1] = color.G;
- imageData[arrayOffset + 2] = color.B;
- imageData[arrayOffset + 3] = color.A;
+ 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 cd955612c..ad80bbc76 100644
--- a/src/ImageProcessor/Formats/Bmp/BmpEncoder.cs
+++ b/src/ImageProcessor/Formats/Bmp/BmpEncoder.cs
@@ -110,13 +110,13 @@ namespace ImageProcessor.Formats
// Limit the output range and multiply out from our floating point.
// Convert back to b-> g-> r-> a order.
- // Convert to non-premultiplied sRGB color.
+ // Convert to non-premultiplied color.
float r = data[offset];
float g = data[offset + 1];
float b = data[offset + 2];
float a = data[offset + 3];
- Bgra32 color = Color.ToNonPremultiplied(Color.Compress(new Color(r, g, b, a)));
+ Bgra32 color = Color.ToNonPremultiplied(new Color(r, g, b, a));
writer.Write(color.B);
writer.Write(color.G);
diff --git a/src/ImageProcessor/Formats/Jpg/JpegDecoder.cs b/src/ImageProcessor/Formats/Jpg/JpegDecoder.cs
index 6ffcafe06..2f456dfc0 100644
--- a/src/ImageProcessor/Formats/Jpg/JpegDecoder.cs
+++ b/src/ImageProcessor/Formats/Jpg/JpegDecoder.cs
@@ -7,7 +7,6 @@ namespace ImageProcessor.Formats
{
using System;
using System.IO;
- using System.Numerics;
using System.Threading.Tasks;
using BitMiracle.LibJpeg;
@@ -118,14 +117,10 @@ namespace ImageProcessor.Formats
int offset = ((y * pixelWidth) + x) * 4;
- // Expand from sRGB to linear RGB
- Color color =
- Color.Expand(new Color(new Vector3(sample[0], sample[1], sample[2]) / 255f));
-
- pixels[offset + 0] = color.R;
- pixels[offset + 1] = color.G;
- pixels[offset + 2] = color.B;
- pixels[offset + 3] = color.A;
+ pixels[offset + 0] = sample[0] / 255f;
+ pixels[offset + 1] = sample[1] / 255f;
+ pixels[offset + 2] = sample[2] / 255f;
+ pixels[offset + 3] = 1;
}
});
}
@@ -144,14 +139,10 @@ namespace ImageProcessor.Formats
int offset = ((y * pixelWidth) + x) * 4;
- // Expand from sRGB to linear RGB
- Color color =
- Color.Expand(new Color(new Vector3(sample[0], sample[0], sample[0]) / 255f));
-
- pixels[offset + 0] = color.R;
- pixels[offset + 1] = color.G;
- pixels[offset + 2] = color.B;
- pixels[offset + 3] = color.A;
+ pixels[offset + 0] = sample[0] / 255f;
+ pixels[offset + 1] = sample[0] / 255f;
+ pixels[offset + 2] = sample[0] / 255f;
+ pixels[offset + 3] = 1;
}
});
}
diff --git a/src/ImageProcessor/Formats/Jpg/JpegEncoder.cs b/src/ImageProcessor/Formats/Jpg/JpegEncoder.cs
index 9958d6e63..0517b422c 100644
--- a/src/ImageProcessor/Formats/Jpg/JpegEncoder.cs
+++ b/src/ImageProcessor/Formats/Jpg/JpegEncoder.cs
@@ -111,8 +111,7 @@ namespace ImageProcessor.Formats
float b = sourcePixels[source + 2];
float a = sourcePixels[source + 3];
- // Compress back to sRGB
- Bgra32 color = Color.ToNonPremultiplied(Color.Compress(new Color(r, g, b, a)));
+ Bgra32 color = Color.ToNonPremultiplied(new Color(r, g, b, a));
samples[start] = color.R;
samples[start + 1] = color.G;
diff --git a/src/ImageProcessor/Samplers/Resampler.cs b/src/ImageProcessor/Samplers/Resampler.cs
index 22bc7b57c..4fd105f16 100644
--- a/src/ImageProcessor/Samplers/Resampler.cs
+++ b/src/ImageProcessor/Samplers/Resampler.cs
@@ -193,11 +193,12 @@ namespace ImageProcessor.Samplers
foreach (Weight xw in horizontalValues)
{
int originX = xw.Index;
- Color sourceColor = source[originX, originY];
+ Color sourceColor = Color.Expand(source[originX, originY]);
destination += sourceColor * yw.Value * xw.Value;
}
}
+ destination = Color.Compress(destination);
target[x, y] = destination;
}
}
@@ -301,12 +302,13 @@ namespace ImageProcessor.Samplers
if (sourceRectangle.Contains(rotated.X, rotated.Y))
{
- Color sourceColor = source[rotated.X, rotated.Y];
+ Color sourceColor = Color.Expand(source[rotated.X, rotated.Y]);
destination += sourceColor * yw.Value * xw.Value;
}
}
}
+ destination = Color.Compress(destination);
target[x, y] = destination;
}
}