Browse Source

Now Color

Former-commit-id: df0c84ebe32444c8e2bf964f839af8fd6b80d196
Former-commit-id: af528ad7c73c8c20f1f1fb5f0e4864bc00dfc4ee
Former-commit-id: e62c836d6621e86a03386c83867d4dbcb668dc5e
af/merge-core
James Jackson-South 10 years ago
parent
commit
ee8987857d
  1. 2
      src/ImageProcessorCore/Bootstrapper.cs
  2. 27
      src/ImageProcessorCore/Formats/Bmp/BmpDecoderCore.cs
  3. 36
      src/ImageProcessorCore/Formats/Bmp/BmpEncoderCore.cs
  4. 4
      src/ImageProcessorCore/Image.cs
  5. 45
      src/ImageProcessorCore/PackedVector/Color.cs
  6. 1
      src/ImageProcessorCore/PackedVector/IPackedVector.cs
  7. 20
      src/ImageProcessorCore/PixelAccessor/ColorPixelAccessor.cs
  8. 12
      tests/ImageProcessorCore.Benchmarks/Image/GetSetPixel.cs

2
src/ImageProcessorCore/Bootstrapper.cs

@ -44,7 +44,7 @@ namespace ImageProcessorCore
this.pixelAccessors = new Dictionary<Type, Func<IImageBase, IPixelAccessor>>
{
{ typeof(Bgra32), i=> new Bgra32PixelAccessor(i) }
{ typeof(Color), i=> new ColorPixelAccessor(i) }
};
}

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

@ -49,7 +49,8 @@ namespace ImageProcessorCore.Formats
/// Decodes the image from the specified this._stream and sets
/// the data to image.
/// </summary>
/// <typeparam name="T">The type of pixels contained within the image.</typeparam>
/// <typeparam name="T">The pixel format.</typeparam>
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
/// <param name="image">The image, where the data should be set to.
/// Cannot be null (Nothing in Visual Basic).</param>
/// <param name="stream">The this._stream, where the image should be
@ -187,7 +188,8 @@ namespace ImageProcessorCore.Formats
/// <summary>
/// Reads the color palette from the stream.
/// </summary>
/// <typeparam name="T">The type of pixels contained within the image.</typeparam>
/// <typeparam name="T">The pixel format.</typeparam>
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
/// <param name="imageData">The <see cref="T:T[]"/> image data to assign the palette to.</param>
/// <param name="colors">The <see cref="T:byte[]"/> containing the colors.</param>
/// <param name="width">The width of the bitmap.</param>
@ -238,9 +240,9 @@ namespace ImageProcessorCore.Formats
int colorIndex = ((data[offset] >> (8 - bits - (shift * bits))) & mask) * 4;
int arrayOffset = (row * width) + (colOffset + shift);
// Stored in b-> g-> r-> a order.
// Stored in b-> g-> r order.
T packed = default(T);
packed.PackBytes(colors[colorIndex], colors[colorIndex + 1], colors[colorIndex + 2], 255);
packed.PackBytes(colors[colorIndex + 2], colors[colorIndex + 1], colors[colorIndex], 255);
imageData[arrayOffset] = packed;
}
}
@ -250,7 +252,8 @@ namespace ImageProcessorCore.Formats
/// <summary>
/// Reads the 16 bit color palette from the stream
/// </summary>
/// <typeparam name="T">The type of pixels contained within the image.</typeparam>
/// <typeparam name="T">The pixel format.</typeparam>
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
/// <param name="imageData">The <see cref="T:T[]"/> image data to assign the palette to.</param>
/// <param name="width">The width of the bitmap.</param>
/// <param name="height">The height of the bitmap.</param>
@ -288,9 +291,9 @@ namespace ImageProcessorCore.Formats
int arrayOffset = ((row * width) + x);
// Stored in b-> g-> r-> a order.
// Stored in b-> g-> r order.
T packed = default(T);
packed.PackBytes(b, g, r, 255);
packed.PackBytes(r, g, b, 255);
imageData[arrayOffset] = packed;
}
});
@ -299,7 +302,8 @@ namespace ImageProcessorCore.Formats
/// <summary>
/// Reads the 24 bit color palette from the stream
/// </summary>
/// <typeparam name="T">The type of pixels contained within the image.</typeparam>
/// <typeparam name="T">The pixel format.</typeparam>
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
/// <param name="imageData">The <see cref="T:T[]"/> image data to assign the palette to.</param>
/// <param name="width">The width of the bitmap.</param>
/// <param name="height">The height of the bitmap.</param>
@ -329,7 +333,7 @@ namespace ImageProcessorCore.Formats
// We divide by 255 as we will store the colors in our floating point format.
// Stored in b-> g-> r-> a order.
T packed = default(T);
packed.PackBytes(data[offset], data[offset + 1], data[offset + 2], 255);
packed.PackBytes(data[offset + 2], data[offset + 1], data[offset], 255);
imageData[arrayOffset] = packed;
}
});
@ -338,7 +342,8 @@ namespace ImageProcessorCore.Formats
/// <summary>
/// Reads the 32 bit color palette from the stream
/// </summary>
/// <typeparam name="T">The type of pixels contained within the image.</typeparam>
/// <typeparam name="T">The pixel format.</typeparam>
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
/// <param name="imageData">The <see cref="T:T[]"/> image data to assign the palette to.</param>
/// <param name="width">The width of the bitmap.</param>
/// <param name="height">The height of the bitmap.</param>
@ -367,7 +372,7 @@ namespace ImageProcessorCore.Formats
// Stored in b-> g-> r-> a order.
T packed = default(T);
packed.PackBytes(data[offset], data[offset + 1], data[offset + 2], data[offset + 3]);
packed.PackBytes(data[offset + 2], data[offset + 1], data[offset], data[offset + 3]);
imageData[arrayOffset] = packed;
}
});

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

