Browse Source

Use blitting, cleanup code.

Former-commit-id: a52a42b2bfb7b00e838d5c5108c7eaec8bf1da95
Former-commit-id: 495ad3d53a5d04e510dffb7b1f2f71e3fc7b28d1
Former-commit-id: df993deb570146848acce1064c2a6a960ec7d6f2
af/merge-core
James Jackson-South 10 years ago
parent
commit
ea4fae53d4
  1. 32
      src/ImageProcessorCore/Image.cs
  2. 84
      src/ImageProcessorCore/Image/IImageBase.cs
  3. 14
      src/ImageProcessorCore/Image/IImageFrame.cs
  4. 10
      src/ImageProcessorCore/Image/IImageProcessor.cs
  5. 13
      src/ImageProcessorCore/Image/Image.cs
  6. 87
      src/ImageProcessorCore/Image/ImageBase.cs
  7. 27
      src/ImageProcessorCore/Image/ImageExtensions.cs
  8. 9
      src/ImageProcessorCore/Image/ImageFrame.cs
  9. 21
      src/ImageProcessorCore/Image/ImageProperty.cs
  10. 125
      src/ImageProcessorCore/PackedVector/Bgra32.cs
  11. 32
      src/ImageProcessorCore/PackedVector/IPackedVector.cs
  12. 2
      tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs

32
src/ImageProcessorCore/Image.cs

