/// <summary>
        /// Overlays pixel data from another <see cref="BitmapBuffer"/>, with alpha blending.
        /// </summary>
        /// <param name="x">
        /// The x-coordinate where to begin writing in this <see cref="BitmapBuffer"/>.</param>
        /// <param name="y">
        /// The y-coordinate where to begin writing in this <see cref="BitmapBuffer"/>.</param>
        /// <param name="source">
        /// Another <see cref="BitmapBuffer"/> containing the rectangle to overlay.</param>
        /// <param name="bounds">
        /// The pixel rectangle within the specified <paramref name="source"/> to overlay.</param>
        /// <param name="color">
        /// The <see cref="Color"/> to substitute for all <paramref name="source"/> pixels.</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="source"/> is a null reference.</exception>
        /// <remarks><para>
        /// <b>Overlay</b> blends all <see cref="Pixels"/> elements within the specified <paramref
        /// name="bounds"/> of the specified <paramref name="source"/> buffer with the corresponding
        /// <see cref="Pixels"/> elements in this <see cref="BitmapBuffer"/>, starting with the
        /// specified <paramref name="x"/> and <paramref name="y"/> coordinates.
        /// </para><para>
        /// <b>Overlay</b> calls <see cref="BitmapUtility.BlendPbgra32"/> to perform alpha blending
        /// between the specified <paramref name="source"/> buffer (acting as the overlay) and this
        /// <see cref="BitmapBuffer"/> (acting as the blending target). No coordinate checking is
        /// performed.
        /// </para><para>
        /// <b>Overlay</b> substitutes the specified <paramref name="color"/> for the actual color
        /// channels of each <paramref name="source"/> pixel, while using its alpha channel to
        /// govern alpha blending with the corresponding <see cref="Pixels"/> element. The alpha
        /// channel of the specified <paramref name="color"/> is ignored.</para></remarks>

        public void Overlay(int x, int y, BitmapBuffer source, RectI bounds, Color color)
        {
            if (source == null)
            {
                ThrowHelper.ThrowArgumentNullException("source");
            }

            int sourceOffset = bounds.X + source._size.Width * bounds.Y;
            int targetOffset = x + _size.Width * y;

            for (int dy = 0; dy < bounds.Height; dy++)
            {
                for (int dx = 0; dx < bounds.Width; dx++)
                {
                    uint p0 = source._pixels[sourceOffset + dx];
                    uint p1 = _pixels[targetOffset + dx];

                    // multiply color channels with source alpha
                    color.A = (byte)(p0 >> 24);
                    p0      = BitmapUtility.ColorToPbgra32(color);

                    _pixels[targetOffset + dx] = BitmapUtility.BlendPbgra32(p0, p1);
                }

                sourceOffset += source._size.Width;
                targetOffset += _size.Width;
            }
        }
        /// <summary>
        /// Blends the specified pixel in the <see cref="BitmapBuffer"/> with the specified <see
        /// cref="Color"/>.</summary>
        /// <param name="x">
        /// The x-coordinate of the pixel to blend with <paramref name="color"/>.</param>
        /// <param name="y">
        /// The y-coordinate of the pixel to blend with <paramref name="color"/>.</param>
        /// <param name="color">
        /// The <see cref="Color"/> to blend with the pixel at the specified location in the <see
        /// cref="BitmapBuffer"/>.</param>
        /// <remarks><para>
        /// <b>BlendPixel</b> blends the <see cref="Pixels"/> element at the specified <paramref
        /// name="x"/> and <paramref name="y"/> coordinates with the <see
        /// cref="PixelFormats.Pbgra32"/> representation of the specified <paramref name="color"/>.
        /// </para><para>
        /// <b>BlendPixel</b> calls <see cref="BitmapUtility.BlendPbgra32"/> to perform alpha
        /// blending between the specified <paramref name="color"/> (acting as the overlay) and this
        /// <see cref="BitmapBuffer"/> (acting as the blending target). No coordinate checking is
        /// performed.</para></remarks>

        public void BlendPixel(int x, int y, Color color)
        {
            uint value = BitmapUtility.ColorToPbgra32(color);
            int  i     = x + _size.Width * y;

            _pixels[i] = BitmapUtility.BlendPbgra32(value, _pixels[i]);
        }
        /// <overloads>
        /// Overlays pixel data from another <see cref="BitmapBuffer"/>.</overloads>
        /// <summary>
        /// Overlays pixel data from another <see cref="BitmapBuffer"/>, with alpha blending.
        /// </summary>
        /// <param name="x">
        /// The x-coordinate where to begin writing in this <see cref="BitmapBuffer"/>.</param>
        /// <param name="y">
        /// The y-coordinate where to begin writing in this <see cref="BitmapBuffer"/>.</param>
        /// <param name="source">
        /// Another <see cref="BitmapBuffer"/> containing the rectangle to overlay.</param>
        /// <param name="bounds">
        /// The pixel rectangle within the specified <paramref name="source"/> to overlay.</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="source"/> is a null reference.</exception>
        /// <remarks><para>
        /// <b>Overlay</b> blends all <see cref="Pixels"/> elements within the specified <paramref
        /// name="bounds"/> of the specified <paramref name="source"/> buffer with the corresponding
        /// <see cref="Pixels"/> elements in this <see cref="BitmapBuffer"/>, starting with the
        /// specified <paramref name="x"/> and <paramref name="y"/> coordinates.
        /// </para><para>
        /// <b>Overlay</b> calls <see cref="BitmapUtility.BlendPbgra32"/> to perform alpha blending
        /// between the specified <paramref name="source"/> buffer (acting as the overlay) and this
        /// <see cref="BitmapBuffer"/> (acting as the blending target). No coordinate checking is
        /// performed.</para></remarks>

        public void Overlay(int x, int y, BitmapBuffer source, RectI bounds)
        {
            if (source == null)
            {
                ThrowHelper.ThrowArgumentNullException("source");
            }

            int sourceOffset = bounds.X + source._size.Width * bounds.Y;
            int targetOffset = x + _size.Width * y;

            for (int dy = 0; dy < bounds.Height; dy++)
            {
                for (int dx = 0; dx < bounds.Width; dx++)
                {
                    uint p0 = source._pixels[sourceOffset + dx];
                    uint p1 = _pixels[targetOffset + dx];
                    _pixels[targetOffset + dx] = BitmapUtility.BlendPbgra32(p0, p1);
                }

                sourceOffset += source._size.Width;
                targetOffset += _size.Width;
            }
        }
 public void BlendPbgra32()
 {
     Assert.AreEqual(0x12345678, BitmapUtility.BlendPbgra32(0x00ABCDEF, 0x12345678));
     Assert.AreEqual(0xFFABCDEF, BitmapUtility.BlendPbgra32(0xFFABCDEF, 0x12345678));
     Assert.AreEqual(0xAF485058, BitmapUtility.BlendPbgra32(0x7F203040, 0x60504030));
 }