/// <summary>
    /// Copies (blits) the pixels from the WriteableBitmap source to the destination WriteableBitmap (this).
    /// </summary>
    /// <param name="destContext">The destination WriteableBitmap.</param>
    /// <param name="destRect">The rectangle that defines the destination region.</param>
    /// <param name="srcContext">The source WriteableBitmap.</param>
    /// <param name="sourceRect">The rectangle that will be copied from the source to the destination.</param>
    /// <param name="color">If not Colors.White, will tint the source image. A partially transparent color and the image will be drawn partially transparent. If the BlendMode is ColorKeying, this color will be used as color key to mask all pixels with this value out.</param>
    /// <param name="blendMode">The blending mode <see cref="BlendMode"/>.</param>
    public static void Blit(this BitmapContext destContext, RectInt destRect, BitmapContext srcContext, RectInt sourceRect, Color color, BlendMode blendMode)
    {
      if (color.A == 0)
      {
        return;
      }
      int dw = destRect.w;
      int dh = destRect.h;

      int sourceWidth = srcContext.Width;
      int dpw = destContext.Width;
      int dph = destContext.Height;
      var intersect = RectInt.Intersect(new RectInt(0, 0, dpw, dph), destRect);
      if (intersect.IsEmpty)
      {
        return;
      }

      var sourcePixels = srcContext.Pixels;
      var destPixels = destContext.Pixels;
      int sourceLength = srcContext.Length;
      int px = destRect.x;
      int py = destRect.y;
      int y;
      double jj;
      int sr = 0;
      int sg = 0;
      int sb = 0;
      int sa = 0;
      int ca = color.A;
      int cr = color.R;
      int cg = color.G;
      int cb = color.B;
      bool tinted = color != Colors.White;
      var sw = sourceRect.w;
      var sdx = sourceRect.w / (double)destRect.w;
      var sdy = sourceRect.h / (double)destRect.h;
      int sourceStartX = sourceRect.x;
      int sourceStartY = sourceRect.y;
      int lastii, lastjj;
      lastii = -1;
      lastjj = -1;
      jj = sourceStartY;
      y = py;
      for (int j = 0; j < dh; j++)
      {
        if (y >= 0 && y < dph)
        {
          double ii = sourceStartX;
          var idx = px + y * dpw;
          var x = px;
          var sourcePixel = sourcePixels[0];

          // Scanline BlockCopy is much faster (3.5x) if no tinting and blending is needed,
          // even for smaller sprites like the 32x32 particles. 
          int sourceIdx;
          if (blendMode == BlendMode.None && !tinted)
          {
            sourceIdx = (int)ii + (int)jj * sourceWidth;
            var offset = x < 0 ? -x : 0;
            var xx = x + offset;
            var wx = sourceWidth - offset;
            var len = xx + wx < dpw ? wx : dpw - xx;
            if (len > sw) len = sw;
            if (len > dw) len = dw;
            BitmapContext.BlockCopy(srcContext, (sourceIdx + offset) * 4, destContext, (idx + offset) * 4, len * 4);
          }

          // Pixel by pixel copying
          else
          {
            for (int i = 0; i < dw; i++)
            {
              if (x >= 0 && x < dpw)
              {
                if ((int)ii != lastii || (int)jj != lastjj)
                {
                  sourceIdx = (int)ii + (int)jj * sourceWidth;
                  if (sourceIdx >= 0 && sourceIdx < sourceLength)
                  {
                    sourcePixel = sourcePixels[sourceIdx];
                    sa = ((sourcePixel >> 24) & 0xff);
                    sr = ((sourcePixel >> 16) & 0xff);
                    sg = ((sourcePixel >> 8) & 0xff);
                    sb = ((sourcePixel) & 0xff);
                    if (tinted && sa != 0)
                    {
                      sa = (((sa * ca) * 0x8081) >> 23);
                      sr = ((((((sr * cr) * 0x8081) >> 23) * ca) * 0x8081) >> 23);
                      sg = ((((((sg * cg) * 0x8081) >> 23) * ca) * 0x8081) >> 23);
                      sb = ((((((sb * cb) * 0x8081) >> 23) * ca) * 0x8081) >> 23);
                      sourcePixel = (sa << 24) | (sr << 16) | (sg << 8) | sb;
                    }
                  }
                  else
                  {
                    sa = 0;
                  }
                }
                if (blendMode == BlendMode.None)
                {
                  destPixels[idx] = sourcePixel;
                }
                else if (blendMode == BlendMode.ColorKeying)
                {
                  sr = ((sourcePixel >> 16) & 0xff);
                  sg = ((sourcePixel >> 8) & 0xff);
                  sb = ((sourcePixel) & 0xff);

                  if (sr != color.R || sg != color.G || sb != color.B)
                  {
                    destPixels[idx] = sourcePixel;
                  }

                }
                else
                {
                  int dr;
                  int dg;
                  int db;
                  int da;
                  if (blendMode == BlendMode.Mask)
                  {
                    int destPixel = destPixels[idx];
                    da = ((destPixel >> 24) & 0xff);
                    dr = ((destPixel >> 16) & 0xff);
                    dg = ((destPixel >> 8) & 0xff);
                    db = ((destPixel) & 0xff);
                    destPixel = ((((da * sa) * 0x8081) >> 23) << 24) |
                                ((((dr * sa) * 0x8081) >> 23) << 16) |
                                ((((dg * sa) * 0x8081) >> 23) << 8) |
                                ((((db * sa) * 0x8081) >> 23));
                    destPixels[idx] = destPixel;
                  }
                  else if (sa > 0)
                  {
                    int destPixel = destPixels[idx];
                    da = ((destPixel >> 24) & 0xff);
                    if ((sa == 255 || da == 0) &&
                        blendMode != BlendMode.Additive
                        && blendMode != BlendMode.Subtractive
                        && blendMode != BlendMode.Multiply
                      )
                    {
                      destPixels[idx] = sourcePixel;
                    }
                    else
                    {
                      dr = ((destPixel >> 16) & 0xff);
                      dg = ((destPixel >> 8) & 0xff);
                      db = ((destPixel) & 0xff);
                      if (blendMode == BlendMode.Alpha)
                      {
                        destPixel = ((sa + (((da * (255 - sa)) * 0x8081) >> 23)) << 24) |
                                    ((sr + (((dr * (255 - sa)) * 0x8081) >> 23)) << 16) |
                                    ((sg + (((dg * (255 - sa)) * 0x8081) >> 23)) << 8) |
                                    ((sb + (((db * (255 - sa)) * 0x8081) >> 23)));
                      }
                      else if (blendMode == BlendMode.Additive)
                      {
                        int a = (255 <= sa + da) ? 255 : (sa + da);
                        destPixel = (a << 24) |
                                    (((a <= sr + dr) ? a : (sr + dr)) << 16) |
                                    (((a <= sg + dg) ? a : (sg + dg)) << 8) |
                                    (((a <= sb + db) ? a : (sb + db)));
                      }
                      else if (blendMode == BlendMode.Subtractive)
                      {
                        int a = da;
                        destPixel = (a << 24) |
                                    (((sr >= dr) ? 0 : (sr - dr)) << 16) |
                                    (((sg >= dg) ? 0 : (sg - dg)) << 8) |
                                    (((sb >= db) ? 0 : (sb - db)));
                      }
                      else if (blendMode == BlendMode.Multiply)
                      {
                        // Faster than a division like (s * d) / 255 are 2 shifts and 2 adds
                        int ta = (sa * da) + 128;
                        int tr = (sr * dr) + 128;
                        int tg = (sg * dg) + 128;
                        int tb = (sb * db) + 128;

                        int ba = ((ta >> 8) + ta) >> 8;
                        int br = ((tr >> 8) + tr) >> 8;
                        int bg = ((tg >> 8) + tg) >> 8;
                        int bb = ((tb >> 8) + tb) >> 8;

                        destPixel = (ba << 24) |
                                    ((ba <= br ? ba : br) << 16) |
                                    ((ba <= bg ? ba : bg) << 8) |
                                    ((ba <= bb ? ba : bb));
                      }

                      destPixels[idx] = destPixel;
                    }
                  }
                }
              }
              x++;
              idx++;
              ii += sdx;
            }
          }
        }
        jj += sdy;
        y++;
      }
    }
    /// <summary>
    /// Creates a new resized bitmap.
    /// </summary>
    /// <param name="srcContext">The source context.</param>
    /// <param name="widthSource">The width of the source pixels.</param>
    /// <param name="heightSource">The height of the source pixels.</param>
    /// <param name="width">The new desired width.</param>
    /// <param name="height">The new desired height.</param>
    /// <param name="interpolation">The interpolation method that should be used.</param>
    /// <returns>A new bitmap that is a resized version of the input.</returns>
    public static int[] Resize(BitmapContext srcContext, int widthSource, int heightSource, int width, int height, Interpolation interpolation)
    {
      var pixels = srcContext.Pixels;
      var pd = new int[width * height];
      var xs = (float)widthSource / width;
      var ys = (float)heightSource / height;

      float sx, sy;
      int x0;
      int y0;

      // Nearest Neighbor
      switch (interpolation)
      {
        case Interpolation.NearestNeighbor:
        {
          var srcIdx = 0;
          for (var y = 0; y < height; y++)
          {
            for (var x = 0; x < width; x++)
            {
              sx = x * xs;
              sy = y * ys;
              x0 = (int)sx;
              y0 = (int)sy;

              pd[srcIdx++] = pixels[y0 * widthSource + x0];
            }
          }
        } break;
        case Interpolation.Bilinear:
        {
          var srcIdx = 0;
          for (var y = 0; y < height; y++)
          {
            for (var x = 0; x < width; x++)
            {
              sx = x * xs;
              sy = y * ys;
              x0 = (int)sx;
              y0 = (int)sy;

              // Calculate coordinates of the 4 interpolation points
              var fracx = sx - x0;
              var fracy = sy - y0;
              var ifracx = 1f - fracx;
              var ifracy = 1f - fracy;
              var x1 = x0 + 1;
              if (x1 >= widthSource)
              {
                x1 = x0;
              }
              var y1 = y0 + 1;
              if (y1 >= heightSource)
              {
                y1 = y0;
              }


              // Read source color
              var c = pixels[y0 * widthSource + x0];
              var c1A = (byte)(c >> 24);
              var c1R = (byte)(c >> 16);
              var c1G = (byte)(c >> 8);
              var c1B = (byte)(c);

              c = pixels[y0 * widthSource + x1];
              var c2A = (byte)(c >> 24);
              var c2R = (byte)(c >> 16);
              var c2G = (byte)(c >> 8);
              var c2B = (byte)(c);

              c = pixels[y1 * widthSource + x0];
              var c3A = (byte)(c >> 24);
              var c3R = (byte)(c >> 16);
              var c3G = (byte)(c >> 8);
              var c3B = (byte)(c);

              c = pixels[y1 * widthSource + x1];
              var c4A = (byte)(c >> 24);
              var c4R = (byte)(c >> 16);
              var c4G = (byte)(c >> 8);
              var c4B = (byte)(c);


              // Calculate colors
              // Alpha
              var l0 = ifracx * c1A + fracx * c2A;
              var l1 = ifracx * c3A + fracx * c4A;
              var a = (byte)(ifracy * l0 + fracy * l1);

              // Red
              l0 = ifracx * c1R * c1A + fracx * c2R * c2A;
              l1 = ifracx * c3R * c3A + fracx * c4R * c4A;
              var rf = ifracy * l0 + fracy * l1;

              // Green
              l0 = ifracx * c1G * c1A + fracx * c2G * c2A;
              l1 = ifracx * c3G * c3A + fracx * c4G * c4A;
              var gf = ifracy * l0 + fracy * l1;

              // Blue
              l0 = ifracx * c1B * c1A + fracx * c2B * c2A;
              l1 = ifracx * c3B * c3A + fracx * c4B * c4A;
              var bf = ifracy * l0 + fracy * l1;

              // Divide by alpha
              if (a > 0)
              {
                rf = rf / a;
                gf = gf / a;
                bf = bf / a;
              }

              // Cast to byte
              var r = (byte)rf;
              var g = (byte)gf;
              var b = (byte)bf;

              // Write destination
              pd[srcIdx++] = (a << 24) | (r << 16) | (g << 8) | b;
            }
          }
        } break;
      }
      return pd;
    }
 /// <summary>
 /// Copies (blits) the pixels from the WriteableBitmap source to the destination WriteableBitmap (this).
 /// </summary>
 /// <param name="context">The destination WriteableBitmap.</param>
 /// <param name="destRect">The rectangle that defines the destination region.</param>
 /// <param name="source">The source WriteableBitmap.</param>
 /// <param name="sourceRect">The rectangle that will be copied from the source to the destination.</param>
 public static void Blit(this BitmapContext context, RectInt destRect, BitmapContext source, RectInt sourceRect)
 {
   Blit(context, destRect, source, sourceRect, Colors.White, BlendMode.Alpha);
 }
 /// <summary>
 /// Copies (blits) the pixels from the WriteableBitmap source to the destination WriteableBitmap (this).
 /// </summary>
 /// <param name="context">The destination WriteableBitmap.</param>
 /// <param name="destPosition">The destination position in the destination bitmap.</param>
 /// <param name="source">The source WriteableBitmap.</param>
 /// <param name="sourceRect">The rectangle that will be copied from the source to the destination.</param>
 /// <param name="color">If not Colors.White, will tint the source image. A partially transparent color and the image will be drawn partially transparent.</param>
 /// <param name="blendMode">The blending mode <see cref="BlendMode"/>.</param>
 public static void Blit(this BitmapContext context, PointInt destPosition, BitmapContext source, RectInt sourceRect, Color color, BlendMode blendMode)
 {
   var destRect = new RectInt(destPosition, new SizeInt(sourceRect.w, sourceRect.h));
   Blit(context, destRect, source, sourceRect, color, blendMode);
 }
        private static void DrawBonesAndJoints(IBody body, BitmapContext context, Color boneColor, Color jointColor)
        {
            foreach (var bone in BoneTypeEx.DrawnBones)
            {
                DrawBone(body, context, bone, boneColor);
            }

            System.Diagnostics.Debug.WriteLine("Angles at Left (Shoulder,Elbow) : ({0},{1})",
                body.GetAngleAt(JointTypeEx.ShoulderLeft), body.GetAngleAt(JointTypeEx.ElbowLeft));


            Color inferredJointColor = jointColor;
            inferredJointColor.A = 128;

            // Render Joints
            foreach (var joint in body.Joints.Values)
            {
                if (joint.TrackingState == TrackingState.NotTracked)
                {
                    continue;
                }

                var point = GetDepthSpacePoint(joint, body.HasMappedDepthPositions);

                context.WriteableBitmap.FillEllipseCentered(
                    (int)point.X,
                    (int)point.Y,
                    (int)_jointThickness,
                    (int)_jointThickness,
                    joint.TrackingState == TrackingState.Inferred ? inferredJointColor : jointColor);
            }
        }
        private static void DrawBone(IBody body, BitmapContext context, BoneTypeEx bone, Color color)
        {
            var startJoint = body.Joints[bone.StartJoint];
            var endJoint = body.Joints[bone.EndJoint];

            // If we can't find either of these joints, exit
            if (startJoint.TrackingState == TrackingState.NotTracked ||
                endJoint.TrackingState == TrackingState.NotTracked)
            {
                return;
            }

            // Don't draw if both points are inferred
            if (startJoint.TrackingState == TrackingState.Inferred &&
                endJoint.TrackingState == TrackingState.Inferred)
            {
                return;
            }

            // If either isn't tracked, it is "inferred"
            if (startJoint.TrackingState != TrackingState.Tracked || endJoint.TrackingState != TrackingState.Tracked)
            {
                color.A = 192;
            }

            var startPoint = GetDepthSpacePoint(startJoint, body.HasMappedDepthPositions);
            var endPoint = GetDepthSpacePoint(endJoint, body.HasMappedDepthPositions);

            context.WriteableBitmap.DrawLineAa(
                (int)startPoint.X,
                (int)startPoint.Y,
                (int)endPoint.X,
                (int)endPoint.Y,
                color);
        }
 private static void AddBodyToContext(IBody body, BitmapContext context, Color boneColor, Color jointColor)
 {
     DrawBonesAndJoints(body, context, boneColor, jointColor);
     RenderClippedEdges(body, context);
 }
    /// <summary>
    /// Draws a segment of a Cardinal spline (cubic) defined by four control points.
    /// </summary>
    /// <param name="x1">The x-coordinate of the 1st control point.</param>
    /// <param name="y1">The y-coordinate of the 1st control point.</param>
    /// <param name="x2">The x-coordinate of the 2nd control point.</param>
    /// <param name="y2">The y-coordinate of the 2nd control point.</param>
    /// <param name="x3">The x-coordinate of the 3rd control point.</param>
    /// <param name="y3">The y-coordinate of the 3rd control point.</param>
    /// <param name="x4">The x-coordinate of the 4th control point.</param>
    /// <param name="y4">The y-coordinate of the 4th control point.</param>
    /// <param name="tension">The tension of the curve defines the shape. Usually between 0 and 1. 0 would be a straight line.</param>
    /// <param name="color">The color.</param>
    /// <param name="context">The pixel context.</param>
    /// <param name="w">The width of the bitmap.</param>
    /// <param name="h">The height of the bitmap.</param> 
    static void DrawCurveSegment(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4, float tension, int color, BitmapContext context, int w, int h)
    {
      // Determine distances between controls points (bounding rect) to find the optimal stepsize
      var minX = Math.Min(x1, Math.Min(x2, Math.Min(x3, x4)));
      var minY = Math.Min(y1, Math.Min(y2, Math.Min(y3, y4)));
      var maxX = Math.Max(x1, Math.Max(x2, Math.Max(x3, x4)));
      var maxY = Math.Max(y1, Math.Max(y2, Math.Max(y3, y4)));

      // Get slope
      var lenx = maxX - minX;
      var len = maxY - minY;
      if (lenx > len)
      {
        len = lenx;
      }

      // Prevent divison by zero
      if (len == 0) return;

      // Init vars
      var step = StepFactor / len;
      int tx1 = x2;
      int ty1 = y2;

      // Calculate factors
      var sx1 = tension * (x3 - x1);
      var sy1 = tension * (y3 - y1);
      var sx2 = tension * (x4 - x2);
      var sy2 = tension * (y4 - y2);
      var ax = sx1 + sx2 + 2 * x2 - 2 * x3;
      var ay = sy1 + sy2 + 2 * y2 - 2 * y3;
      var bx = -2 * sx1 - sx2 - 3 * x2 + 3 * x3;
      var by = -2 * sy1 - sy2 - 3 * y2 + 3 * y3;

      // Interpolate
      for (var t = step; t <= 1; t += step)
      {
        var tSq = t * t;

        var tx2 = (int)(ax * tSq * t + bx * tSq + sx1 * t + x2);
        var ty2 = (int)(ay * tSq * t + @by * tSq + sy1 * t + y2);

        // Draw line
        DrawLine(context, w, h, tx1, ty1, tx2, ty2, color);
        tx1 = tx2;
        ty1 = ty2;
      }

      // Prevent rounding gap
      DrawLine(context, w, h, tx1, ty1, x3, y3, color);
    }
    /// <summary> 
    /// Draws an anti-aliased line, using an optimized version of Gupta-Sproull algorithm 
    /// From http://nokola.com/blog/post/2010/10/14/Anti-aliased-Lines-And-Optimizing-Code-for-Windows-Phone-7e28093First-Look.aspx
    /// <param name="context">The context containing the pixels as int RGBA value.</param>
    /// <param name="pixelWidth">The width of one scanline in the pixels array.</param>
    /// <param name="pixelHeight">The height of the bitmap.</param>
    /// <param name="x1">The x-coordinate of the start point.</param>
    /// <param name="y1">The y-coordinate of the start point.</param>
    /// <param name="x2">The x-coordinate of the end point.</param>
    /// <param name="y2">The y-coordinate of the end point.</param>
    /// <param name="color">The color for the line.</param>
    /// </summary> 
    public static void DrawLineAa(BitmapContext context, int pixelWidth, int pixelHeight, int x1, int y1, int x2, int y2, int color)
    {
      if ((x1 == x2) && (y1 == y2)) return; // edge case causing invDFloat to overflow, found by Shai Rubinshtein

      if (x1 < 1) x1 = 1;
      if (x1 > pixelWidth - 2) x1 = pixelWidth - 2;
      if (y1 < 1) y1 = 1;
      if (y1 > pixelHeight - 2) y1 = pixelHeight - 2;

      if (x2 < 1) x2 = 1;
      if (x2 > pixelWidth - 2) x2 = pixelWidth - 2;
      if (y2 < 1) y2 = 1;
      if (y2 > pixelHeight - 2) y2 = pixelHeight - 2;

      var addr = y1 * pixelWidth + x1;
      var dx = x2 - x1;
      var dy = y2 - y1;

      int du;
      int dv;
      int u;
      int uincr;
      int vincr;

      // Extract color
      var a = (color >> 24) & 0xFF;
      var srb = (uint)(color & 0x00FF00FF);
      var sg = (uint)((color >> 8) & 0xFF);

      // By switching to (u,v), we combine all eight octants 
      int adx = dx, ady = dy;
      if (dx < 0) adx = -dx;
      if (dy < 0) ady = -dy;

      if (adx > ady)
      {
        du = adx;
        dv = ady;
        u = x2;
        uincr = 1;
        vincr = pixelWidth;
        if (dx < 0) uincr = -uincr;
        if (dy < 0) vincr = -vincr;
      }
      else
      {
        du = ady;
        dv = adx;
        u = y2;
        uincr = pixelWidth;
        vincr = 1;
        if (dy < 0) uincr = -uincr;
        if (dx < 0) vincr = -vincr;
      }

      var uend = u + du;
      var d = (dv << 1) - du;        // Initial value as in Bresenham's 
      var incrS = dv << 1;    // &#916;d for straight increments 
      var incrD = (dv - du) << 1;    // &#916;d for diagonal increments

      var invDFloat = 1.0 / (4.0 * Math.Sqrt(du * du + dv * dv));   // Precomputed inverse denominator 
      var invD2DuFloat = 0.75 - 2.0 * (du * invDFloat);   // Precomputed constant

      const int PrecisionShift = 10; // result distance should be from 0 to 1 << PRECISION_SHIFT, mapping to a range of 0..1 
      const int PrecisionMultiplier = 1 << PrecisionShift;
      var invD = (int)(invDFloat * PrecisionMultiplier);
      var invD2Du = (int)(invD2DuFloat * PrecisionMultiplier * a);
      var zeroDot75 = (int)(0.75 * PrecisionMultiplier * a);

      var invDMulAlpha = invD * a;
      var duMulInvD = du * invDMulAlpha; // used to help optimize twovdu * invD 
      var dMulInvD = d * invDMulAlpha; // used to help optimize twovdu * invD 
      //int twovdu = 0;    // Numerator of distance; starts at 0 
      var twovduMulInvD = 0; // since twovdu == 0 
      var incrSMulInvD = incrS * invDMulAlpha;
      var incrDMulInvD = incrD * invDMulAlpha;

      do
      {
        AlphaBlendNormalOnPremultiplied(context, addr, (zeroDot75 - twovduMulInvD) >> PrecisionShift, srb, sg);
        AlphaBlendNormalOnPremultiplied(context, addr + vincr, (invD2Du + twovduMulInvD) >> PrecisionShift, srb, sg);
        AlphaBlendNormalOnPremultiplied(context, addr - vincr, (invD2Du - twovduMulInvD) >> PrecisionShift, srb, sg);

        if (d < 0)
        {
          // choose straight (u direction) 
          twovduMulInvD = dMulInvD + duMulInvD;
          d += incrS;
          dMulInvD += incrSMulInvD;
        }
        else
        {
          // choose diagonal (u+v direction) 
          twovduMulInvD = dMulInvD - duMulInvD;
          d += incrD;
          dMulInvD += incrDMulInvD;
          addr += vincr;
        }
        u++;
        addr += uincr;
      } while (u < uend);
    }
    /// <summary> 
    /// Blends a specific source color on top of a destination premultiplied color 
    /// </summary> 
    /// <param name="context">Array containing destination color</param> 
    /// <param name="index">Index of destination pixel</param> 
    /// <param name="sa">Source alpha (0..255)</param> 
    /// <param name="srb">Source non-premultiplied red and blue component in the format 0x00rr00bb</param> 
    /// <param name="sg">Source green component (0..255)</param> 
    private static void AlphaBlendNormalOnPremultiplied(BitmapContext context, int index, int sa, uint srb, uint sg)
    {
      var pixels = context.Pixels;
      var destPixel = (uint)pixels[index];

      var da = (destPixel >> 24);
      var dg = ((destPixel >> 8) & 0xff);
      var drb = destPixel & 0x00FF00FF;

      // blend with high-quality alpha and lower quality but faster 1-off RGBs 
      pixels[index] = (int)(
         ((sa + ((da * (255 - sa) * 0x8081) >> 23)) << 24) | // aplha 
         (((sg - dg) * sa + (dg << 8)) & 0xFFFFFF00) | // green 
         (((((srb - drb) * sa) >> 8) + drb) & 0x00FF00FF) // red and blue 
      );
    }
    /// <summary>
    /// Draws a colored line by connecting two points using an optimized DDA. 
    /// Uses the pixels array and the width directly for best performance.
    /// </summary>
    /// <param name="context">The context containing the pixels as int RGBA value.</param>
    /// <param name="pixelWidth">The width of one scanline in the pixels array.</param>
    /// <param name="pixelHeight">The height of the bitmap.</param>
    /// <param name="x1">The x-coordinate of the start point.</param>
    /// <param name="y1">The y-coordinate of the start point.</param>
    /// <param name="x2">The x-coordinate of the end point.</param>
    /// <param name="y2">The y-coordinate of the end point.</param>
    /// <param name="color">The color for the line.</param>
    public static void DrawLine(BitmapContext context, int pixelWidth, int pixelHeight, int x1, int y1, int x2, int y2, int color)
    {
      var pixels = context.Pixels;

      // Distance start and end point
      int dx = x2 - x1;
      int dy = y2 - y1;

      const int PrecisionShift = 8;

      // Determine slope (absoulte value)
      int lenX, lenY;
      if (dy >= 0)
      {
        lenY = dy;
      }
      else
      {
        lenY = -dy;
      }

      if (dx >= 0)
      {
        lenX = dx;
      }
      else
      {
        lenX = -dx;
      }

      if (lenX > lenY)
      { // x increases by +/- 1
        if (dx < 0)
        {
          int t = x1;
          x1 = x2;
          x2 = t;
          t = y1;
          y1 = y2;
          y2 = t;
        }

        // Init steps and start
        int incy = (dy << PrecisionShift) / dx;

        int y1S = y1 << PrecisionShift;
        int y2S = y2 << PrecisionShift;
        int hs = pixelHeight << PrecisionShift;

        if (y1 < y2)
        {
          if (y1 >= pixelHeight || y2 < 0)
          {
            return;
          }
          if (y1S < 0)
          {
            if (incy == 0)
            {
              return;
            }
            int oldy1S = y1S;
            // Find lowest y1s that is greater or equal than 0.
            y1S = incy - 1 + ((y1S + 1) % incy);
            x1 += (y1S - oldy1S) / incy;
          }
          if (y2S >= hs)
          {
            if (incy != 0)
            {
              // Find highest y2s that is less or equal than ws - 1.
              // y2s = y1s + n * incy. Find n.
              y2S = hs - 1 - (hs - 1 - y1S) % incy;
              x2 = x1 + (y2S - y1S) / incy;
            }
          }
        }
        else
        {
          if (y2 >= pixelHeight || y1 < 0)
          {
            return;
          }
          if (y1S >= hs)
          {
            if (incy == 0)
            {
              return;
            }
            int oldy1S = y1S;
            // Find highest y1s that is less or equal than ws - 1.
            // y1s = oldy1s + n * incy. Find n.
            y1S = hs - 1 + (incy - (hs - 1 - oldy1S) % incy);
            x1 += (y1S - oldy1S) / incy;
          }
          if (y2S < 0)
          {
            if (incy != 0)
            {
              // Find lowest y2s that is greater or equal than 0.
              // y2s = y1s + n * incy. Find n.
              y2S = y1S % incy;
              x2 = x1 + (y2S - y1S) / incy;
            }
          }
        }

        if (x1 < 0)
        {
          y1S -= incy * x1;
          x1 = 0;
        }
        if (x2 >= pixelWidth)
        {
          x2 = pixelWidth - 1;
        }

        int ys = y1S;

        // Walk the line!
        int y = ys >> PrecisionShift;
        int previousY = y;
        int index = x1 + y * pixelWidth;
        int k = incy < 0 ? 1 - pixelWidth : 1 + pixelWidth;
        for (int x = x1; x <= x2; ++x)
        {
          pixels[index] = color;
          ys += incy;
          y = ys >> PrecisionShift;
          if (y != previousY)
          {
            previousY = y;
            index += k;
          }
          else
          {
            ++index;
          }
        }
      }
      else
      {
        // Prevent divison by zero
        if (lenY == 0)
        {
          return;
        }
        if (dy < 0)
        {
          int t = x1;
          x1 = x2;
          x2 = t;
          t = y1;
          y1 = y2;
          y2 = t;
        }

        // Init steps and start
        int x1S = x1 << PrecisionShift;
        int x2S = x2 << PrecisionShift;
        int ws = pixelWidth << PrecisionShift;

        int incx = (dx << PrecisionShift) / dy;

        if (x1 < x2)
        {
          if (x1 >= pixelWidth || x2 < 0)
          {
            return;
          }
          if (x1S < 0)
          {
            if (incx == 0)
            {
              return;
            }
            int oldx1S = x1S;
            // Find lowest x1s that is greater or equal than 0.
            x1S = incx - 1 + ((x1S + 1) % incx);
            y1 += (x1S - oldx1S) / incx;
          }
          if (x2S >= ws)
          {
            if (incx != 0)
            {
              // Find highest x2s that is less or equal than ws - 1.
              // x2s = x1s + n * incx. Find n.
              x2S = ws - 1 - (ws - 1 - x1S) % incx;
              y2 = y1 + (x2S - x1S) / incx;
            }
          }
        }
        else
        {
          if (x2 >= pixelWidth || x1 < 0)
          {
            return;
          }
          if (x1S >= ws)
          {
            if (incx == 0)
            {
              return;
            }
            int oldx1S = x1S;
            // Find highest x1s that is less or equal than ws - 1.
            // x1s = oldx1s + n * incx. Find n.
            x1S = ws - 1 + (incx - (ws - 1 - oldx1S) % incx);
            y1 += (x1S - oldx1S) / incx;
          }
          if (x2S < 0)
          {
            if (incx != 0)
            {
              // Find lowest x2s that is greater or equal than 0.
              // x2s = x1s + n * incx. Find n.
              x2S = x1S % incx;
              y2 = y1 + (x2S - x1S) / incx;
            }
          }
        }

        if (y1 < 0)
        {
          x1S -= incx * y1;
          y1 = 0;
        }
        if (y2 >= pixelHeight)
        {
          y2 = pixelHeight - 1;
        }

        int index = x1S + ((y1 * pixelWidth) << PrecisionShift);

        // Walk the line!
        var inc = (pixelWidth << PrecisionShift) + incx;
        for (int y = y1; y <= y2; ++y)
        {
          pixels[index >> PrecisionShift] = color;
          index += inc;
        }
      }
    }
