/// <summary>
        /// Draws the skeleton if necessary.
        /// </summary>
        private void drawSkeletonAndLabels()
        {
            using (Graphics g = Graphics.FromImage(bitmap))
            {
                if (UserLocationInformation.ContainsKey(CurrentFrame))
                {
                    foreach (int user in UserLocationInformation[CurrentFrame].Keys)
                    {
                        JointDictionary twoDPositions =
                            Convert3Dto2D(UserLocationInformation[CurrentFrame][user], depthGenerator);

                        if (shouldDrawSkeleton)
                        {
                            DrawSkeleton(g, ANTICOLORS[user % NCOLORS],
                                         twoDPositions, ConfidenceThreshold);
                        }

                        if (shouldPrintID)
                        {
                            Point3D com   = twoDPositions[SkeletonJoint.Torso].Position;
                            string  label = "User " + user.ToString();
                            using (Brush brush = new SolidBrush(ANTICOLORS[user % NCOLORS]))
                            {
                                g.DrawString(label, font_label,
                                             brush,
                                             com.X - TextRenderer.MeasureText(label, font_label).Width / 2,
                                             com.Y);
                            }
                        }
                    }

                    if (AdditionalSkeletonIDs != null &&
                        AdditionalSkeletonInformation != null &&
                        shouldDrawSkeleton)
                    {
                        foreach (int user in AdditionalSkeletonIDs)
                        {
                            if (AdditionalSkeletonInformation.ContainsKey(CurrentFrame) &&
                                AdditionalSkeletonInformation[CurrentFrame].ContainsKey(user))
                            {
                                JointDictionary twoDPositions;
                                if (UserLocationInformation.Is3DData)
                                {
                                    twoDPositions =
                                        Convert3Dto2D(AdditionalSkeletonInformation[CurrentFrame][user], depthGenerator);
                                }
                                else
                                {
                                    twoDPositions = AdditionalSkeletonInformation[CurrentFrame][user];
                                }

                                DrawSkeleton(g, COLORS[user % NCOLORS],
                                             twoDPositions, 0.0);
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// The export logic.
        /// </summary>
        /// <param name="parameter">An object[] with the real parameters.
        /// Have a look at <see cref="ExportFrames"/> for a usage
        /// example.</param>
        private void doExport(object parameter)
        {
            object[] parameters = parameter as object[];
            if (parameters == null)
            {
                return;
            }

            // Export directory
            DirectoryInfo exportDir = parameters[10] as DirectoryInfo;

            if (exportDir == null)
            {
                return;
            }

            // Frame list
            List <int> frames = parameters[0] as List <int>;

            if (frames == null || frames.Count == 0)
            {
                return;
            }
            frames.Sort();

            // User list
            List <int> userIDs = parameters[1] as List <int>;

            if (userIDs == null)
            {
                return;
            }

            // Ignore List
            List <int> formerIgnoreList = new List <int>(UsersToIgnore);

            UsersToIgnore.Clear();
            List <int> occuringUsers = GetUserStatistics(frames).Keys.ToList <int>();

            foreach (int user in occuringUsers)
            {
                if (!userIDs.Contains(user))
                {
                    UsersToIgnore.Add(user);
                }
            }

            // The rest of parameters
            bool AnnotationsIn2D         = (bool)parameters[2];
            bool AnnotationsIn3D         = (bool)parameters[3];
            bool ExportRelativePathNames = (bool)parameters[4];
            bool ImageOrDepth            = (bool)parameters[5];
            bool DrawBackground          = (bool)parameters[6];
            bool DrawSkeleton            = (bool)parameters[7];
            bool DrawHighlights          = (bool)parameters[8];
            bool DrawLabels = (bool)parameters[9];

            // Number format
            int max = frames[frames.Count - 1];
            int characters;

            if (max == 0)
            {
                characters = 1;
            }
            else
            {
                characters = (int)Math.Ceiling(Math.Log10(max));
            }
            String exportFormatString = "d" + characters;

            // The export xml files.
            ImageDictionary exportedIndex2D = new ImageDictionary(false);

            exportedIndex2D.XmlExportFrameFileList = new Dictionary <int, string>();
            exportedIndex2D.XmlOmitPoints          = (userIDs.Count == 0);

            ImageDictionary exportedIndex3D = new ImageDictionary(true);

            exportedIndex3D.XmlExportFrameFileList = new Dictionary <int, string>();
            exportedIndex3D.XmlOmitPoints          = (userIDs.Count == 0);

            String filename;
            String export_filename_suffix = "";

            lock (RUN_CONTROL_LOCK)
            {
                try
                {
                    StopPlayback();

                    lock (EXPORT_LOCK)
                    {
                        // Configure for export
                        DrawSkeletonMesh         = DrawSkeleton;
                        DrawSensorData           = true;
                        this.ImageOrDepth        = ImageOrDepth;
                        this.DrawBackground      = DrawBackground;
                        this.DrawUserHighlight   = DrawHighlights;
                        this.DrawUserInformation = DrawLabels;

                        if (DrawSkeleton)
                        {
                            export_filename_suffix += "s";
                        }
                        if (!DrawSensorData)
                        {
                            export_filename_suffix += "a";
                        }
                        if (!ImageOrDepth)
                        {
                            export_filename_suffix += "d";
                        }
                        if (!DrawBackground)
                        {
                            export_filename_suffix += "b";
                        }
                        if (DrawUserHighlight)
                        {
                            export_filename_suffix += "h";
                        }
                        if (DrawUserInformation)
                        {
                            export_filename_suffix += "l";
                        }

                        if (export_filename_suffix.Length > 0)
                        {
                            export_filename_suffix = "-" + export_filename_suffix;
                        }

                        for (int frameIndex = 0; frameIndex < frames.Count; frameIndex++)
                        {
                            SeekFrame(frames[frameIndex]);
                            RequestUpdate(false);
                            String relative_filename = frames[frameIndex].ToString(exportFormatString) +
                                                       export_filename_suffix + ".png";
                            filename = Path.Combine(exportDir.FullName,
                                                    relative_filename);


                            lock (ImageLock)
                            {
                                bitmap.Save(filename, ImageFormat.Png);
                            }

                            // Get the user positions in this frame
                            Dictionary <int, JointDictionary> frame_positions2D =
                                new Dictionary <int, JointDictionary>();
                            Dictionary <int, JointDictionary> frame_positions3D =
                                new Dictionary <int, JointDictionary>();
                            if (UserLocationInformation.ContainsKey(frames[frameIndex]))
                            {
                                foreach (int user in UserLocationInformation[frames[frameIndex]].Keys)
                                {
                                    if (userIDs.Contains(user))
                                    {
                                        frame_positions3D.Add(user, new JointDictionary(
                                                                  UserLocationInformation[frames[frameIndex]][user]));
                                        frame_positions2D.Add(user, new JointDictionary(
                                                                  Convert3Dto2D(UserLocationInformation[frames[frameIndex]][user], depthGenerator)));
                                    }
                                }
                            }
                            exportedIndex2D.Add(frames[frameIndex], frame_positions2D);
                            if (!ExportRelativePathNames)
                            {
                                exportedIndex2D.XmlExportFrameFileList.Add(
                                    frames[frameIndex], filename);
                            }
                            else
                            {
                                exportedIndex2D.XmlExportFrameFileList.Add(
                                    frames[frameIndex], relative_filename);
                            }
                            exportedIndex3D.Add(frames[frameIndex], frame_positions3D);
                            if (!ExportRelativePathNames)
                            {
                                exportedIndex3D.XmlExportFrameFileList.Add(
                                    frames[frameIndex], filename);
                            }
                            else
                            {
                                exportedIndex3D.XmlExportFrameFileList.Add(
                                    frames[frameIndex], relative_filename);
                            }


                            onExportMadeProgress(
                                (float)(frameIndex + 1) / (float)frames.Count * 100, frameIndex + 1, frames.Count);
                            if (export_cancelled)
                            {
                                return;
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    onExportFailed(e.Message);
                    return;
                }

                // Reset ignore list
                UsersToIgnore.Clear();
                UsersToIgnore.AddRange(formerIgnoreList);

                if (!AnnotationsIn2D)
                {
                    exportedIndex2D = null;
                }
                if (!AnnotationsIn3D)
                {
                    exportedIndex3D = null;
                }
            }

            // Report success.
            Thread reporter = new Thread(onExportFinished);

            reporter.Start(new object[] { this, exportDir, frames, userIDs,
                                          exportedIndex2D, exportedIndex3D, ExportRelativePathNames,
                                          export_filename_suffix });
        }
 /// <summary>
 /// Calculates how often the user with given id occurs in the given
 /// frames. If the argument frames is null, the entire video will
 /// be iterated.
 /// </summary>
 public Dictionary <int, int> GetUserStatistics(List <int> frames)
 {
     return(UserLocationInformation.GetUserStatistics(frames));
 }