Browse Source

Remove bytes functions

Former-commit-id: 153a5f985339b738d1cf15e10a3d42a6613ef729
Former-commit-id: ece59225c4bd1e6afad22fcf7a18d5cb60189228
Former-commit-id: 9d9fe57bb80e756284f496373c630b9ea09f3058
af/merge-core
James Jackson-South 10 years ago
parent
commit
ff720da2bb
  1. 41
      src/ImageProcessorCore/Colors/Color.cs
  2. 46
      src/ImageProcessorCore/Colors/PackedVector/IPackedVector.cs
  3. 8
      src/ImageProcessorCore/Common/Helpers/ImageMaths.cs
  4. 2
      src/ImageProcessorCore/Filters/DetectEdges.cs
  5. 2
      src/ImageProcessorCore/Filters/Processors/ColorMatrix/LomographProcessor.cs
  6. 4
      src/ImageProcessorCore/Filters/Processors/ColorMatrix/PolaroidProcessor.cs
  7. 9
      src/ImageProcessorCore/Formats/Bmp/BmpDecoderCore.cs
  8. 10
      src/ImageProcessorCore/Formats/Bmp/BmpEncoderCore.cs
  9. 3
      src/ImageProcessorCore/Formats/Gif/GifDecoderCore.cs
  10. 8
      src/ImageProcessorCore/Formats/Gif/GifEncoderCore.cs
  11. 2
      src/ImageProcessorCore/Formats/Jpg/JpegDecoderCore.cs.REMOVED.git-id
  12. 8
      src/ImageProcessorCore/Formats/Jpg/JpegEncoderCore.cs
  13. 14
      src/ImageProcessorCore/Formats/Png/PngDecoderCore.cs
  14. 20
      src/ImageProcessorCore/Formats/Png/PngEncoderCore.cs
  15. 36
      src/ImageProcessorCore/Quantizers/Octree/OctreeQuantizer.cs
  16. 20
      src/ImageProcessorCore/Quantizers/Palette/PaletteQuantizer.cs
  17. 26
      src/ImageProcessorCore/Quantizers/Wu/WuQuantizer.cs

41
src/ImageProcessorCore/Colors/Color.cs

@ -160,7 +160,7 @@ namespace ImageProcessorCore
public Color(float r, float g, float b, float a = 1) public Color(float r, float g, float b, float a = 1)
: this() : this()
{ {
Pack(ref r, ref g, ref b, ref a); this.packedValue = Pack(r, g, b, a);
} }
/// <summary> /// <summary>
@ -172,8 +172,7 @@ namespace ImageProcessorCore
public Color(Vector3 vector) public Color(Vector3 vector)
: this() : this()
{ {
float a = 1; this.packedValue = Pack(ref vector);
Pack(ref vector.X, ref vector.Y, ref vector.Z, ref a);
} }
/// <summary> /// <summary>
@ -282,25 +281,39 @@ namespace ImageProcessorCore
} }
/// <summary> /// <summary>
/// Packs a vector into a uint. /// Packs a <see cref="Vector4"/> into a uint.
/// </summary> /// </summary>
/// <param name="vector">The vector containing the values to pack.</param> /// <param name="vector">The vector containing the values to pack.</param>
/// <returns>The ulong containing the packed values.</returns> /// <returns>The ulong containing the packed values.</returns>
private static uint Pack(ref Vector4 vector) private static uint Pack(ref Vector4 vector)
{ {
// TODO: Maybe use Vector4.Clamp() instead. return Pack(vector.X, vector.Y, vector.Z, vector.W);
return (uint)((byte)Math.Round(vector.X * Max).Clamp(Min, Max) }
| ((byte)Math.Round(vector.Y * Max).Clamp(Min, Max) << 8)
| (byte)Math.Round(vector.Z * Max).Clamp(Min, Max) << 16 /// <summary>
| (byte)Math.Round(vector.W * Max).Clamp(Min, Max) << 24); /// Packs a <see cref="Vector3"/> into a uint.
/// </summary>
/// <param name="vector">The vector containing the values to pack.</param>
/// <returns>The ulong containing the packed values.</returns>
private static uint Pack(ref Vector3 vector)
{
return Pack(vector.X, vector.Y, vector.Z, 1);
} }
private static uint Pack(ref float x, ref float y, ref float z, ref float w) /// <summary>
/// Packs the four floats into a uint.
/// </summary>
/// <param name="x">The x-component</param>
/// <param name="y">The y-component</param>
/// <param name="z">The z-component</param>
/// <param name="w">The w-component</param>
/// <returns>The <see cref="uint"/></returns>
private static uint Pack(float x, float y, float z, float w)
{ {
return (uint)((byte)Math.Round(x * Max).Clamp(Min, Max) return (uint)((byte)Math.Round(x.Clamp(0, 1) * Max)
| ((byte)Math.Round(y * Max).Clamp(Min, Max) << 8) | ((byte)Math.Round(y.Clamp(0, 1) * Max) << 8)
| (byte)Math.Round(z * Max).Clamp(Min, Max) << 16 | (byte)Math.Round(z.Clamp(0, 1) * Max) << 16
| (byte)Math.Round(w * Max).Clamp(Min, Max) << 24); | (byte)Math.Round(w.Clamp(0, 1) * Max) << 24);
} }
/// <summary> /// <summary>