Beispiel #12
0
 /// <summary>
 /// Performs a Copy operation from source BitmapContext to destination Array
 /// </summary>
 /// <remarks>Equivalent to calling Buffer.BlockCopy in Silverlight, or native memcpy in WPF</remarks>
 public static void BlockCopy(BitmapContext src, int srcOffset, byte[] dest, int destOffset, int count)
 {
   Buffer.BlockCopy(src.Pixels, srcOffset, dest, destOffset, count);
 }
Beispiel #13
0
 /// <summary>
 /// Performs a Copy operation from source Array to destination BitmapContext
 /// </summary>
 /// <remarks>Equivalent to calling Buffer.BlockCopy in Silverlight, or native memcpy in WPF</remarks>
 public static void BlockCopy(int[] src, int srcOffset, BitmapContext dest, int destOffset, int count)
 {
   Buffer.BlockCopy(src, srcOffset, dest.Pixels, destOffset, count);
 }
Beispiel #14
0
    static void MaleTestbild(BitmapContext bmpTarget, BitmapContext bmpSource, int px, int py, BildElement bildElement, BildTeile bildTeile = BildTeile.Alle)
    {
      var target = new RectInt(px * BoxPixelWidth * Multi, py * BoxPixelHeight * Multi, BoxPixelWidth * Multi, BoxPixelHeight * Multi);
      int elY = (int)bildElement / 7;
      int elX = (int)bildElement - (elY * 7);
      var source = new RectInt(elX * BoxPixelWidth, elY * BoxPixelHeight, BoxPixelWidth, BoxPixelHeight);

      switch (bildTeile)
      {
        case BildTeile.Alle: break;
        case BildTeile.Links: target.w /= 2; source.w /= 2; break;
        case BildTeile.Rechts: target.w /= 2; source.w /= 2; target.x += BoxPixelWidth * Multi / 2; source.x += BoxPixelWidth / 2; break;
        case BildTeile.Oben: target.h /= 2; source.h /= 2; break;
        case BildTeile.Unten: target.h /= 2; source.h /= 2; target.y += BoxPixelHeight * Multi / 2; source.y += BoxPixelHeight / 2; break;
        case BildTeile.LinksOben: target.w /= 2; target.h /= 2; source.w /= 2; source.h /= 2; break;
        case BildTeile.RechtsOben: target.w /= 2; target.h /= 2; source.w /= 2; source.h /= 2; target.x += BoxPixelWidth * Multi / 2; source.x += BoxPixelWidth / 2; break;
        case BildTeile.LinksUnten: target.w /= 2; target.h /= 2; source.w /= 2; source.h /= 2; target.y += BoxPixelHeight * Multi / 2; source.y += BoxPixelHeight / 2; break;
        case BildTeile.RechtsUnten: target.w /= 2; target.h /= 2; source.w /= 2; source.h /= 2; target.x += BoxPixelWidth * Multi / 2; source.x += BoxPixelWidth / 2; target.y += BoxPixelHeight * Multi / 2; source.y += BoxPixelHeight / 2; break;
        default: throw new Exception("kombi unbekannt: " + (int)bildTeile);
      }

      if (bildElement == BildElement.Frei)
      {
        bmpTarget.FillRectangle(target.x, target.y, target.x + target.w, target.y + target.h, 0x001122);
      }

      bmpTarget.Blit(target, bmpSource, source, Colors.White, BlendMode.Alpha);
    }
        private static void RenderClippedEdges(IBody body, BitmapContext context)
        {
            try
            {
                if (body.ClippedEdges.HasFlag(FrameEdges.Bottom))
                {
                    context.WriteableBitmap.FillRectangle(
                        0,
                        (int)_height - (int)_clipBoundsThickness, 
                        (int)_width,
                        (int)_height, 
                        Colors.Red);
                }

                if (body.ClippedEdges.HasFlag(FrameEdges.Top))
                {
                    context.WriteableBitmap.FillRectangle(
                        0,
                        0,
                        (int)_width,
                        (int)_clipBoundsThickness,
                        Colors.Red);
                }

                if (body.ClippedEdges.HasFlag(FrameEdges.Left))
                {
                    context.WriteableBitmap.FillRectangle(
                        0,
                        0,
                        (int)_clipBoundsThickness,
                        (int)_height,
                        Colors.Red);
                }

                if (body.ClippedEdges.HasFlag(FrameEdges.Right))
                {
                    context.WriteableBitmap.FillRectangle(
                        (int)_width - (int)_clipBoundsThickness,
                        0,
                        (int)_width,
                        (int)_height,
                        Colors.Red);
                }
            }
            catch { }
        }
