/// <summary>
        /// Extract the depth image and create a mask
        /// </summary>
        /// <param name="depthInfo">The depth info</param>
        /// <param name="y">The current line in the depth and color map</param>
        private void WritePlayersMask(DepthImageFrameInfo depthInfo, int y)
        {
            for (int x = 0; x < depthInfo.Width; ++x)
            {
                // calculate index into depth array
                int depthIndex = x + (y * depthInfo.Width);

                short depthPixel = depthInfo.FrameData[depthIndex];

                int player = depthPixel & DepthImageFrame.PlayerIndexBitmask;

                // if we're tracking a player for the current pixel, do green screen
                if (player > 0)
                {
                    // retrieve the depth to color mapping for the current depth pixel
                    ColorImagePoint colorImagePoint =
                        _colorCoordinates[depthIndex];

                    // scale color coordinates to depth resolution
                    int colorInDepthX = colorImagePoint.X /
                                        depthInfo.ColorToDepthDivisor;
                    int colorInDepthY = colorImagePoint.Y /
                                        depthInfo.ColorToDepthDivisor;

                    // make sure the depth pixel maps to a valid point in color space
                    // check y > 0 and y < depthHeight to make sure we don't write outside of the array
                    // check x > 0 instead of >= 0 since to fill gaps we set opaque current pixel plus the one to the left
                    // because of how the sensor works it is more correct to do it this way than to set to the right
                    if (colorInDepthX > 0 && colorInDepthX < depthInfo.Width &&
                        colorInDepthY >= 0 &&
                        colorInDepthY < depthInfo.Height)
                    {
                        // calculate index into the green screen pixel array
                        int greenScreenIndex = colorInDepthX +
                                               (colorInDepthY * depthInfo.Width);

                        // set opaque
                        _greenScreenPixelData[greenScreenIndex] =
                            OpaquePixelValue;

                        // compensate for depth/color not corresponding exactly by setting the pixel
                        // to the left to opaque as well
                        _greenScreenPixelData[greenScreenIndex - 1] =
                            OpaquePixelValue;
                    }
                }
            }

            if (_playerOpacityMaskImage == null)
            {
                _playerOpacityMaskImage = new WriteableBitmap(
                    depthInfo.Width,
                    depthInfo.Height,
                    96,
                    96,
                    PixelFormats.Bgra32,
                    null);
            }

            _playerOpacityMaskImage.WritePixels(
                new Int32Rect(0, 0, depthInfo.Width, depthInfo.Height),
                _greenScreenPixelData,
                depthInfo.Width * ((_playerOpacityMaskImage.Format.BitsPerPixel + 7) / 8), 0);
        }
        /// <summary>
        /// Do the image composition
        /// </summary>
        /// <param name="tuple">The depth and color information</param>
        /// <param name="image">The background image</param>
        private void Merge(Tuple <DepthImageFrameInfo, ColorImageFrameInfo> tuple, BitmapSource image)
        {
            //No background
            if (image == null)
            {
                return;
            }

            DepthImageFrameInfo depthInfo = tuple.Item1;
            ColorImageFrameInfo colorInfo = tuple.Item2;

            //Initiate buffer
            if (_greenScreenPixelData.Length != depthInfo.DepthStreamFramePixelDataLength)
            {
                _greenScreenPixelData = new int[depthInfo.DepthStreamFramePixelDataLength];
            }
            Array.Clear(_greenScreenPixelData, 0, _greenScreenPixelData.Length);

            //Initiate buffer
            if (_colorCoordinates.Length != depthInfo.DepthStreamFramePixelDataLength)
            {
                _colorCoordinates = new ColorImagePoint[depthInfo.DepthStreamFramePixelDataLength];
            }
            Array.Clear(_colorCoordinates, 0, _colorCoordinates.Length);

            _kinectManager.MapDepthFrameToColorFrame(
                depthInfo.Format,
                depthInfo.FrameData,
                colorInfo.Format,
                _colorCoordinates);

            // loop over each row and column of the depth
            for (int y = 0; y < depthInfo.Height; ++y)
            {
                WritePlayersMask(depthInfo, y);
            }

            WriteColorPixels(colorInfo);


            //Use the bigger image as the size for the resulting picture
            int width  = Math.Max(colorInfo.Width, image.PixelWidth);
            int height = Math.Max(colorInfo.Height, image.PixelHeight);

            // create a render target that we'll render our images to
            var renderBitmap = new RenderTargetBitmap(width, height,
                                                      96.0, 96.0, PixelFormats.Pbgra32);


            var imageBrushSource = new ImageBrush
            {
                ImageSource = image,
                Stretch     = Stretch.Fill,
                TileMode    = TileMode.None,
                AlignmentX  = AlignmentX.Left,
                AlignmentY  = AlignmentY.Top,
                Opacity     = 1,
            };
            var imageBrushMask = new ImageBrush
            {
                ImageSource = _playerOpacityMaskImage,
                Stretch     = Stretch.UniformToFill,
                TileMode    = TileMode.None,
                AlignmentX  = AlignmentX.Left,
                AlignmentY  = AlignmentY.Top,
                Opacity     = 1,
            };

            var imageBrushPlayer = new ImageBrush
            {
                ImageSource = _colorBitmap,
                Stretch     = Stretch.UniformToFill,
                TileMode    = TileMode.None,
                AlignmentX  = AlignmentX.Left,
                AlignmentY  = AlignmentY.Top,
                Opacity     = 1,
            };


            var drawingVisual = new DrawingVisual();

            //Compose images
            using (DrawingContext dc = drawingVisual.RenderOpen())
            {
                dc.DrawRectangle(imageBrushSource, null /* no pen */,
                                 new Rect(0, 0, width, height));
                dc.PushOpacityMask(imageBrushMask);
                dc.DrawRectangle(imageBrushPlayer, null /* no pen */,
                                 new Rect(0, 0, width,
                                          height));
            }
            var result = new RenderTargetBitmap(width,
                                                height,
                                                renderBitmap.DpiX, renderBitmap.DpiY,
                                                renderBitmap.Format);

            result.Render(drawingVisual);

            //Make it thread context free
            result.Freeze();

            //broadcast the result
            _resultBlock.SendAsync(result);
        }