46
src/ImageProcessorCore/Colors/PackedVector/IPackedVector.cs

@ -16,22 +16,6 @@ namespace ImageProcessorCore
where TPacked : struct where TPacked : struct
{ {
TPacked PackedValue { get; set; } TPacked PackedValue { get; set; }
///// <summary>
///// Directly gets the packed representation of the packed vector.
///// Typically packed in least to greatest significance order.
///// </summary>
///// <returns>
///// The <see cref="TPacked"/>.
///// </returns>
//TPacked GetPackedValue();
///// <summary>
///// Directly sets the packed representation of the packed vector.
///// Typically packed in least to greatest significance order.
///// </summary>
///// <param name="value">The packed value.</param>
//void SetPackedValue(TPacked value);
} }
/// <summary> /// <summary>
@ -45,14 +29,14 @@ namespace ImageProcessorCore
/// <param name="vector">The vector to create the packed representation from.</param> /// <param name="vector">The vector to create the packed representation from.</param>
void PackFromVector4(Vector4 vector); void PackFromVector4(Vector4 vector);
/// <summary> ///// <summary>
/// Sets the packed representation from a <see cref="T:byte[]"/>. ///// Sets the packed representation from a <see cref="T:byte[]"/>.
/// </summary> ///// </summary>
/// <param name="x">The x-component to create the packed representation from.</param> ///// <param name="x">The x-component to create the packed representation from.</param>
/// <param name="y">The y-component to create the packed representation from.</param> ///// <param name="y">The y-component to create the packed representation from.</param>
/// <param name="z">The z-component to create the packed representation from.</param> ///// <param name="z">The z-component to create the packed representation from.</param>
/// <param name="w">The w-component to create the packed representation from.</param> ///// <param name="w">The w-component to create the packed representation from.</param>
void PackFromBytes(byte x, byte y, byte z, byte w); //void PackFromBytes(byte x, byte y, byte z, byte w);
/// <summary> /// <summary>
/// Expands the packed representation into a <see cref="Vector4"/>. /// Expands the packed representation into a <see cref="Vector4"/>.
@ -61,12 +45,12 @@ namespace ImageProcessorCore
/// <returns>The <see cref="Vector4"/>.</returns> /// <returns>The <see cref="Vector4"/>.</returns>
Vector4 ToVector4(); Vector4 ToVector4();
/// <summary> ///// <summary>
/// Expands the packed representation into a <see cref="T:byte[]"/>. ///// Expands the packed representation into a <see cref="T:byte[]"/>.
/// The bytes are typically expanded in least to greatest significance order. ///// The bytes are typically expanded in least to greatest significance order.
/// Red -> Green -> Blue -> Alpha ///// Red -> Green -> Blue -> Alpha
/// </summary> ///// </summary>
/// <returns>The <see cref="Vector4"/>.</returns> ///// <returns>The <see cref="Vector4"/>.</returns>
byte[] ToBytes(); //byte[] ToBytes();
} }
} }