Beispiel #16
0
    void InitGame(string gameTxt)
    {
      playField = new SokowahnField(gameTxt);
      undoList.Clear();
      undoList.Push(playField.GetGameState());
      drawField = new SokowahnField(playField);
      for (int i = 0; i < drawField.fieldData.Length; i++) drawField.fieldData[i] = '-';

      int width = playField.width * BoxPixelWidth * Multi;
      int height = playField.height * BoxPixelHeight * Multi + 1;

      viewImage = new WriteableBitmap(width, height);
      viewContext = viewImage.GetBitmapContext();

      GameImage.Source = viewImage;

      UpdateScreen(playField);
    }
Beispiel #17
0
        private static void DrawBonesAndJoints(IBody body, BitmapContext context, Color boneColor, Color jointColor)
        {
            foreach (var bone in BoneTypeEx.DrawnBones)
            {
                DrawBone(body, context, bone, boneColor);
            }

            Color inferredJointColor = jointColor;
            inferredJointColor.A = 128;

            // Render Joints
            foreach (var joint in body.Joints.Values)
            {
                if (joint.TrackingState == TrackingState.NotTracked)
                {
                    continue;
                }

                var point = GetDepthSpacePoint(joint, body.HasMappedDepthPositions);

                context.WriteableBitmap.FillEllipseCentered(
                    (int)point.X,
                    (int)point.Y,
                    (int)_jointThickness,
                    (int)_jointThickness,
                    joint.TrackingState == TrackingState.Inferred ? inferredJointColor : jointColor);
            }
        }