// NOTE: Bitmap objects does not support parallel read-outs blame Microsoft /// <summary> /// Initializes a new instance of the <see cref="cImage"/> class from a <see cref="Bitmap"/> instance. /// </summary> /// <param name="bitmap">The bitmap.</param> public static cImage FromBitmap(Bitmap bitmap) { if (bitmap == null) return (null); var result = new cImage(bitmap.Width, bitmap.Height); var height = result._height; var width = result._width; var bitmapData = bitmap.LockBits( new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb ); var intFillX = bitmapData.Stride - bitmapData.Width * 4; unsafe { var ptrOffset = (byte*)bitmapData.Scan0.ToPointer(); for (var y = 0; y < height; y++) { for (var x = 0; x < width; x++) { result[x, y] = new sPixel(*(ptrOffset + 2), *(ptrOffset + 1), *(ptrOffset + 0), *(ptrOffset + 3)); ptrOffset += 4; } ptrOffset += intFillX; } } bitmap.UnlockBits(bitmapData); return (result); }
/// <summary> /// Weighted interpolation of four <see cref="sPixel"/> instances. /// </summary> /// <param name="pixel1">The first instance.</param> /// <param name="pixel2">The second instance.</param> /// <param name="pixel3">The third instance.</param> /// <param name="pixel4">The fourth instance.</param> /// <param name="quantifier1">The quantifier for the first instance.</param> /// <param name="quantifier2">The quantifier for the second instance.</param> /// <param name="quantifier3">The quantifier for the third instance.</param> /// <param name="quantifier4">The quantifier for the fourth instance.</param> /// <returns>A new instance from the interpolated components.</returns> public static sPixel Interpolate( sPixel pixel1, sPixel pixel2, sPixel pixel3, sPixel pixel4, byte quantifier1, byte quantifier2, byte quantifier3, byte quantifier4) { var total = (UInt16)(quantifier1 + quantifier2 + quantifier3 + quantifier4); return(new sPixel( (byte) ((pixel1.Red * quantifier1 + pixel2.Red * quantifier2 + pixel3.Red * quantifier3 + pixel4.Red * quantifier4) / total), (byte) ((pixel1.Green * quantifier1 + pixel2.Green * quantifier2 + pixel3.Green * quantifier3 + pixel4.Green * quantifier4) / total), (byte) ((pixel1.Blue * quantifier1 + pixel2.Blue * quantifier2 + pixel3.Blue * quantifier3 + pixel4.Blue * quantifier4) / total), (byte) ((pixel1.Alpha * quantifier1 + pixel2.Alpha * quantifier2 + pixel3.Alpha * quantifier3 + pixel4.Alpha * quantifier4) / total) )); }
// NOTE: Bitmap objects does not support parallel read-outs blame Microsoft /// <summary> /// Initializes a new instance of the <see cref="cImage"/> class from a <see cref="Bitmap"/> instance. /// </summary> /// <param name="bitmap">The bitmap.</param> public static cImage FromBitmap(Bitmap bitmap) { if (bitmap == null) { return(null); } var result = new cImage(bitmap.Width, bitmap.Height); var height = result._height; var width = result._width; var bitmapData = bitmap.LockBits( new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb ); var intFillX = bitmapData.Stride - bitmapData.Width * 4; unsafe { var ptrOffset = (byte *)bitmapData.Scan0.ToPointer(); for (var y = 0; y < height; y++) { for (var x = 0; x < width; x++) { result[x, y] = new sPixel(*(ptrOffset + 2), *(ptrOffset + 1), *(ptrOffset + 0), *(ptrOffset + 3)); ptrOffset += 4; } ptrOffset += intFillX; } } bitmap.UnlockBits(bitmapData); return(result); }
/// <summary> /// Calculates the absolute difference between to pixels. /// </summary> /// <param name="pixel">The pixel to differ to.</param> /// <returns>The absolute difference.</returns> public uint AbsDifference(sPixel pixel) { return( _LUMINANCE_TRIGGER * (this.Luminance - pixel.Luminance).Abs() + _CHROMA_V_TRIGGER * (this.ChrominanceV - pixel.ChrominanceV).Abs() + _CHROMA_U_TRIGGER * (this.ChrominanceU - pixel.ChrominanceU).Abs() ); }
/// <summary> /// Interpolates two <see cref="sPixel"/> instances. /// </summary> /// <param name="pixel1">The first pixel instance.</param> /// <param name="pixel2">The second pixel instance.</param> /// <returns>A new instance with the interpolated color values.</returns> public static sPixel Interpolate(sPixel pixel1, sPixel pixel2) { return(new sPixel( (byte)((pixel1.Red + pixel2.Red) >> 1), (byte)((pixel1.Green + pixel2.Green) >> 1), (byte)((pixel1.Blue + pixel2.Blue) >> 1), (byte)((pixel1.Alpha + pixel2.Alpha) >> 1) )); }
/// <summary> /// Interpolates three <see cref="sPixel"/> instances. /// </summary> /// <param name="pixel1">The first pixel instance.</param> /// <param name="pixel2">The second pixel instance.</param> /// <param name="pixel3">The third pixel instance.</param> /// <returns>A new instance with the interpolated color values.</returns> public static sPixel Interpolate(sPixel pixel1, sPixel pixel2, sPixel pixel3) { return(new sPixel( (byte)((pixel1.Red + pixel2.Red + pixel3.Red) / 3), (byte)((pixel1.Green + pixel2.Green + pixel3.Green) / 3), (byte)((pixel1.Blue + pixel2.Blue + pixel3.Blue) / 3), (byte)((pixel1.Alpha + pixel2.Alpha + pixel3.Alpha) / 3) )); }
/// <summary> /// Interpolates four <see cref="sPixel"/> instances. /// </summary> /// <param name="pixel1">The first pixel instance.</param> /// <param name="pixel2">The second pixel instance.</param> /// <param name="pixel3">The third pixel instance.</param> /// <param name="pixel4">The fourth pixel instance.</param> /// <returns>A new instance with the interpolated color values.</returns> public static sPixel Interpolate(sPixel pixel1, sPixel pixel2, sPixel pixel3, sPixel pixel4) { return(new sPixel( (byte)((pixel1.Red + pixel2.Red + pixel3.Red + pixel4.Red) >> 2), (byte)((pixel1.Green + pixel2.Green + pixel3.Green + pixel4.Green) >> 2), (byte)((pixel1.Blue + pixel2.Blue + pixel3.Blue + pixel4.Blue) >> 2), (byte)((pixel1.Alpha + pixel2.Alpha + pixel3.Alpha + pixel4.Alpha) >> 2) )); }
internal void SetPixel(int x, int y, sPixel value) { var width = this._width; var height = this._height; if (x < width && y < height && x >= 0 && y >= 0) { this._imageData[y * width + x] = value; } }
/// <summary> /// Weighted interpolation of two <see cref="sPixel"/> instances. /// </summary> /// <param name="pixel1">The first instance.</param> /// <param name="pixel2">The second instance.</param> /// <param name="quantifier1">The quantifier for the first instance.</param> /// <param name="quantifier2">The quantifier for the second instance.</param> /// <returns>A new instance from the interpolated components.</returns> public static sPixel Interpolate(sPixel pixel1, sPixel pixel2, byte quantifier1, byte quantifier2) { var total = (ushort) (quantifier1 + quantifier2); return (new sPixel( (byte) ((pixel1.Red * quantifier1 + pixel2.Red * quantifier2) / total), (byte) ((pixel1.Green * quantifier1 + pixel2.Green * quantifier2) / total), (byte) ((pixel1.Blue * quantifier1 + pixel2.Blue * quantifier2) / total), (byte) ((pixel1.Alpha * quantifier1 + pixel2.Alpha * quantifier2) / total) )); }
/// <summary> /// Determines whether the specified <see cref="sPixel"/> instance is similar to this instance. /// </summary> /// <param name="pixel">The instance to compare to.</param> /// <returns> /// <c>true</c> if the specified instance is alike; otherwise, <c>false</c>. /// </returns> public bool IsLike(sPixel pixel) { if (!AllowThresholds) return (this == pixel); var delta = this.ChrominanceV - pixel.ChrominanceV; if (delta > _CHROMA_V_TRIGGER || delta < -_CHROMA_V_TRIGGER) return false; delta = this.Luminance - pixel.Luminance; if (delta > _LUMINANCE_TRIGGER || delta < -_LUMINANCE_TRIGGER) return false; delta = this.ChrominanceU - pixel.ChrominanceU; return delta <= _CHROMA_U_TRIGGER && delta >= -_CHROMA_U_TRIGGER; }
/// <summary> /// Determines whether the specified <see cref="sPixel"/> instance is similar to this instance. /// </summary> /// <param name="pixel">The instance to compare to.</param> /// <returns> /// <c>true</c> if the specified instance is alike; otherwise, <c>false</c>. /// </returns> public bool IsLike(sPixel pixel) { if (!AllowThresholds) { return(this == pixel); } var delta = this.Luminance - pixel.Luminance; if (delta.Abs() > _LUMINANCE_TRIGGER) { return(false); } delta = this.ChrominanceV - pixel.ChrominanceV; if (delta.Abs() > _CHROMA_V_TRIGGER) { return(false); } delta = this.ChrominanceU - pixel.ChrominanceU; return(delta.Abs() <= _CHROMA_U_TRIGGER); }
/// <summary> /// Calculates the absolute difference between to pixels. /// </summary> /// <param name="pixel">The pixel to differ to.</param> /// <returns>The absolute difference.</returns> public uint AbsDifference(sPixel pixel) { return ( _LUMINANCE_TRIGGER * (this.Luminance - pixel.Luminance).Abs() + _CHROMA_V_TRIGGER * (this.ChrominanceV - pixel.ChrominanceV).Abs() + _CHROMA_U_TRIGGER * (this.ChrominanceU - pixel.ChrominanceU).Abs() ); }
/// <summary> /// Determines whether this instance is not like the specified <see cref="sPixel"/> instance. /// </summary> /// <param name="pixel">The instance to compare to.</param> /// <returns> /// <c>true</c> if the specified instance is not alike; otherwise, <c>false</c>. /// </returns> public bool IsNotLike(sPixel pixel) { return(!this.IsLike(pixel)); }
/// <summary> /// Determines whether the specified <see cref="sPixel"/> is equal to this instance. /// </summary> /// <param name="pixel">The <see cref="sPixel"/> to compare with this instance.</param> /// <returns> /// <c>true</c> if the specified <see cref="sPixel"/> is equal to this instance; otherwise, <c>false</c>. /// </returns> public bool Equals(sPixel pixel) { return(pixel._rgbBytes == this._rgbBytes); }
/// <summary> /// Initializes a new instance of the <see cref="sPixel"/> struct by using an existing one. /// </summary> /// <param name="pixel">The pixel instance to copy from.</param> public sPixel(sPixel pixel) : this(pixel._rgbBytes) { }
/// <summary> /// Weighted interpolation of two <see cref="sPixel"/> instances. /// </summary> /// <param name="pixel1">The first instance.</param> /// <param name="pixel2">The second instance.</param> /// <param name="quantifier1">The quantifier for the first instance.</param> /// <param name="quantifier2">The quantifier for the second instance.</param> /// <returns>A new instance from the interpolated components.</returns> public static sPixel Interpolate(sPixel pixel1, sPixel pixel2, int quantifier1, int quantifier2) { var total = (uint)(quantifier1 + quantifier2); return (new sPixel( (byte)((pixel1.Red * quantifier1 + pixel2.Red * quantifier2) / total), (byte)((pixel1.Green * quantifier1 + pixel2.Green * quantifier2) / total), (byte)((pixel1.Blue * quantifier1 + pixel2.Blue * quantifier2) / total), (byte)((pixel1.Alpha * quantifier1 + pixel2.Alpha * quantifier2) / total) )); }
/// <summary> /// Determines whether the specified <see cref="sPixel"/> is equal to this instance. /// </summary> /// <param name="pixel">The <see cref="sPixel"/> to compare with this instance.</param> /// <returns> /// <c>true</c> if the specified <see cref="sPixel"/> is equal to this instance; otherwise, <c>false</c>. /// </returns> public bool Equals(sPixel pixel) { return (pixel._rgbBytes == this._rgbBytes); }
/// <summary> /// Fills the image with the specified pixel. /// </summary> /// <param name="pixel">The pixel instance.</param> public void Fill(sPixel pixel) { Parallel.For(0, this._imageData.LongLength, offset => this._imageData[offset] = pixel); }
/// <summary> /// Interpolates three <see cref="sPixel"/> instances. /// </summary> /// <param name="pixel1">The first pixel instance.</param> /// <param name="pixel2">The second pixel instance.</param> /// <param name="pixel3">The third pixel instance.</param> /// <returns>A new instance with the interpolated color values.</returns> public static sPixel Interpolate(sPixel pixel1, sPixel pixel2, sPixel pixel3) { return (new sPixel( (byte)((pixel1.Red + pixel2.Red + pixel3.Red) / 3), (byte)((pixel1.Green + pixel2.Green + pixel3.Green) / 3), (byte)((pixel1.Blue + pixel2.Blue + pixel3.Blue) / 3), (byte)((pixel1.Alpha + pixel2.Alpha + pixel3.Alpha) / 3) )); }
/// <summary> /// Determines whether this instance is not like the specified <see cref="sPixel"/> instance. /// </summary> /// <param name="pixel">The instance to compare to.</param> /// <returns> /// <c>true</c> if the specified instance is not alike; otherwise, <c>false</c>. /// </returns> public bool IsNotLike(sPixel pixel) => !this.IsLike(pixel);
/// <summary> /// Determines whether the specified <see cref="sPixel"/> is equal to this instance. /// </summary> /// <param name="pixel">The <see cref="sPixel"/> to compare with this instance.</param> /// <returns> /// <c>true</c> if the specified <see cref="sPixel"/> is equal to this instance; otherwise, <c>false</c>. /// </returns> public bool Equals(sPixel pixel) => pixel._argbBytes == this._argbBytes;
/// <summary> /// Weighted interpolation of four <see cref="sPixel"/> instances. /// </summary> /// <param name="pixel1">The first instance.</param> /// <param name="pixel2">The second instance.</param> /// <param name="pixel3">The third instance.</param> /// <param name="pixel4">The fourth instance.</param> /// <param name="quantifier1">The quantifier for the first instance.</param> /// <param name="quantifier2">The quantifier for the second instance.</param> /// <param name="quantifier3">The quantifier for the third instance.</param> /// <param name="quantifier4">The quantifier for the fourth instance.</param> /// <returns>A new instance from the interpolated components.</returns> public static sPixel Interpolate( sPixel pixel1, sPixel pixel2, sPixel pixel3, sPixel pixel4, byte quantifier1, byte quantifier2, byte quantifier3, byte quantifier4) { var total = (UInt16)(quantifier1 + quantifier2 + quantifier3 + quantifier4); return (new sPixel( (byte) ((pixel1.Red * quantifier1 + pixel2.Red * quantifier2 + pixel3.Red * quantifier3 + pixel4.Red * quantifier4) / total), (byte) ((pixel1.Green * quantifier1 + pixel2.Green * quantifier2 + pixel3.Green * quantifier3 + pixel4.Green * quantifier4) / total), (byte) ((pixel1.Blue * quantifier1 + pixel2.Blue * quantifier2 + pixel3.Blue * quantifier3 + pixel4.Blue * quantifier4) / total), (byte) ((pixel1.Alpha * quantifier1 + pixel2.Alpha * quantifier2 + pixel3.Alpha * quantifier3 + pixel4.Alpha * quantifier4) / total) )); }
/// <summary> /// Determines whether this instance is not like the specified <see cref="sPixel"/> instance. /// </summary> /// <param name="pixel">The instance to compare to.</param> /// <returns> /// <c>true</c> if the specified instance is not alike; otherwise, <c>false</c>. /// </returns> public bool IsNotLike(sPixel pixel) { return (!this.IsLike(pixel)); }
/// <summary> /// Determines whether the specified <see cref="sPixel"/> instance is similar to this instance. /// </summary> /// <param name="pixel">The instance to compare to.</param> /// <returns> /// <c>true</c> if the specified instance is alike; otherwise, <c>false</c>. /// </returns> public bool IsLike(sPixel pixel) { if (!AllowThresholds) return (this == pixel); var delta = this.Luminance - pixel.Luminance; if (delta.Abs() > _LUMINANCE_TRIGGER) return false; delta = this.ChrominanceV - pixel.ChrominanceV; if (delta.Abs() > _CHROMA_V_TRIGGER) return false; delta = this.ChrominanceU - pixel.ChrominanceU; return (delta.Abs() <= _CHROMA_U_TRIGGER); }
/// <summary> /// Interpolates two <see cref="sPixel"/> instances. /// </summary> /// <param name="pixel1">The first pixel instance.</param> /// <param name="pixel2">The second pixel instance.</param> /// <returns>A new instance with the interpolated color values.</returns> public static sPixel Interpolate(sPixel pixel1, sPixel pixel2) { return (new sPixel( (byte)((pixel1.Red + pixel2.Red) >> 1), (byte)((pixel1.Green + pixel2.Green) >> 1), (byte)((pixel1.Blue + pixel2.Blue) >> 1), (byte)((pixel1.Alpha + pixel2.Alpha) >> 1) )); }
internal void SetPixel(int x, int y, sPixel value) { var width = this._width; var height = this._height; if (x < width && y < height && x >= 0 && y >= 0) this._imageData[y * width + x] = value; }
/// <summary> /// Interpolates four <see cref="sPixel"/> instances. /// </summary> /// <param name="pixel1">The first pixel instance.</param> /// <param name="pixel2">The second pixel instance.</param> /// <param name="pixel3">The third pixel instance.</param> /// <param name="pixel4">The fourth pixel instance.</param> /// <returns>A new instance with the interpolated color values.</returns> public static sPixel Interpolate(sPixel pixel1, sPixel pixel2, sPixel pixel3, sPixel pixel4) { return (new sPixel( (byte)((pixel1.Red + pixel2.Red + pixel3.Red + pixel4.Red) >> 2), (byte)((pixel1.Green + pixel2.Green + pixel3.Green + pixel4.Green) >> 2), (byte)((pixel1.Blue + pixel2.Blue + pixel3.Blue + pixel4.Blue) >> 2), (byte)((pixel1.Alpha + pixel2.Alpha + pixel3.Alpha + pixel4.Alpha) >> 2) )); }
/// <summary> /// Fills the image with the specified pixel. /// </summary> /// <param name="pixel">The pixel instance.</param> public void Fill(sPixel pixel) { #if !NET35 Parallel.For(0, this._imageData.LongLength, offset => this._imageData[offset] = pixel); #else for (var offset = 0; offset < this._imageData.LongLength; offset++) this._imageData[offset] = pixel; #endif }