8
src/ImageProcessorCore/Common/Helpers/ImageMaths.cs

@ -180,19 +180,19 @@ namespace ImageProcessorCore
switch (channel) switch (channel)
{ {
case RgbaComponent.R: case RgbaComponent.R:
delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToBytes()[0] - b) > Epsilon; delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToVector4().X - b) > Epsilon;
break; break;
case RgbaComponent.G: case RgbaComponent.G:
delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToBytes()[1] - b) > Epsilon; delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToVector4().Y - b) > Epsilon;
break; break;
case RgbaComponent.B: case RgbaComponent.B:
delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToBytes()[2] - b) > Epsilon; delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToVector4().Z - b) > Epsilon;
break; break;
default: default:
delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToBytes()[3] - b) > Epsilon; delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToVector4().W - b) > Epsilon;
break; break;
} }

2
src/ImageProcessorCore/Filters/DetectEdges.cs

@ -118,7 +118,7 @@ namespace ImageProcessorCore
break; break;
default: default:
processor = new ScharrProcessor<TColor, TPacked> { Grayscale = grayscale }; processor = new SobelProcessor<TColor, TPacked> { Grayscale = grayscale };
break; break;
} }

2
src/ImageProcessorCore/Filters/Processors/ColorMatrix/LomographProcessor.cs

@ -31,7 +31,7 @@ namespace ImageProcessorCore.Processors
protected override void AfterApply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle) protected override void AfterApply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle)
{ {
TColor packed = default(TColor); TColor packed = default(TColor);
packed.PackFromBytes(0, 10, 0, 255); // Very dark (mostly black) lime green. packed.PackFromVector4(new Color(0, 10, 0).ToVector4()); // Very dark (mostly black) lime green.
new VignetteProcessor<TColor, TPacked> { VignetteColor = packed }.Apply(target, target, sourceRectangle); new VignetteProcessor<TColor, TPacked> { VignetteColor = packed }.Apply(target, target, sourceRectangle);
} }
} }

4
src/ImageProcessorCore/Filters/Processors/ColorMatrix/PolaroidProcessor.cs

@ -37,11 +37,11 @@ namespace ImageProcessorCore.Processors
protected override void AfterApply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle) protected override void AfterApply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle)
{ {
TColor packedV = default(TColor); TColor packedV = default(TColor);
packedV.PackFromBytes(102, 34, 0, 255); // Very dark orange [Brown tone] packedV.PackFromVector4(new Color(102, 34, 0).ToVector4()); // Very dark orange [Brown tone]
new VignetteProcessor<TColor, TPacked> { VignetteColor = packedV }.Apply(target, target, sourceRectangle); new VignetteProcessor<TColor, TPacked> { VignetteColor = packedV }.Apply(target, target, sourceRectangle);
TColor packedG = default(TColor); TColor packedG = default(TColor);
packedG.PackFromBytes(255, 153, 102, 178); // Light orange packedG.PackFromVector4(new Color(255, 153, 102, 178).ToVector4()); // Light orange
new GlowProcessor<TColor, TPacked> { GlowColor = packedG, Radius = target.Width / 4F }.Apply(target, target, sourceRectangle); new GlowProcessor<TColor, TPacked> { GlowColor = packedG, Radius = target.Width / 4F }.Apply(target, target, sourceRectangle);
} }
} }

9
src/ImageProcessorCore/Formats/Bmp/BmpDecoderCore.cs