@ -13,7 +13,6 @@ namespace ImageProcessorCore.Formats
/// <summary>
/// Image encoder for writing an image to a stream as a Windows bitmap.
/// </summary>
/// <remarks>The encoder can currently only write 24-bit rgb images to streams.</remarks>
internal sealed class BmpEncoderCore
{
/// <summary>
@ -22,13 +21,14 @@ namespace ImageProcessorCore.Formats
private BmpBitsPerPixel bmpBitsPerPixel;
/// <summary>
/// Encodes the image to the specified stream from the <see cref="ImageBase{T}"/>.
/// Encodes the image to the specified stream from the <see cref="ImageBase{T,TP}"/>.
/// </summary>
/// <typeparam name="T">The type of pixels contained within the image.</typeparam>
/// <param name="image">The <see cref="ImageBase{T}"/> to encode from.</param>
/// <typeparam name="T">The pixel format.</typeparam>
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
/// <param name="image">The <see cref="ImageBase{T,TP}"/> to encode from.</param>
/// <param name="stream">The <see cref="Stream"/> to encode the image data to.</param>
/// <param name="bitsPerPixel">The <see cref="BmpBitsPerPixel"/></param>
public void Encode<T,TP>(ImageBase<T,TP> image, Stream stream, BmpBitsPerPixel bitsPerPixel)
public void Encode<T, TP>(ImageBase<T, TP> image, Stream stream, BmpBitsPerPixel bitsPerPixel)
where T : IPackedVector<TP>, new()
where TP : struct
{
@ -121,14 +121,14 @@ namespace ImageProcessorCore.Formats
/// <summary>
/// Writes the pixel data to the binary stream.
/// </summary>
/// <typeparam name="T">The type of pixels contained within the image.</typeparam>
/// <param name="writer">
/// <typeparam name="T">The pixel format.</typeparam>
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>/// <param name="writer">
/// The <see cref="EndianBinaryWriter"/> containing the stream to write to.
/// </param>
/// <param name="image">
/// The <see cref="ImageBase{T}"/> containing pixel data.
/// The <see cref="ImageBase{T,TP}"/> containing pixel data.
/// </param>
private void WriteImage<T,TP>(EndianBinaryWriter writer, ImageBase<T,TP> image)
private void WriteImage<T, TP>(EndianBinaryWriter writer, ImageBase<T, TP> image)
where T : IPackedVector<TP>, new()
where TP : struct
{
@ -139,7 +139,7 @@ namespace ImageProcessorCore.Formats
amount = 4 - amount;
}
using (IPixelAccessor<T,TP> pixels = image.Lock())
using (IPixelAccessor<T, TP> pixels = image.Lock())
{
switch (this.bmpBitsPerPixel)
{
@ -157,11 +157,12 @@ namespace ImageProcessorCore.Formats
/// <summary>
/// Writes the 32bit color palette to the stream.
/// </summary>
/// <typeparam name="T">The type of pixels contained within the image.</typeparam>
/// <typeparam name="T">The pixel format.</typeparam>
/// <typeparam name="TP">The packed format. <example>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="amount">The amount to pad each row by.</param>
private void Write32bit<T,TP>(EndianBinaryWriter writer, IPixelAccessor<T,TP> pixels, int amount)
private void Write32bit<T, TP>(EndianBinaryWriter writer, IPixelAccessor<T, TP> pixels, int amount)
where T : IPackedVector<TP>, new()
where TP : struct
{
@ -171,7 +172,7 @@ namespace ImageProcessorCore.Formats
{
// Convert back to b-> g-> r-> a order.
byte[] bytes = pixels[x, y].ToBytes();
writer.Write(bytes);
writer.Write(new[] { bytes[2], bytes[1], bytes[0], bytes[3] });
}
// Pad
@ -185,10 +186,11 @@ namespace ImageProcessorCore.Formats
/// <summary>
/// Writes the 24bit color palette to the stream.
/// </summary>
/// <param name="writer">The <see cref="EndianBinaryWriter"/> containing the stream to write to.</param>
/// <typeparam name="T">The pixel format.</typeparam>
/// <typeparam name="TP">The packed format. <example>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="amount">The amount to pad each row by.</param>
private void Write24bit<T,TP>(EndianBinaryWriter writer, IPixelAccessor<T,TP> pixels, int amount)
private void Write24bit<T, TP>(EndianBinaryWriter writer, IPixelAccessor<T, TP> pixels, int amount)
where T : IPackedVector<TP>, new()
where TP : struct
{
@ -196,9 +198,9 @@ namespace ImageProcessorCore.Formats
{
for (int x = 0; x < pixels.Width; x++)
{
// Convert back to b-> g-> r-> a order.
// Convert back to b-> g-> r order.
byte[] bytes = pixels[x, y].ToBytes();
writer.Write(new[] { bytes[0], bytes[1], bytes[2] });
writer.Write(new[] { bytes[2], bytes[1], bytes[0] });
}
// Pad

4
src/ImageProcessorCore/Image.cs

@ -9,9 +9,9 @@ namespace ImageProcessorCore
using System.IO;
/// <summary>
/// Represents an image. Each pixel is a made up four 8-bit components blue, green, red, and alpha.
/// Represents an image. Each pixel is a made up four 8-bit components red, green, blue, and alpha.
/// </summary>
public class Image : Image<Bgra32, uint>
public class Image : Image<Color, uint>
{
/// <summary>
/// Initializes a new instance of the <see cref="Image"/> class

45
src/ImageProcessorCore/PackedVector/Bgra32.cs → src/ImageProcessorCore/PackedVector/Color.cs

@ -1,7 +1,8 @@
// <copyright file="Bgra32.cs" company="James Jackson-South">
// <copyright file="Color.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageProcessorCore
{
using System;
@ -13,13 +14,13 @@ namespace ImageProcessorCore
/// Packed vector type containing four 8-bit unsigned normalized values ranging from 0 to 255.
/// </summary>
[StructLayout(LayoutKind.Explicit)]
public struct Bgra32 : IPackedVector<uint>, IEquatable<Bgra32>
public struct Color : IPackedVector<uint>, IEquatable<Color>
{
/// <summary>
/// Gets or sets the blue component.
/// </summary>
[FieldOffset(0)]
public byte B;
public byte R;
/// <summary>
/// Gets or sets the green component.
@ -31,7 +32,7 @@ namespace ImageProcessorCore
/// Gets or sets the red component.
/// </summary>
[FieldOffset(2)]
public byte R;
public byte B;
/// <summary>
/// Gets or sets the alpha component.
@ -46,13 +47,13 @@ namespace ImageProcessorCore
private readonly uint packedValue;
/// <summary>
/// Initializes a new instance of the <see cref="Bgra32"/> struct.
/// Initializes a new instance of the <see cref="Color"/> struct.
/// </summary>
/// <param name="b">The blue component.</param>
/// <param name="g">The green component.</param>
/// <param name="r">The red component.</param>
/// <param name="a">The alpha component.</param>
public Bgra32(float b, float g, float r, float a)
public Color(float b, float g, float r, float a)
: this()
{
Vector4 clamped = Vector4.Clamp(new Vector4(b, g, r, a), Vector4.Zero, Vector4.One) * 255f;
@ -63,13 +64,13 @@ namespace ImageProcessorCore
}
/// <summary>
/// Initializes a new instance of the <see cref="Bgra32"/> struct.
/// Initializes a new instance of the <see cref="Color"/> struct.
/// </summary>
/// <param name="b">The blue component.</param>
/// <param name="g">The green component.</param>
/// <param name="r">The red component.</param>
/// <param name="a">The alpha component.</param>
public Bgra32(byte b, byte g, byte r, byte a)
public Color(byte b, byte g, byte r, byte a)
: this()
{
this.B = b;
@ -79,12 +80,12 @@ namespace ImageProcessorCore
}
/// <summary>
/// Initializes a new instance of the <see cref="Bgra32"/> struct.
/// Initializes a new instance of the <see cref="Color"/> struct.
/// </summary>
/// <param name="vector">
/// The vector containing the components for the packed vector.
/// </param>
public Bgra32(Vector4 vector)
public Color(Vector4 vector)
: this()
{
Vector4 clamped = Vector4.Clamp(vector, Vector4.Zero, Vector4.One) * 255f;
@ -95,31 +96,31 @@ namespace ImageProcessorCore
}
/// <summary>
/// Compares two <see cref="Bgra32"/> objects for equality.
/// Compares two <see cref="Color"/> objects for equality.
/// </summary>
/// <param name="left">
/// The <see cref="Bgra32"/> on the left side of the operand.
/// The <see cref="Color"/> on the left side of the operand.
/// </param>
/// <param name="right">
/// The <see cref="Bgra32"/> on the right side of the operand.
/// The <see cref="Color"/> on the right side of the operand.
/// </param>
/// <returns>
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
public static bool operator ==(Bgra32 left, Bgra32 right)
public static bool operator ==(Color left, Color right)
{
return left.packedValue == right.packedValue;
}
/// <summary>
/// Compares two <see cref="Bgra32"/> objects for equality.
/// Compares two <see cref="Color"/> objects for equality.
/// </summary>
/// <param name="left">The <see cref="Bgra32"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="Bgra32"/> on the right side of the operand.</param>
/// <param name="left">The <see cref="Color"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="Color"/> on the right side of the operand.</param>
/// <returns>
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
public static bool operator !=(Bgra32 left, Bgra32 right)
public static bool operator !=(Color left, Color right)
{
return left.packedValue != right.packedValue;
}
@ -164,11 +165,11 @@ namespace ImageProcessorCore
/// <inheritdoc/>
public override bool Equals(object obj)
{
return (obj is Bgra32) && this.Equals((Bgra32)obj);
return (obj is Color) && this.Equals((Color)obj);
}
/// <inheritdoc/>
public bool Equals(Bgra32 other)
public bool Equals(Color other)
{
return this.packedValue == other.packedValue;
}
@ -192,13 +193,13 @@ namespace ImageProcessorCore
/// Returns the hash code for this instance.
/// </summary>
/// <param name="packed">
/// The instance of <see cref="Bgra32"/> to return the hash code for.
/// The instance of <see cref="Color"/> to return the hash code for.
/// </param>
/// <returns>
/// A 32-bit signed integer that is the hash code for this instance.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private int GetHashCode(Bgra32 packed)
private int GetHashCode(Color packed)
{
return packed.packedValue.GetHashCode();
}

1
src/ImageProcessorCore/PackedVector/IPackedVector.cs

@ -55,6 +55,7 @@ namespace ImageProcessorCore
/// <summary>
/// Expands the packed representation into a <see cref="T:byte[]"/>.
/// The bytes are typically expanded in least to greatest significance order.
/// Red -> Green -> Blue -> Alpha
/// </summary>
/// <returns>The <see cref="Vector4"/>.</returns>
byte[] ToBytes();

20
src/ImageProcessorCore/PixelAccessor/Bgra32PixelAccessor.cs → src/ImageProcessorCore/PixelAccessor/ColorPixelAccessor.cs

@ -12,15 +12,15 @@ namespace ImageProcessorCore
/// Provides per-pixel access to an images pixels.
/// </summary>
/// <remarks>
/// The image data is always stored in <see cref="Bgra32"/> format, where the blue, green, red, and
/// The image data is always stored in <see cref="Color"/> format, where the red, green, blue, and
/// alpha values are 8 bit unsigned bytes.
/// </remarks>
public sealed unsafe class Bgra32PixelAccessor : IPixelAccessor<Bgra32, uint>
public sealed unsafe class ColorPixelAccessor : IPixelAccessor<Color, uint>
{
/// <summary>
/// The position of the first pixel in the bitmap.
/// </summary>
private Bgra32* pixelsBase;
private Color* pixelsBase;
/// <summary>
/// Provides a way to access the pixels from unmanaged memory.
@ -41,12 +41,12 @@ namespace ImageProcessorCore
private bool isDisposed;
/// <summary>
/// Initializes a new instance of the <see cref="Bgra32PixelAccessor"/> class.
/// Initializes a new instance of the <see cref="ColorPixelAccessor"/> class.
/// </summary>
/// <param name="image">
/// The image to provide pixel access for.
/// </param>
public Bgra32PixelAccessor(IImageBase image)
public ColorPixelAccessor(IImageBase image)
{
Guard.NotNull(image, nameof(image));
Guard.MustBeGreaterThan(image.Width, 0, "image width");
@ -55,14 +55,14 @@ namespace ImageProcessorCore
this.Width = image.Width;
this.Height = image.Height;
this.pixelsHandle = GCHandle.Alloc(((ImageBase<Bgra32, uint>)image).Pixels, GCHandleType.Pinned);
this.pixelsBase = (Bgra32*)this.pixelsHandle.AddrOfPinnedObject().ToPointer();
this.pixelsHandle = GCHandle.Alloc(((ImageBase<Color, uint>)image).Pixels, GCHandleType.Pinned);
this.pixelsBase = (Color*)this.pixelsHandle.AddrOfPinnedObject().ToPointer();
}
/// <summary>
/// Finalizes an instance of the <see cref="Bgra32PixelAccessor"/> class.
/// Finalizes an instance of the <see cref="ColorPixelAccessor"/> class.
/// </summary>
~Bgra32PixelAccessor()
~ColorPixelAccessor()
{
this.Dispose();
}
@ -89,7 +89,7 @@ namespace ImageProcessorCore
/// than zero and smaller than the width of the pixel.
/// </param>
/// <returns>The <see cref="IPackedVector"/> at the specified position.</returns>
public Bgra32 this[int x, int y]
public Color this[int x, int y]
{
get
{

12
tests/ImageProcessorCore.Benchmarks/Image/GetSetPixel.cs

@ -4,8 +4,8 @@
using BenchmarkDotNet.Attributes;
//using CoreColor = ImageProcessorCore.Color;
//using CoreImage = ImageProcessorCore.Image<Bgra32>;
using CoreColor = ImageProcessorCore.Color;
using CoreImage = ImageProcessorCore.Image;
using SystemColor = System.Drawing.Color;
public class GetSetPixel
@ -21,12 +21,12 @@
}
[Benchmark(Description = "ImageProcessorCore GetSet Pixel")]
public Bgra32 ResizeCore()
public CoreColor ResizeCore()
{
Image<Bgra32, uint> image = new Image<Bgra32, uint>(400, 400);
using (IPixelAccessor<Bgra32, uint> imagePixels = image.Lock())
CoreImage image = new CoreImage(400, 400);
using (IPixelAccessor<CoreColor, uint> imagePixels = image.Lock())
{
imagePixels[200, 200] = new Bgra32(1, 1, 1, 1);
imagePixels[200, 200] = new CoreColor(255, 255, 255, 255);
return imagePixels[200, 200];
}
}

Loading…
Cancel
Save