From d481dcc201c3547d3f2b01bdccfdac9f5f3763a0 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Sun, 6 Dec 2015 18:30:22 +1100 Subject: [PATCH] Fix format conversion output. Former-commit-id: 2936205e13fa5329caf84d98691898c1f312cd02 Former-commit-id: dbfc0b5e29033f3357511c71c298940ff0ff9f5d Former-commit-id: e996c20ff4b2cc6a2a76953b532dd7560f0cf735 --- src/ImageProcessor/Colors/Color.cs | 4 +- src/ImageProcessor/Colors/Formats/Bgra32.cs | 2 +- src/ImageProcessor/Formats/Bmp/BmpEncoder.cs | 3 +- src/ImageProcessor/Formats/Gif/GifEncoder.cs | 11 +++--- .../Formats/Gif/Quantizer/QuantizedImage.cs | 6 +-- .../Formats/Gif/Quantizer/Quantizer.cs | 2 - src/ImageProcessor/Formats/Jpg/JpegEncoder.cs | 3 +- src/ImageProcessor/Formats/Png/PngEncoder.cs | 5 +-- .../Processors/Formats/EncoderDecoderTests.cs | 37 +++++++++++++++++++ 9 files changed, 53 insertions(+), 20 deletions(-) diff --git a/src/ImageProcessor/Colors/Color.cs b/src/ImageProcessor/Colors/Color.cs index d6a169af5..ced40890e 100644 --- a/src/ImageProcessor/Colors/Color.cs +++ b/src/ImageProcessor/Colors/Color.cs @@ -238,7 +238,7 @@ namespace ImageProcessor /// public static implicit operator Color(Bgra32 color) { - return Color.FromNonPremultiplied(new Color(color.R / 255f, color.G / 255f, color.B / 255f, color.A / 255f)); + return new Color(color.R / 255f, color.G / 255f, color.B / 255f, color.A / 255f); } /// @@ -473,7 +473,7 @@ namespace ImageProcessor public static Color Lerp(Color from, Color to, float amount) { amount = amount.Clamp(0f, 1f); - + // Premultiplied. return (from * (1 - amount)) + to; } diff --git a/src/ImageProcessor/Colors/Formats/Bgra32.cs b/src/ImageProcessor/Colors/Formats/Bgra32.cs index 98b78bc8a..f76753a79 100644 --- a/src/ImageProcessor/Colors/Formats/Bgra32.cs +++ b/src/ImageProcessor/Colors/Formats/Bgra32.cs @@ -94,7 +94,7 @@ namespace ImageProcessor /// public static implicit operator Bgra32(Color color) { - color = Color.ToNonPremultiplied(color.Limited); + color = color.Limited; return new Bgra32((255f * color.B).ToByte(), (255f * color.G).ToByte(), (255f * color.R).ToByte(), (255f * color.A).ToByte()); } diff --git a/src/ImageProcessor/Formats/Bmp/BmpEncoder.cs b/src/ImageProcessor/Formats/Bmp/BmpEncoder.cs index d227ec1d1..04bf02dd0 100644 --- a/src/ImageProcessor/Formats/Bmp/BmpEncoder.cs +++ b/src/ImageProcessor/Formats/Bmp/BmpEncoder.cs @@ -130,8 +130,7 @@ namespace ImageProcessor.Formats float b = data[offset + 2]; float a = data[offset + 3]; - // Implicit cast to Bgra32 handles premultiplication conversion. - Bgra32 color = new Color(r, g, b, a); + Bgra32 color = Color.ToNonPremultiplied(new Color(r, g, b, a)); if (color.A < this.Threshold) { diff --git a/src/ImageProcessor/Formats/Gif/GifEncoder.cs b/src/ImageProcessor/Formats/Gif/GifEncoder.cs index d50182448..a0f344b01 100644 --- a/src/ImageProcessor/Formats/Gif/GifEncoder.cs +++ b/src/ImageProcessor/Formats/Gif/GifEncoder.cs @@ -30,7 +30,7 @@ namespace ImageProcessor.Formats /// public string MimeType => "image/gif"; - + /// /// Gets or sets the transparency threshold. /// @@ -137,7 +137,7 @@ namespace ImageProcessor.Formats private QuantizedImage WriteColorTable(ImageBase image, Stream stream, int quality, int bitDepth) { // Quantize the image returning a pallete. - IQuantizer quantizer = new OctreeQuantizer(quality.Clamp(1, 255), bitDepth) {Threshold = this.threshold}; + IQuantizer quantizer = new OctreeQuantizer(quality.Clamp(1, 255), bitDepth) { Threshold = this.threshold }; QuantizedImage quantizedImage = quantizer.Quantize(image); // Grab the pallete and write it to the stream. @@ -151,10 +151,11 @@ namespace ImageProcessor.Formats for (int i = 0; i < pixelCount; i++) { int offset = i * 3; - Bgra32 color = pallete[i]; - colorTable[offset + 2] = color.B; + Bgra32 color = Color.ToNonPremultiplied(pallete[i]); + + colorTable[offset] = color.R; colorTable[offset + 1] = color.G; - colorTable[offset + 0] = color.R; + colorTable[offset + 2] = color.B; } stream.Write(colorTable, 0, colorTableLength); diff --git a/src/ImageProcessor/Formats/Gif/Quantizer/QuantizedImage.cs b/src/ImageProcessor/Formats/Gif/Quantizer/QuantizedImage.cs index 6b840fc70..846073e63 100644 --- a/src/ImageProcessor/Formats/Gif/Quantizer/QuantizedImage.cs +++ b/src/ImageProcessor/Formats/Gif/Quantizer/QuantizedImage.cs @@ -75,10 +75,10 @@ namespace ImageProcessor.Formats for (int i = 0; i < pixelCount; i++) { int offset = i * 4; - Bgra32 color = this.Palette[Math.Min(palletCount, this.Pixels[i])]; - bgraPixels[offset + 0] = color.B; + Color color = this.Palette[Math.Min(palletCount, this.Pixels[i])]; + bgraPixels[offset] = color.R; bgraPixels[offset + 1] = color.G; - bgraPixels[offset + 2] = color.R; + bgraPixels[offset + 2] = color.B; bgraPixels[offset + 3] = color.A; } diff --git a/src/ImageProcessor/Formats/Gif/Quantizer/Quantizer.cs b/src/ImageProcessor/Formats/Gif/Quantizer/Quantizer.cs index 136f13037..8312e5480 100644 --- a/src/ImageProcessor/Formats/Gif/Quantizer/Quantizer.cs +++ b/src/ImageProcessor/Formats/Gif/Quantizer/Quantizer.cs @@ -79,7 +79,6 @@ namespace ImageProcessor.Formats for (int x = 0; x < width; x++) { // Now I have the pixel, call the FirstPassQuantize function... - // Implicit cast to Bgra32 handles premultiplication conversion. this.InitialQuantizePixel(source[x, y]); } } @@ -107,7 +106,6 @@ namespace ImageProcessor.Formats { for (int x = 0; x < width; x++) { - // Implicit cast to Bgra32 handles premultiplication conversion. 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/JpegEncoder.cs b/src/ImageProcessor/Formats/Jpg/JpegEncoder.cs index 30fd6574c..d794c9d6e 100644 --- a/src/ImageProcessor/Formats/Jpg/JpegEncoder.cs +++ b/src/ImageProcessor/Formats/Jpg/JpegEncoder.cs @@ -125,8 +125,7 @@ namespace ImageProcessor.Formats float b = sourcePixels[source + 2]; float a = sourcePixels[source + 3]; - // Implicit cast to Bgra32 handles premultiplication conversion. - Bgra32 color = new Color(r, g, b, a); + Bgra32 color = Color.ToNonPremultiplied(new Color(r, g, b, a)); if (color.A < this.Threshold) { diff --git a/src/ImageProcessor/Formats/Png/PngEncoder.cs b/src/ImageProcessor/Formats/Png/PngEncoder.cs index 0b9edb44e..64e3ff7c9 100644 --- a/src/ImageProcessor/Formats/Png/PngEncoder.cs +++ b/src/ImageProcessor/Formats/Png/PngEncoder.cs @@ -340,8 +340,7 @@ namespace ImageProcessor.Formats float b = pixels[pixelOffset + 2]; float a = pixels[pixelOffset + 3]; - // Implicit cast to Bgra32 handles premultiplication conversion. - Bgra32 color = new Color(r, g, b, a); + Bgra32 color = Color.ToNonPremultiplied(new Color(r, g, b, a)); if (color.A < this.Threshold) { @@ -362,7 +361,7 @@ namespace ImageProcessor.Formats b = pixels[lastOffset + 2]; a = pixels[lastOffset + 3]; - color = new Color(r, g, b, a); + color = Color.ToNonPremultiplied(new Color(r, g, b, a)); data[dataOffset] -= color.R; data[dataOffset + 1] -= color.G; diff --git a/tests/ImageProcessor.Tests/Processors/Formats/EncoderDecoderTests.cs b/tests/ImageProcessor.Tests/Processors/Formats/EncoderDecoderTests.cs index 5220a03b1..baf56ed3b 100644 --- a/tests/ImageProcessor.Tests/Processors/Formats/EncoderDecoderTests.cs +++ b/tests/ImageProcessor.Tests/Processors/Formats/EncoderDecoderTests.cs @@ -64,5 +64,42 @@ } } } + + [Fact] + public void ImageCanConvertFormat() + { + if (!Directory.Exists("TestOutput/Format")) + { + Directory.CreateDirectory("TestOutput/Format"); + } + + foreach (string file in Files) + { + using (FileStream stream = File.OpenRead(file)) + { + Image image = new Image(stream); + + using (FileStream output = File.OpenWrite($"TestOutput/Format/{Path.GetFileNameWithoutExtension(file)}.gif")) + { + image.SaveAsGif(output); + } + + using (FileStream output = File.OpenWrite($"TestOutput/Format/{Path.GetFileNameWithoutExtension(file)}.bmp")) + { + image.SaveAsBmp(output); + } + + using (FileStream output = File.OpenWrite($"TestOutput/Format/{Path.GetFileNameWithoutExtension(file)}.jpg")) + { + image.SaveAsJpeg(output); + } + + using (FileStream output = File.OpenWrite($"TestOutput/Format/{Path.GetFileNameWithoutExtension(file)}.png")) + { + image.SaveAsPng(output); + } + } + } + } } } \ No newline at end of file