@ -243,7 +243,7 @@ namespace ImageProcessorCore.Formats
// Stored in b-> g-> r order. // Stored in b-> g-> r order.
TColor packed = default(TColor); TColor packed = default(TColor);
packed.PackFromBytes(colors[colorIndex + 2], colors[colorIndex + 1], colors[colorIndex], 255); packed.PackFromVector4(new Color(colors[colorIndex + 2], colors[colorIndex + 1], colors[colorIndex]).ToVector4());
imageData[arrayOffset] = packed; imageData[arrayOffset] = packed;
} }
} }
@ -295,7 +295,7 @@ namespace ImageProcessorCore.Formats
// Stored in b-> g-> r order. // Stored in b-> g-> r order.
TColor packed = default(TColor); TColor packed = default(TColor);
packed.PackFromBytes(r, g, b, 255); packed.PackFromVector4(new Color(r, g, b).ToVector4());
imageData[arrayOffset] = packed; imageData[arrayOffset] = packed;
} }
}); });
@ -333,10 +333,9 @@ namespace ImageProcessorCore.Formats
int offset = rowOffset + (x * 3); int offset = rowOffset + (x * 3);
int arrayOffset = ((row * width) + x); int arrayOffset = ((row * width) + x);
// We divide by 255 as we will store the colors in our floating point format.
// Stored in b-> g-> r-> a order. // Stored in b-> g-> r-> a order.
TColor packed = default(TColor); TColor packed = default(TColor);
packed.PackFromBytes(data[offset + 2], data[offset + 1], data[offset], 255); packed.PackFromVector4(new Color(data[offset + 2], data[offset + 1], data[offset]).ToVector4());
imageData[arrayOffset] = packed; imageData[arrayOffset] = packed;
} }
}); });
@ -376,7 +375,7 @@ namespace ImageProcessorCore.Formats
// Stored in b-> g-> r-> a order. // Stored in b-> g-> r-> a order.
TColor packed = default(TColor); TColor packed = default(TColor);
packed.PackFromBytes(data[offset + 2], data[offset + 1], data[offset], data[offset + 3]); packed.PackFromVector4(new Color(data[offset + 2], data[offset + 1], data[offset], data[offset + 3]).ToVector4());
imageData[arrayOffset] = packed; imageData[arrayOffset] = packed;
} }
}); });

10
src/ImageProcessorCore/Formats/Bmp/BmpEncoderCore.cs

@ -160,8 +160,8 @@ namespace ImageProcessorCore.Formats
for (int x = 0; x < pixels.Width; x++) for (int x = 0; x < pixels.Width; x++)
{ {
// Convert back to b-> g-> r-> a order. // Convert back to b-> g-> r-> a order.
byte[] bytes = pixels[x, y].ToBytes(); Color color = new Color(pixels[x, y].ToVector4());
writer.Write(new[] { bytes[2], bytes[1], bytes[0], bytes[3] }); writer.Write(new[] { color.B, color.G, color.R, color.A });
} }
// Pad // Pad
@ -177,7 +177,7 @@ namespace ImageProcessorCore.Formats
/// </summary> /// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam> /// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>/// <param name="writer">The <see cref="EndianBinaryWriter"/> containing the stream to write to.</param> /// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>/// <param name="writer">The <see cref="EndianBinaryWriter"/> containing the stream to write to.</param>
/// <param name="pixels">The <see cref="IPixelAccessor"/> containing pixel data.</param> /// <param name="pixels">The <see cref="PixelAccessor{TColor,TPacked}"/> containing pixel data.</param>
private void Write24Bit<TColor, TPacked>(EndianBinaryWriter writer, PixelAccessor<TColor, TPacked> pixels) private void Write24Bit<TColor, TPacked>(EndianBinaryWriter writer, PixelAccessor<TColor, TPacked> pixels)
where TColor : IPackedVector<TPacked> where TColor : IPackedVector<TPacked>
where TPacked : struct where TPacked : struct
@ -187,8 +187,8 @@ namespace ImageProcessorCore.Formats
for (int x = 0; x < pixels.Width; x++) for (int x = 0; x < pixels.Width; x++)
{ {
// Convert back to b-> g-> r order. // Convert back to b-> g-> r order.
byte[] bytes = pixels[x, y].ToBytes(); Color color = new Color(pixels[x, y].ToVector4());
writer.Write(new[] { bytes[2], bytes[1], bytes[0] }); writer.Write(new[] { color.B, color.G, color.R });
} }
// Pad // Pad

3
src/ImageProcessorCore/Formats/Gif/GifDecoderCore.cs

