/// <summary> /// Requests pixels from the ChainedCustomBitmapSource. /// </summary> /// <param name="sourceRect"> /// The rectangle of pixels being requested. /// </param> /// <param name="stride"> /// The stride of the destination buffer. /// </param> /// <param name="bufferSize"> /// The size of the destination buffer. /// </param> /// <param name="buffer"> /// The destination buffer. /// </param> /// <remarks> /// Converts the contents of the source bitmap into a grayscale /// color scheme. /// /// The algorithm is taken from here: /// http://en.wikipedia.org/wiki/Grayscale /// </remarks> protected override void CopyPixelsCore(Int32Rect sourceRect, int stride, int bufferSize, IntPtr buffer) { BitmapSource source = Source; if (source != null) { // First defer to the base implementation, which will fill in // the buffer from the source and convert the pixel format as // needed. base.CopyPixelsCore(sourceRect, stride, bufferSize, buffer); // The buffer has been filled with Bgr32 or Bgra32 pixels. // Now process those pixels into grayscale. Ignore the // alpha channel. // // Note: if this buffer pointer came from a managed array, the // array has already been pinned. unsafe { byte *pBytes = (byte *)buffer.ToPointer(); for (int y = 0; y < sourceRect.Height; y++) { Bgra32Pixel *pPixel = (Bgra32Pixel *)pBytes; for (int x = 0; x < sourceRect.Width; x++) { // Get the linear color space values of this pixel. Color c = Color.FromRgb(pPixel->Red, pPixel->Green, pPixel->Blue); float red = c.ScR; float green = c.ScG; float blue = c.ScB; // Calculate the grayscale equivalent, taking into account // the sensitivity of the human eye to the different primary // colors (less sensitive to blue, more to green). float gray = red * 0.30f + green * 0.59f + blue * 0.11f; Color cGray = Color.FromScRgb(1.0f, gray, gray, gray); // Write sRGB (non-linear) since it is implied by // the pixel format we chose. pPixel->Red = cGray.R; pPixel->Green = cGray.G; pPixel->Blue = cGray.B; pPixel++; } pBytes += stride; } } } }
/// <summary> /// Requests pixels from the ChainedCustomBitmapSource. /// </summary> /// <param name="sourceRect"> /// The rectangle of pixels being requested. /// </param> /// <param name="stride"> /// The stride of the destination buffer. /// </param> /// <param name="bufferSize"> /// The size of the destination buffer. /// </param> /// <param name="buffer"> /// The destination buffer. /// </param> /// <remarks> /// Converts the contents of the source bitmap into a sepia color /// scheme. /// /// The algorithm is taken from here: /// http://msdn.microsoft.com/en-us/magazine/cc163866.aspx /// </remarks> protected override void CopyPixelsCore(Int32Rect sourceRect, int stride, int bufferSize, IntPtr buffer) { BitmapSource source = Source; if (source != null) { // First defer to the base implementation, which will fill in // the buffer from the source and convert the pixel format as // needed. base.CopyPixelsCore(sourceRect, stride, bufferSize, buffer); // The buffer has been filled with Bgr32 or Bgra32 pixels. // Now process those pixels into a sepia tint. Ignore the // alpha channel. // // Note: if this buffer pointer came from a managed array, the // array has already been pinned. unsafe { byte *pBytes = (byte *)buffer.ToPointer(); for (int y = 0; y < sourceRect.Height; y++) { Bgra32Pixel *pPixel = (Bgra32Pixel *)pBytes; for (int x = 0; x < sourceRect.Width; x++) { // Get the linear color space values of this pixel. Color c = Color.FromRgb(pPixel->Red, pPixel->Green, pPixel->Blue); float red = c.ScR; float green = c.ScG; float blue = c.ScB; Color cSepia = Color.FromScRgb(1.0f, red * 0.393f + green * 0.769f + blue * 0.189f, red * 0.349f + green * 0.686f + blue * 0.168f, red * 0.272f + green * 0.534f + blue * 0.131f); // Write sRGB (non-linear) since it is implied by // the pixel format we chose. pPixel->Red = cSepia.R; pPixel->Green = cSepia.G; pPixel->Blue = cSepia.B; pPixel++; } pBytes += stride; } } } }
/// <summary> /// Requests pixels from the ChainedCustomBitmapSource. /// </summary> /// <param name="sourceRect"> /// The rectangle of pixels being requested. /// </param> /// <param name="stride"> /// The stride of the destination buffer. /// </param> /// <param name="bufferSize"> /// The size of the destination buffer. /// </param> /// <param name="buffer"> /// The destination buffer. /// </param> /// <remarks> /// The default implementation simply calls CopyPixels on the /// source. /// </remarks> protected override void CopyPixelsCore(Int32Rect sourceRect, int stride, int bufferSize, IntPtr buffer) { BitmapSource source = Source; if (source != null) { // First defer to the base implementation, which will fill in // the buffer from the source and convert the pixel format as // needed. base.CopyPixelsCore(sourceRect, stride, bufferSize, buffer); // Also fetch the color of the upper-left corner (0,0) if the // transparent color has not been specified. Color solidColor; if (SelectedColor == null) { solidColor = Colors.Black; } else { solidColor = SelectedColor.Value; } // The buffer has been filled with Bgr32 or Bgra32 pixels. // Now process these pixels and set the alpha channel to 0 for // pixels that match the color key. Leave the other pixels // alone. // // Note: if this buffer pointer came from a managed array, the // array has already been pinned. unsafe { byte *pBytes = (byte *)buffer.ToPointer(); for (int y = 0; y < sourceRect.Height; y++) { Bgra32Pixel *pPixel = (Bgra32Pixel *)pBytes; for (int x = 0; x < sourceRect.Width; x++) { pPixel->Red = solidColor.R; pPixel->Blue = solidColor.B; pPixel->Green = solidColor.G; pPixel++; } pBytes += stride; } } } }
/// <summary> /// Requests pixels from the ChainedCustomBitmapSource. /// </summary> /// <param name="sourceRect"> /// The rectangle of pixels being requested. /// </param> /// <param name="stride"> /// The stride of the destination buffer. /// </param> /// <param name="bufferSize"> /// The size of the destination buffer. /// </param> /// <param name="buffer"> /// The destination buffer. /// </param> /// <remarks> /// The default implementation simply calls CopyPixels on the /// source. /// </remarks> protected override void CopyPixelsCore(Int32Rect sourceRect, int stride, int bufferSize, IntPtr buffer) { BitmapSource source = Source; if (source != null) { // First defer to the base implementation, which will fill in // the buffer from the source and convert the pixel format as // needed. base.CopyPixelsCore(sourceRect, stride, bufferSize, buffer); // Also fetch the color of the upper-left corner (0,0) if the // transparent color has not been specified. Color transparentColor; if (TransparentColor == null) { uint[] firstPixel = new uint[1]; unsafe { fixed(uint *pFirstPixel = firstPixel) { base.CopyPixelsCore(new Int32Rect(0, 0, 1, 1), 4, 4, new IntPtr(pFirstPixel)); Bgra32Pixel *pBgraPixel = (Bgra32Pixel *)pFirstPixel; transparentColor = Color.FromRgb(pBgraPixel->Red, pBgraPixel->Green, pBgraPixel->Blue); } } } else { transparentColor = TransparentColor.Value; } // The buffer has been filled with Bgr32 or Bgra32 pixels. // Now process these pixels and set the alpha channel to 0 for // pixels that match the color key. Leave the other pixels // alone. // // Note: if this buffer pointer came from a managed array, the // array has already been pinned. unsafe { byte *pBytes = (byte *)buffer.ToPointer(); for (int y = 0; y < sourceRect.Height; y++) { Bgra32Pixel *pPixel = (Bgra32Pixel *)pBytes; for (int x = 0; x < sourceRect.Width; x++) { if (pPixel->Red == transparentColor.R && pPixel->Green == transparentColor.G && pPixel->Blue == transparentColor.B) { pPixel->Alpha = 0x00; } pPixel++; } pBytes += stride; } } } }
/// <summary> /// Requests pixels from the ChainedCustomBitmapSource. /// </summary> /// <param name="sourceRect"> /// The rectangle of pixels being requested. /// </param> /// <param name="stride"> /// The stride of the destination buffer. /// </param> /// <param name="bufferSize"> /// The size of the destination buffer. /// </param> /// <param name="buffer"> /// The destination buffer. /// </param> /// <remarks> /// Converts the contents of the source bitmap into a grayscale /// color scheme. /// /// The algorithm is taken from here: /// http://en.wikipedia.org/wiki/Grayscale /// </remarks> protected override void CopyPixelsCore(Int32Rect sourceRect, int stride, int bufferSize, IntPtr buffer) { BitmapSource source = Source; if (source != null) { // First defer to the base implementation, which will fill in // the buffer from the source and convert the pixel format as // needed. base.CopyPixelsCore(sourceRect, stride, bufferSize, buffer); // The buffer has been filled with Bgr32 or Bgra32 pixels. // Now process those pixels into grayscale. Ignore the // alpha channel. // // Note: if this buffer pointer came from a managed array, the // array has already been pinned. unsafe { byte *pBytes = (byte *)buffer.ToPointer(); for (int y = 0; y < sourceRect.Height; y++) { Bgra32Pixel *pPixel = (Bgra32Pixel *)pBytes; for (int x = 0; x < sourceRect.Width; x++) { System.Diagnostics.Debug.Assert(pPixel->Red == pPixel->Green); System.Diagnostics.Debug.Assert(pPixel->Red == pPixel->Blue); float gray; if (pPixel->Red < 16) { gray = 0.0000f; } else if (pPixel->Red < 32) { gray = 0.0667f; } else if (pPixel->Red < 48) { gray = 0.1333f; } else if (pPixel->Red < 64) { gray = 0.2000f; } else if (pPixel->Red < 80) { gray = 0.2667f; } else if (pPixel->Red < 96) { gray = 0.3333f; } else if (pPixel->Red < 112) { gray = 0.4000f; } else if (pPixel->Red < 128) { gray = 0.4667f; } else if (pPixel->Red < 144) { gray = 0.5333f; } else if (pPixel->Red < 160) { gray = 0.6000f; } else if (pPixel->Red < 176) { gray = 0.6667f; } else if (pPixel->Red < 192) { gray = 0.7333f; } else if (pPixel->Red < 208) { gray = 0.8000f; } else if (pPixel->Red < 224) { gray = 0.8667f; } else if (pPixel->Red < 240) { gray = 0.9333f; } else { gray = 1f; } Color cGray = Color.FromScRgb(1.0f, gray, gray, gray); // Write sRGB (non-linear) since it is implied by // the pixel format we chose. pPixel->Red = cGray.R; pPixel->Green = cGray.G; pPixel->Blue = cGray.B; pPixel++; } pBytes += stride; } } } }