@ -1,19 +1,47 @@
using System.IO;
// <copyright file="Image.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;
using System.IO;
/// <summary>
/// Represents an image. Each pixel is a made up four 8-bit components blue, green, red, and alpha.
/// </summary>
public class Image : Image<Bgra32, uint>
{
// TODO Constructors.
/// <summary>
/// Initializes a new instance of the <see cref="Image"/> class
/// with the height and the width of the image.
/// </summary>
/// <param name="width">The width of the image in pixels.</param>
/// <param name="height">The height of the image in pixels.</param>
public Image(int width, int height)
: base(width, height)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Image"/> class.
/// </summary>
/// <param name="stream">
/// The stream containing image information.
/// </param>
/// <exception cref="ArgumentNullException">Thrown if the <paramref name="stream"/> is null.</exception>
public Image(Stream stream)
: base(stream)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Image"/> class
/// by making a copy from another image.
/// </summary>
/// <param name="other">The other image, where the clone should be made from.</param>
/// <exception cref="ArgumentNullException"><paramref name="other"/> is null.</exception>
public Image(Image other)
: base(other)
{

84
src/ImageProcessorCore/Image/IImageBase.cs

@ -1,29 +1,88 @@
using System.Collections.Generic;
// <copyright file="IImageBase.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;
/// <summary>
/// Encapsulates the basic properties and methods required to manipulate images in varying formats.
/// </summary>
/// <typeparam name="T">The pixel format.</typeparam>
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
public interface IImageBase<T, TP> : IImageBase
where T : IPackedVector<T, TP>, new()
where TP : struct
{
/// <summary>
/// Gets the pixels as an array of the given packed pixel format.
/// </summary>
T[] Pixels { get; }
/// <summary>
/// Sets the pixel array of the image to the given value.
/// </summary>
/// <param name="width">The new width of the image. Must be greater than zero.</param>
/// <param name="height">The new height of the image. Must be greater than zero.</param>
/// <param name="pixels">The array with pixels. Must be a multiple of the width and height.</param>
/// <exception cref="ArgumentOutOfRangeException">
/// Thrown if either <paramref name="width"/> or <paramref name="height"/> are less than or equal to 0.
/// </exception>
/// <exception cref="ArgumentException">
/// Thrown if the <paramref name="pixels"/> length is not equal to Width * Height.
/// </exception>
void SetPixels(int width, int height, T[] pixels);
/// <summary>
/// Sets the pixel array of the image to the given value, creating a copy of
/// the original pixels.
/// </summary>
/// <param name="width">The new width of the image. Must be greater than zero.</param>
/// <param name="height">The new height of the image. Must be greater than zero.</param>
/// <param name="pixels">The array with pixels. Must be a multiple of four times the width and height.</param>
/// <exception cref="ArgumentOutOfRangeException">
/// Thrown if either <paramref name="width"/> or <paramref name="height"/> are less than or equal to 0.
/// </exception>
/// <exception cref="ArgumentException">
/// Thrown if the <paramref name="pixels"/> length is not equal to Width * Height.
/// </exception>
void ClonePixels(int width, int height, T[] pixels);
/// <summary>
/// Locks the image providing access to the pixels.
/// <remarks>
/// It is imperative that the accessor is correctly disposed off after use.
/// </remarks>
/// </summary>
/// <returns>The <see cref="IPixelAccessor"/></returns>
IPixelAccessor<T, TP> Lock();
void SetPixels(int width, int height, T[] pixels);
}
/// <summary>
/// Encapsulates the basic properties and methods required to manipulate images.
/// </summary>
public interface IImageBase
{
/// <summary>
/// Gets the <see cref="Rectangle"/> representing the bounds of the image.
/// </summary>
Rectangle Bounds { get; }
int FrameDelay { get; set; }
int Height { get; }
double PixelRatio { get; }
/// <summary>
/// Gets or sets the quality of the image. This affects the output quality of lossy image formats.
/// </summary>
int Quality { get; set; }
/// <summary>
/// Gets or sets the frame delay for animated images.
/// If not 0, this field specifies the number of hundredths (1/100) of a second to
/// wait before continuing with the processing of the Data Stream.
/// The clock starts ticking immediately after the graphic is rendered.
/// </summary>
int FrameDelay { get; set; }
/// <summary>
/// Gets or sets the maximum allowable width in pixels.
/// </summary>
@ -34,6 +93,19 @@ namespace ImageProcessorCore
/// </summary>
int MaxHeight { get; set; }
/// <summary>
/// Gets the width in pixels.
/// </summary>
int Width { get; }
/// <summary>
/// Gets the height in pixels.
/// </summary>
int Height { get; }
/// <summary>
/// Gets the pixel ratio made up of the width and height.
/// </summary>
double PixelRatio { get; }
}
}

14
src/ImageProcessorCore/Image/IImageFrame.cs

@ -1,6 +1,16 @@
namespace ImageProcessorCore
// <copyright file="IImageFrame.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageProcessorCore
{
public interface IImageFrame<T,TP> : IImageBase<T,TP>
/// <summary>
/// Represents a single frame in a animation.
/// </summary>
/// <typeparam name="T">The pixel format.</typeparam>
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
public interface IImageFrame<T, TP> : IImageBase<T, TP>
where T : IPackedVector<T, TP>, new()
where TP : struct
{

10
src/ImageProcessorCore/Image/IImageProcessor.cs

@ -27,9 +27,10 @@ namespace ImageProcessorCore.Processors
event ProgressEventHandler OnProgress;
/// <summary>
/// Applies the process to the specified portion of the specified <see cref="ImageBase{T}"/>.
/// Applies the process to the specified portion of the specified <see cref="ImageBase{T, TP}"/>.
/// </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="target">Target image to apply the process to.</param>
/// <param name="source">The source image. Cannot be null.</param>
/// <param name="sourceRectangle">
@ -50,10 +51,11 @@ namespace ImageProcessorCore.Processors
new() where TP : struct;
/// <summary>
/// Applies the process to the specified portion of the specified <see cref="ImageBase{T}"/> at the specified
/// Applies the process to the specified portion of the specified <see cref="ImageBase{T, TP}"/> at the specified
/// location and with the specified size.
/// </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="target">Target image to apply the process to.</param>
/// <param name="source">The source image. Cannot be null.</param>
/// <param name="width">The target width.</param>

13
src/ImageProcessorCore/Image/Image.cs

@ -17,9 +17,8 @@ namespace ImageProcessorCore
/// <summary>
/// Encapsulates an image, which consists of the pixel data for a graphics image and its attributes.
/// </summary>
/// <typeparam name="T">
/// The packed vector containing pixel information.
/// </typeparam>
/// <typeparam name="T">The pixel format.</typeparam>
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
public class Image<T, TP> : ImageBase<T, TP>
where T : IPackedVector<T, TP>, new()
where TP : struct
@ -37,7 +36,7 @@ namespace ImageProcessorCore
public const double DefaultVerticalResolution = 96;
/// <summary>
/// Initializes a new instance of the <see cref="Image{T}"/> class.
/// Initializes a new instance of the <see cref="Image{T, TP}"/> class.
/// </summary>
public Image()
{
@ -45,7 +44,7 @@ namespace ImageProcessorCore
}
/// <summary>
/// Initializes a new instance of the <see cref="Image{T}"/> class
/// Initializes a new instance of the <see cref="Image{T, TP}"/> class
/// with the height and the width of the image.
/// </summary>
/// <param name="width">The width of the image in pixels.</param>
@ -58,7 +57,7 @@ namespace ImageProcessorCore
}
/// <summary>
/// Initializes a new instance of the <see cref="Image{T}"/> class.
/// Initializes a new instance of the <see cref="Image{T, TP}"/> class.
/// </summary>
/// <param name="stream">
/// The stream containing image information.
@ -71,7 +70,7 @@ namespace ImageProcessorCore
}
/// <summary>
/// Initializes a new instance of the <see cref="Image{T}"/> class
/// Initializes a new instance of the <see cref="Image{T, TP}"/> class
/// by making a copy from another image.
/// </summary>
/// <param name="other">The other image, where the clone should be made from.</param>

87
src/ImageProcessorCore/Image/ImageBase.cs

@ -8,12 +8,11 @@ namespace ImageProcessorCore
using System;
/// <summary>
/// The base class of all images. Encapsulates the basic properties and methods required to manipulate images
/// in different pixel formats.
/// The base class of all images. Encapsulates the basic properties and methods required to manipulate
/// images in different pixel formats.
/// </summary>
/// <typeparam name="T">
/// The packed vector pixels format.
/// </typeparam>
/// <typeparam name="T">The pixel format.</typeparam>
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
public abstract class ImageBase<T, TP> : IImageBase<T, TP>
where T : IPackedVector<T, TP>, new()
where TP : struct
@ -66,68 +65,34 @@ namespace ImageProcessorCore
Array.Copy(other.Pixels, this.Pixels, other.Pixels.Length);
}
/// <summary>
/// Gets or sets the maximum allowable width in pixels.
/// </summary>
/// <inheritdoc/>
public int MaxWidth { get; set; } = int.MaxValue;
/// <summary>
/// Gets or sets the maximum allowable height in pixels.
/// </summary>
/// <inheritdoc/>
public int MaxHeight { get; set; } = int.MaxValue;
/// <summary>
/// Gets the pixels as an array of the given packed pixel format.
/// </summary>
/// <inheritdoc/>
public T[] Pixels { get; private set; }
/// <summary>
/// Gets the width in pixels.
/// </summary>
/// <inheritdoc/>
public int Width { get; private set; }
/// <summary>
/// Gets the height in pixels.
/// </summary>
/// <inheritdoc/>
public int Height { get; private set; }
/// <summary>
/// Gets the pixel ratio made up of the width and height.
/// </summary>
/// <inheritdoc/>
public double PixelRatio => (double)this.Width / this.Height;
/// <summary>
/// Gets the <see cref="Rectangle"/> representing the bounds of the image.
/// </summary>
/// <inheritdoc/>
public Rectangle Bounds => new Rectangle(0, 0, this.Width, this.Height);
/// <summary>
/// Gets or sets th quality of the image. This affects the output quality of lossy image formats.
/// </summary>
/// <inheritdoc/>
public int Quality { get; set; }
/// <summary>
/// Gets or sets the frame delay for animated images.
/// If not 0, this field specifies the number of hundredths (1/100) of a second to
/// wait before continuing with the processing of the Data Stream.
/// The clock starts ticking immediately after the graphic is rendered.
/// </summary>
/// <inheritdoc/>
public int FrameDelay { get; set; }
/// <summary>
/// Sets the pixel array of the image to the given value.
/// </summary>
/// <param name="width">The new width of the image. Must be greater than zero.</param>
/// <param name="height">The new height of the image. Must be greater than zero.</param>
/// <param name="pixels">
/// The array with colors. Must be a multiple of the width and height.
/// </param>
/// <exception cref="ArgumentOutOfRangeException">
/// Thrown if either <paramref name="width"/> or <paramref name="height"/> are less than or equal to 0.
/// </exception>
/// <exception cref="ArgumentException">
/// Thrown if the <paramref name="pixels"/> length is not equal to Width * Height.
/// </exception>
/// <inheritdoc/>
public void SetPixels(int width, int height, T[] pixels)
{
if (width <= 0)
@ -150,21 +115,7 @@ namespace ImageProcessorCore
this.Pixels = pixels;
}
/// <summary>
/// Sets the pixel array of the image to the given value, creating a copy of
/// the original pixels.
/// </summary>
/// <param name="width">The new width of the image. Must be greater than zero.</param>
/// <param name="height">The new height of the image. Must be greater than zero.</param>
/// <param name="pixels">
/// The array with colors. Must be a multiple of four times the width and height.
/// </param>
/// <exception cref="ArgumentOutOfRangeException">
/// Thrown if either <paramref name="width"/> or <paramref name="height"/> are less than or equal to 0.
/// </exception>
/// <exception cref="ArgumentException">
/// Thrown if the <paramref name="pixels"/> length is not equal to Width * Height.
/// </exception>
/// <inheritdoc/>
public void ClonePixels(int width, int height, T[] pixels)
{
if (width <= 0)
@ -190,13 +141,7 @@ namespace ImageProcessorCore
Array.Copy(pixels, this.Pixels, pixels.Length);
}
/// <summary>
/// Locks the image providing access to the pixels.
/// <remarks>
/// It is imperative that the accessor is correctly disposed off after use.
/// </remarks>
/// </summary>
/// <returns>The <see cref="IPixelAccessor"/></returns>
/// <inheritdoc/>
public abstract IPixelAccessor<T, TP> Lock();
}
}