@ -358,9 +358,8 @@ namespace ImageProcessorCore.Formats
{ {
// Stored in r-> g-> b-> a order. // Stored in r-> g-> b-> a order.
int indexOffset = index * 3; int indexOffset = index * 3;
TColor pixel = default(TColor); TColor pixel = default(TColor);
pixel.PackFromBytes(colorTable[indexOffset], colorTable[indexOffset + 1], colorTable[indexOffset + 2], 255); pixel.PackFromVector4(new Color(colorTable[indexOffset], colorTable[indexOffset + 1], colorTable[indexOffset + 2]).ToVector4());
this.currentFrame[offset] = pixel; this.currentFrame[offset] = pixel;
} }

8
src/ImageProcessorCore/Formats/Gif/GifEncoderCore.cs

@ -281,11 +281,11 @@ namespace ImageProcessorCore.Formats
i => i =>
{ {
int offset = i * 3; int offset = i * 3;
byte[] color = palette[i].ToBytes(); Color color = new Color(palette[i].ToVector4());
colorTable[offset] = color[0]; colorTable[offset] = color.R;
colorTable[offset + 1] = color[1]; colorTable[offset + 1] = color.G;
colorTable[offset + 2] = color[2]; colorTable[offset + 2] = color.B;
}); });
writer.Write(colorTable, 0, colorTableLength); writer.Write(colorTable, 0, colorTableLength);

2
src/ImageProcessorCore/Formats/Jpg/JpegDecoderCore.cs.REMOVED.git-id

@ -1 +1 @@
d6ce5dd6236ac6ef9ba570fb4e57e81c06bbb854 508fcf1910c42f4e080fcfd9c9f22ba724c1990c

8
src/ImageProcessorCore/Formats/Jpg/JpegEncoderCore.cs

@ -2,6 +2,9 @@
// Copyright (c) James Jackson-South and contributors. // Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
// </copyright> // </copyright>
using System.Numerics;
namespace ImageProcessorCore.Formats namespace ImageProcessorCore.Formats
{ {
using System; using System;
@ -349,10 +352,7 @@ namespace ImageProcessorCore.Formats
{ {
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
{ {
// Bytes are expected in r->g->b->a oder. YCbCr color = new Color(pixels[Math.Min(x + i, xmax), Math.Min(y + j, ymax)].ToVector4());
byte[] pixel = pixels[Math.Min(x + i, xmax), Math.Min(y + j, ymax)].ToBytes();
YCbCr color = new Color(pixel[0], pixel[1], pixel[2], pixel[3]);
int index = (8 * j) + i; int index = (8 * j) + i;
yBlock[index] = (int)color.Y; yBlock[index] = (int)color.Y;
cbBlock[index] = (int)color.Cb; cbBlock[index] = (int)color.Cb;

14
src/ImageProcessorCore/Formats/Png/PngDecoderCore.cs

@ -3,6 +3,8 @@
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
// </copyright> // </copyright>
using System.Numerics;
namespace ImageProcessorCore.Formats namespace ImageProcessorCore.Formats
{ {
using System; using System;
@ -339,7 +341,7 @@ namespace ImageProcessorCore.Formats
byte intensity = defilteredScanline[offset]; byte intensity = defilteredScanline[offset];
TColor color = default(TColor); TColor color = default(TColor);
color.PackFromBytes(intensity, intensity, intensity, 255); color.PackFromVector4(new Vector4(intensity, intensity, intensity, 255) / 255F);
pixels[(row * this.header.Width) + x] = color; pixels[(row * this.header.Width) + x] = color;
} }
@ -355,7 +357,7 @@ namespace ImageProcessorCore.Formats
byte alpha = defilteredScanline[offset + bytesPerSample]; byte alpha = defilteredScanline[offset + bytesPerSample];
TColor color = default(TColor); TColor color = default(TColor);
color.PackFromBytes(intensity, intensity, intensity, alpha); color.PackFromVector4(new Vector4(intensity, intensity, intensity, alpha) / 255F);
pixels[(row * this.header.Width) + x] = color; pixels[(row * this.header.Width) + x] = color;
} }
@ -382,7 +384,7 @@ namespace ImageProcessorCore.Formats
byte r = this.palette[pixelOffset]; byte r = this.palette[pixelOffset];
byte g = this.palette[pixelOffset + 1]; byte g = this.palette[pixelOffset + 1];
byte b = this.palette[pixelOffset + 2]; byte b = this.palette[pixelOffset + 2];
color.PackFromBytes(r, g, b, a); color.PackFromVector4(new Vector4(r, g, b, a) / 255F);
} }
pixels[offset] = color; pixels[offset] = color;
@ -401,7 +403,7 @@ namespace ImageProcessorCore.Formats
byte b = this.palette[pixelOffset + 2]; byte b = this.palette[pixelOffset + 2];
TColor color = default(TColor); TColor color = default(TColor);
color.PackFromBytes(r, g, b, 255); color.PackFromVector4(new Vector4(r, g, b, 255) / 255F);
pixels[offset] = color; pixels[offset] = color;
} }
} }
@ -419,7 +421,7 @@ namespace ImageProcessorCore.Formats
byte b = defilteredScanline[offset + 2 * bytesPerSample]; byte b = defilteredScanline[offset + 2 * bytesPerSample];
TColor color = default(TColor); TColor color = default(TColor);
color.PackFromBytes(r, g, b, 255); color.PackFromVector4(new Vector4(r, g, b, 255) / 255F);
pixels[(row * this.header.Width) + x] = color; pixels[(row * this.header.Width) + x] = color;
} }
@ -437,7 +439,7 @@ namespace ImageProcessorCore.Formats
byte a = defilteredScanline[offset + 3 * bytesPerSample]; byte a = defilteredScanline[offset + 3 * bytesPerSample];
TColor color = default(TColor); TColor color = default(TColor);
color.PackFromBytes(r, g, b, a); color.PackFromVector4(new Vector4(r, g, b, a) / 255F);
pixels[(row * this.header.Width) + x] = color; pixels[(row * this.header.Width) + x] = color;
} }

20
src/ImageProcessorCore/Formats/Png/PngEncoderCore.cs

@ -264,15 +264,17 @@ namespace ImageProcessorCore.Formats
Bootstrapper.Instance.ParallelOptions, Bootstrapper.Instance.ParallelOptions,
y => y =>
{ {
// Color data is stored in r -> g -> b -> a order
for (int x = 0; x < this.width; x++) for (int x = 0; x < this.width; x++)
{ {
int dataOffset = (y * stride) + (x * this.bytesPerPixel); int dataOffset = (y * stride) + (x * this.bytesPerPixel);
byte[] source = pixels[x, y].ToBytes(); Color source = new Color(pixels[x, y].ToVector4());
for (int i = 0; i < this.bytesPerPixel; i++) this.pixelData[dataOffset] = source.R;
this.pixelData[dataOffset + 1] = source.G;
this.pixelData[dataOffset + 2] = source.B;
if (this.bytesPerPixel == 4)
{ {
this.pixelData[dataOffset + i] = source[i]; this.pixelData[dataOffset + 3] = source.A;
} }
} }
}); });
@ -511,12 +513,10 @@ namespace ImageProcessorCore.Formats
i => i =>
{ {
int offset = i * 3; int offset = i * 3;
byte[] color = palette[i].ToBytes(); Color color = new Color(palette[i].ToVector4());
colorTable[offset] = color.R;
// Expected format r->g->b colorTable[offset + 1] = color.G;
colorTable[offset] = color[0]; colorTable[offset + 2] = color.B;
colorTable[offset + 1] = color[1];
colorTable[offset + 2] = color[2];
}); });
this.WriteChunk(stream, PngChunkTypes.Palette, colorTable); this.WriteChunk(stream, PngChunkTypes.Palette, colorTable);

36
src/ImageProcessorCore/Quantizers/Octree/OctreeQuantizer.cs