27
src/ImageProcessorCore/Image/ImageExtensions.cs

@ -12,7 +12,7 @@ namespace ImageProcessorCore
using Processors;
/// <summary>
/// Extension methods for the <see cref="Image{T}"/> type.
/// Extension methods for the <see cref="Image{T, TP}"/> type.
/// </summary>
public static partial class ImageExtensions
{
@ -57,10 +57,11 @@ namespace ImageProcessorCore
/// Applies the collection of processors to the image.
/// <remarks>This method does not resize the target image.</remarks>
/// </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="source">The image this method extends.</param>
/// <param name="processor">The processor to apply to the image.</param>
/// <returns>The <see cref="Image{T}"/>.</returns>
/// <returns>The <see cref="Image{T, TP}"/>.</returns>
public static Image<T, TP> Process<T, TP>(this Image<T, TP> source, IImageProcessor processor)
where T : IPackedVector<T, TP>, new()
where TP : struct
@ -72,13 +73,14 @@ namespace ImageProcessorCore
/// Applies the collection of processors to the image.
/// <remarks>This method does not resize the target image.</remarks>
/// </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="source">The image this method extends.</param>
/// <param name="sourceRectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to draw.
/// </param>
/// <param name="processor">The processors to apply to the image.</param>
/// <returns>The <see cref="Image{T}"/>.</returns>
/// <returns>The <see cref="Image{T, TP}"/>.</returns>
public static Image<T, TP> Process<T, TP>(this Image<T, TP> source, Rectangle sourceRectangle, IImageProcessor processor)
where T : IPackedVector<T, TP>, new()
where TP : struct
@ -92,12 +94,13 @@ namespace ImageProcessorCore
/// This method is not chainable.
/// </remarks>
/// </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="source">The source image. Cannot be null.</param>
/// <param name="width">The target image width.</param>
/// <param name="height">The target image height.</param>
/// <param name="sampler">The processor to apply to the image.</param>
/// <returns>The <see cref="Image{T}"/>.</returns>
/// <returns>The <see cref="Image{T, TP}"/>.</returns>
public static Image<T, TP> Process<T, TP>(this Image<T, TP> source, int width, int height, IImageSampler sampler)
where T : IPackedVector<T, TP>, new()
where TP : struct
@ -111,7 +114,8 @@ namespace ImageProcessorCore
/// This method does will resize the target image if the source and target rectangles are different.
/// </remarks>
/// </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="source">The source image. Cannot be null.</param>
/// <param name="width">The target image width.</param>
/// <param name="height">The target image height.</param>
@ -123,7 +127,7 @@ namespace ImageProcessorCore
/// The image is scaled to fit the rectangle.
/// </param>
/// <param name="sampler">The processor to apply to the image.</param>
/// <returns>The <see cref="Image{T}"/>.</returns>
/// <returns>The <see cref="Image{T, TP}"/>.</returns>
public static Image<T, TP> Process<T, TP>(this Image<T, TP> source, int width, int height, Rectangle sourceRectangle, Rectangle targetRectangle, IImageSampler sampler)
where T : IPackedVector<T, TP>, new()
where TP : struct
@ -134,11 +138,12 @@ namespace ImageProcessorCore
/// <summary>
/// Performs the given action on the source 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="source">The image to perform the action against.</param>
/// <param name="clone">Whether to clone the image.</param>
/// <param name="action">The <see cref="Action"/> to perform against the image.</param>
/// <returns>The <see cref="Image{T}"/>.</returns>
/// <returns>The <see cref="Image{T, TP}"/>.</returns>
private static Image<T, TP> PerformAction<T, TP>(Image<T, TP> source, bool clone, Action<ImageBase<T, TP>, ImageBase<T, TP>> action)
where T : IPackedVector<T, TP>, new()
where TP : struct

9
src/ImageProcessorCore/Image/ImageFrame.cs

@ -8,22 +8,21 @@ namespace ImageProcessorCore
/// <summary>
/// Represents a single frame in a animation.
/// </summary>
/// <typeparam name="T">
/// The packed vector containing pixel information.
/// </typeparam>
/// <typeparam name="T">The pixel format.</typeparam>
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
public class ImageFrame<T, TP> : ImageBase<T, TP>
where T : IPackedVector<T, TP>, new()
where TP : struct
{
/// <summary>
/// Initializes a new instance of the <see cref="ImageFrame{T}"/> class.
/// Initializes a new instance of the <see cref="ImageFrame{T, TP}"/> class.
/// </summary>
public ImageFrame()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ImageFrame{T}"/> class.
/// Initializes a new instance of the <see cref="ImageFrame{T, TP}"/> class.
/// </summary>
/// <param name="frame">
/// The frame to create the frame from.

21
src/ImageProcessorCore/Image/ImageProperty.cs

@ -1,14 +1,7 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ImageProperty.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// <copyright file="ImageProperty.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// <summary>
// Stores meta information about a image, like the name of the author,
// the copyright information, the date, where the image was created
// or some other information.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessorCore
{
@ -24,12 +17,8 @@ namespace ImageProcessorCore
/// <summary>
/// Initializes a new instance of the <see cref="ImageProperty"/> struct.
/// </summary>
/// <param name="name">
/// The name of the property.
/// </param>
/// <param name="value">
/// The value of the property.
/// </param>
/// <param name="name">The name of the property.</param>
/// <param name="value">The value of the property.</param>
public ImageProperty(string name, string value)
{
this.Name = name;

125
src/ImageProcessorCore/PackedVector/Bgra32.cs

@ -7,16 +7,43 @@ namespace ImageProcessorCore
{
using System;
using System.Numerics;
using System.Runtime.InteropServices;
/// <summary>
/// Packed vector type containing four 8-bit unsigned normalized values ranging from 0 to 1.
/// </summary>
[StructLayout(LayoutKind.Explicit)]
public struct Bgra32 : IPackedVector<Bgra32, uint>, IEquatable<Bgra32>
{
/// <summary>
/// Gets or sets the blue component.
/// </summary>
[FieldOffset(0)]
public byte B;
/// <summary>
/// Gets or sets the green component.
/// </summary>
[FieldOffset(1)]
public byte G;
/// <summary>
/// Gets or sets the red component.
/// </summary>
[FieldOffset(2)]
public byte R;
/// <summary>
/// Gets or sets the alpha component.
/// </summary>
[FieldOffset(3)]
public byte A;
/// <summary>
/// The packed value.
/// </summary>
private uint packedValue;
[FieldOffset(0)]
private readonly uint packedValue;
/// <summary>
/// Initializes a new instance of the <see cref="Bgra32"/> struct.
@ -29,7 +56,10 @@ namespace ImageProcessorCore
: this()
{
Vector4 clamped = Vector4.Clamp(new Vector4(b, g, r, a), Vector4.Zero, Vector4.One) * 255f;
this.packedValue = Pack(ref clamped);
this.B = (byte)Math.Round(clamped.X);
this.G = (byte)Math.Round(clamped.Y);
this.R = (byte)Math.Round(clamped.Z);
this.A = (byte)Math.Round(clamped.W);
}
/// <summary>
@ -46,7 +76,6 @@ namespace ImageProcessorCore
this.G = g;
this.R = r;
this.A = a;
this.packedValue = this.Pack();
}
/// <summary>
@ -59,29 +88,12 @@ namespace ImageProcessorCore
: this()
{
Vector4 clamped = Vector4.Clamp(vector, Vector4.Zero, Vector4.One) * 255f;
this.packedValue = Pack(ref clamped);
this.B = (byte)Math.Round(clamped.X);
this.G = (byte)Math.Round(clamped.Y);
this.R = (byte)Math.Round(clamped.Z);
this.A = (byte)Math.Round(clamped.W);
}
/// <summary>
/// Gets or sets the blue component.
/// </summary>
public byte B { get; set; }
/// <summary>
/// Gets or sets the green component.
/// </summary>
public byte G { get; set; }
/// <summary>
/// Gets or sets the red component.
/// </summary>
public byte R { get; set; }
/// <summary>
/// Gets or sets the alpha component.
/// </summary>
public byte A { get; set; }
/// <summary>
/// Compares two <see cref="Bgra32"/> objects for equality.
/// </summary>
@ -113,12 +125,6 @@ namespace ImageProcessorCore
}
/// <inheritdoc/>
public uint PackedValue()
{
this.packedValue = this.Pack();
return this.packedValue;
}
public void Add(Bgra32 value)
{
this.B = (byte)(this.B + value.B);
@ -127,6 +133,7 @@ namespace ImageProcessorCore
this.A = (byte)(this.A + value.A);
}
/// <inheritdoc/>
public void Subtract(Bgra32 value)
{
this.B = (byte)(this.B - value.B);
@ -135,6 +142,7 @@ namespace ImageProcessorCore
this.A = (byte)(this.A - value.A);
}
/// <inheritdoc/>
public void Multiply(Bgra32 value)
{
this.B = (byte)(this.B * value.B);
@ -143,6 +151,7 @@ namespace ImageProcessorCore
this.A = (byte)(this.A * value.A);
}
/// <inheritdoc/>
public void Multiply(float value)
{
this.B = (byte)(this.B * value);
@ -151,6 +160,7 @@ namespace ImageProcessorCore
this.A = (byte)(this.A * value);
}
/// <inheritdoc/>
public void Divide(Bgra32 value)
{
this.B = (byte)(this.B / value.B);
@ -159,6 +169,7 @@ namespace ImageProcessorCore
this.A = (byte)(this.A / value.A);
}
/// <inheritdoc/>
public void Divide(float value)
{
this.B = (byte)(this.B / value);
@ -167,11 +178,20 @@ namespace ImageProcessorCore
this.A = (byte)(this.A / value);
}
/// <inheritdoc/>
public uint PackedValue()
{
return this.packedValue;
}
/// <inheritdoc/>
public void PackVector(Vector4 vector)
{
Vector4 clamped = Vector4.Clamp(vector, Vector4.Zero, Vector4.One) * 255f;
this.packedValue = Pack(ref clamped);
this.B = (byte)Math.Round(clamped.X);
this.G = (byte)Math.Round(clamped.Y);
this.R = (byte)Math.Round(clamped.Z);
this.A = (byte)Math.Round(clamped.W);
}
/// <inheritdoc/>
@ -181,17 +201,12 @@ namespace ImageProcessorCore
this.G = y;
this.R = z;
this.A = w;
this.packedValue = this.Pack();
}
/// <inheritdoc/>
public Vector4 ToVector4()
{
return new Vector4(
this.packedValue & 0xFF,
(this.packedValue >> 8) & 0xFF,
(this.packedValue >> 16) & 0xFF,
(this.packedValue >> 24) & 0xFF) / 255f;
return new Vector4(this.B, this.G, this.R, this.A) / 255f;
}
/// <inheritdoc/>
@ -199,10 +214,10 @@ namespace ImageProcessorCore
{
return new[]
{
(byte)(this.packedValue & 0xFF),
(byte)((this.packedValue >> 8) & 0xFF),
(byte)((this.packedValue >> 16) & 0xFF),
(byte)((this.packedValue >> 24) & 0xFF)
this.B,
this.G,
this.R,
this.A
};
}
@ -233,34 +248,6 @@ namespace ImageProcessorCore
return this.GetHashCode(this);
}
/// <summary>
/// Sets the packed representation from the given component values.
/// </summary>
/// <param name="vector">
/// The vector containing the components for the packed vector.
/// </param>
/// <returns>
/// The <see cref="uint"/>.
/// </returns>
private static uint Pack(ref Vector4 vector)
{
return (uint)Math.Round(vector.X) |
((uint)Math.Round(vector.Y) << 8) |
((uint)Math.Round(vector.Z) << 16) |
((uint)Math.Round(vector.W) << 24);
}
/// <summary>
/// Sets the packed representation from the given component values.
/// </summary>
/// <returns>
/// The <see cref="uint"/>.
/// </returns>
private uint Pack()
{
return this.B | ((uint)this.G << 8) | ((uint)this.R << 16) | ((uint)this.A << 24);
}
/// <summary>
/// Returns the hash code for this instance.
/// </summary>

32
src/ImageProcessorCore/PackedVector/IPackedVector.cs

@ -11,9 +11,8 @@ namespace ImageProcessorCore
/// An interface that converts packed vector types to and from <see cref="Vector4"/> values,
/// allowing multiple encodings to be manipulated in a generic way.
/// </summary>
/// <typeparam name="T">
/// The type of object representing the packed value.
/// </typeparam>
/// <typeparam name="T">The pixel format.</typeparam>
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
public interface IPackedVector<T, TP> : IPackedVector
where TP : struct
{
@ -21,18 +20,45 @@ namespace ImageProcessorCore
/// Gets the packed representation of the value.
/// Typically packed in least to greatest significance order.
/// </summary>
/// <returns>
/// The <see cref="TP"/>.
/// </returns>
TP PackedValue();
/// <summary>
/// Adds the given <see cref="T"/> to the current instance.
/// </summary>
/// <param name="value">The packed vector to add.</param>
void Add(T value);
/// <summary>
/// Subtracts the given <see cref="T"/> from the current instance.
/// </summary>
/// <param name="value">The packed vector to subtract.</param>
void Subtract(T value);
/// <summary>
/// Multiplies the given current instance by given the <see cref="T"/>.
/// </summary>
/// <param name="value">The packed vector to multiply by.</param>
void Multiply(T value);
/// <summary>
/// Multiplies the given current instance by given the value.
/// </summary>
/// <param name="value">The value to multiply by.</param>
void Multiply(float value);
/// <summary>
/// Divides the given current instance by given the <see cref="T"/>.
/// </summary>
/// <param name="value">The packed vector to divide by.</param>
void Divide(T value);
/// <summary>
/// Divides the given current instance by given the value.
/// </summary>
/// <param name="value">The value to divide by.</param>
void Divide(float value);
}

2
tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs

@ -24,7 +24,7 @@ namespace ImageProcessorCore.Tests
//{ "Lanczos3", new Lanczos3Resampler() },
//{ "Lanczos5", new Lanczos5Resampler() },
//{ "Lanczos8", new Lanczos8Resampler() },
//{ "MitchellNetravali", new MitchellNetravaliResampler() },
{ "MitchellNetravali", new MitchellNetravaliResampler() },
//{ "Hermite", new HermiteResampler() },
//{ "Spline", new SplineResampler() },
//{ "Robidoux", new RobidouxResampler() },

Loading…
Cancel
Save