@ -86,7 +86,7 @@ namespace ImageProcessorCore.Quantizers
byte paletteIndex = (byte)this.colors; byte paletteIndex = (byte)this.colors;
// Get the palette index if it's transparency meets criterea. // Get the palette index if it's transparency meets criterea.
if (pixel.ToBytes()[3] > this.Threshold) if (new Color(pixel.ToVector4()).A > this.Threshold)
{ {
paletteIndex = (byte)this.octree.GetPaletteIndex(pixel); paletteIndex = (byte)this.octree.GetPaletteIndex(pixel);
} }
@ -397,10 +397,10 @@ namespace ImageProcessorCore.Quantizers
{ {
// Go to the next level down in the tree // Go to the next level down in the tree
int shift = 7 - level; int shift = 7 - level;
byte[] components = pixel.ToBytes(); Color color = new Color(pixel.ToVector4());
int index = ((components[2] & Mask[level]) >> (shift - 2)) | int index = ((color.B & Mask[level]) >> (shift - 2)) |
((components[1] & Mask[level]) >> (shift - 1)) | ((color.G & Mask[level]) >> (shift - 1)) |
((components[0] & Mask[level]) >> shift); ((color.R & Mask[level]) >> shift);
OctreeNode child = this.children[index]; OctreeNode child = this.children[index];
@ -468,7 +468,7 @@ namespace ImageProcessorCore.Quantizers
// And set the color of the palette entry // And set the color of the palette entry
TColor pixel = default(TColor); TColor pixel = default(TColor);
pixel.PackFromBytes(r, g, b, 255); pixel.PackFromVector4(new Color(r, g, b).ToVector4());
palette.Add(pixel); palette.Add(pixel);
} }
else else
@ -487,12 +487,8 @@ namespace ImageProcessorCore.Quantizers
/// <summary> /// <summary>
/// Return the palette index for the passed color /// Return the palette index for the passed color
/// </summary> /// </summary>
/// <param name="pixel"> /// <param name="pixel">The <see cref="TColor"/> representing the pixel.</param>
/// The <see cref="T"/> representing the pixel. /// <param name="level">The level.</param>
/// </param>
/// <param name="level">
/// The level.
/// </param>
/// <returns> /// <returns>
/// The <see cref="int"/> representing the index of the pixel in the palette. /// The <see cref="int"/> representing the index of the pixel in the palette.
/// </returns> /// </returns>
@ -503,10 +499,10 @@ namespace ImageProcessorCore.Quantizers
if (!this.leaf) if (!this.leaf)
{ {
int shift = 7 - level; int shift = 7 - level;
byte[] components = pixel.ToBytes(); Color color = new Color(pixel.ToVector4());
int pixelIndex = ((components[2] & Mask[level]) >> (shift - 2)) | int pixelIndex = ((color.B & Mask[level]) >> (shift - 2)) |
((components[1] & Mask[level]) >> (shift - 1)) | ((color.G & Mask[level]) >> (shift - 1)) |
((components[0] & Mask[level]) >> shift); ((color.R & Mask[level]) >> shift);
if (this.children[pixelIndex] != null) if (this.children[pixelIndex] != null)
{ {
@ -530,10 +526,10 @@ namespace ImageProcessorCore.Quantizers
public void Increment(TColor pixel) public void Increment(TColor pixel)
{ {
this.pixelCount++; this.pixelCount++;
byte[] components = pixel.ToBytes(); Color color = new Color(pixel.ToVector4());
this.red += components[0]; this.red += color.R;
this.green += components[1]; this.green += color.G;
this.blue += components[2]; this.blue += color.B;
} }
} }
} }

20
src/ImageProcessorCore/Quantizers/Palette/PaletteQuantizer.cs

@ -81,13 +81,13 @@ namespace ImageProcessorCore.Quantizers
{ {
// Not found - loop through the palette and find the nearest match. // Not found - loop through the palette and find the nearest match.
// Firstly check the alpha value - if less than the threshold, lookup the transparent color // Firstly check the alpha value - if less than the threshold, lookup the transparent color
byte[] bytes = pixel.ToBytes(); Color color =new Color(pixel.ToVector4());
if (!(bytes[3] > this.Threshold)) if (!(color.A > this.Threshold))
{ {
// Transparent. Lookup the first color with an alpha value of 0 // Transparent. Lookup the first color with an alpha value of 0
for (int index = 0; index < this.colors.Length; index++) for (int index = 0; index < this.colors.Length; index++)
{ {
if (this.colors[index].ToBytes()[3] == 0) if (new Color(this.colors[index].ToVector4()).A == 0)
{ {
colorIndex = (byte)index; colorIndex = (byte)index;
this.TransparentIndex = colorIndex; this.TransparentIndex = colorIndex;
@ -99,17 +99,17 @@ namespace ImageProcessorCore.Quantizers
{ {
// Not transparent... // Not transparent...
int leastDistance = int.MaxValue; int leastDistance = int.MaxValue;
int red = bytes[0]; int red = color.R;
int green = bytes[1]; int green = color.G;
int blue = bytes[2]; int blue = color.B;
// Loop through the entire palette, looking for the closest color match // Loop through the entire palette, looking for the closest color match
for (int index = 0; index < this.colors.Length; index++) for (int index = 0; index < this.colors.Length; index++)
{ {
byte[] paletteColor = this.colors[index].ToBytes(); Color paletteColor = new Color(this.colors[index].ToVector4());
int redDistance = paletteColor[0] - red; int redDistance = paletteColor.R - red;
int greenDistance = paletteColor[1] - green; int greenDistance = paletteColor.G - green;
int blueDistance = paletteColor[2] - blue; int blueDistance = paletteColor.B - blue;
int distance = (redDistance * redDistance) + int distance = (redDistance * redDistance) +
(greenDistance * greenDistance) + (greenDistance * greenDistance) +

26
src/ImageProcessorCore/Quantizers/Wu/WuQuantizer.cs

@ -3,6 +3,8 @@
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
// </copyright> // </copyright>
using System.Numerics;
namespace ImageProcessorCore.Quantizers namespace ImageProcessorCore.Quantizers
{ {
using System; using System;
@ -332,12 +334,12 @@ namespace ImageProcessorCore.Quantizers
for (int x = 0; x < pixels.Width; x++) for (int x = 0; x < pixels.Width; x++)
{ {
// Colors are expected in r->g->b->a format // Colors are expected in r->g->b->a format
byte[] color = pixels[x, y].ToBytes(); Color color = new Color(pixels[x, y].ToVector4());
byte r = color[0]; byte r = color.R;
byte g = color[1]; byte g = color.G;
byte b = color[2]; byte b = color.B;
byte a = color[3]; byte a = color.A;
int inr = r >> (8 - IndexBits); int inr = r >> (8 - IndexBits);
int ing = g >> (8 - IndexBits); int ing = g >> (8 - IndexBits);
@ -745,7 +747,7 @@ namespace ImageProcessorCore.Quantizers
byte a = (byte)(Volume(cube[k], this.vma) / weight); byte a = (byte)(Volume(cube[k], this.vma) / weight);
TColor color = default(TColor); TColor color = default(TColor);
color.PackFromBytes(r, g, b, a); color.PackFromVector4(new Vector4(r, g, b, a) / 255F);
if (color.Equals(default(TColor))) if (color.Equals(default(TColor)))
{ {
@ -770,13 +772,13 @@ namespace ImageProcessorCore.Quantizers
for (int x = 0; x < width; x++) for (int x = 0; x < width; x++)
{ {
// Expected order r->g->b->a // Expected order r->g->b->a
byte[] color = imagePixels[x, y].ToBytes(); Color color = new Color(imagePixels[x, y].ToVector4());
int r = color[0] >> (8 - IndexBits); int r = color.R >> (8 - IndexBits);
int g = color[1] >> (8 - IndexBits); int g = color.G >> (8 - IndexBits);
int b = color[2] >> (8 - IndexBits); int b = color.B >> (8 - IndexBits);
int a = color[3] >> (8 - IndexAlphaBits); int a = color.A >> (8 - IndexAlphaBits);
if (transparentIndex > -1 && color[3] <= this.Threshold) if (transparentIndex > -1 && color.A <= this.Threshold)
{ {
pixels[(y * width) + x] = (byte)transparentIndex; pixels[(y * width) + x] = (byte)transparentIndex;
continue; continue;

Loading…
Cancel
Save