public Tuple <string, Size> Convert(Bitmap bmp, string inputfilename, string outputfolder, DateTime filetime, Action <string> logit, string bodyname, string systemname, string cmdrname) // can call independent of watcher, pass in bmp to convert
        {
            outputfolder = SubFolder(outputfolder, systemname, cmdrname, filetime);

            // bmp is the original bitmap at full res

            int index = 0;

            string outputfilename;
            string secondfilename, thirdfilename;

            do                                          // add _N on the filename for index>0, to make them unique.
            {
                string fn = CreateFileName(systemname, bodyname, inputfilename, FileNameFormat, HighRes, filetime) + (index == 0 ? "" : "_" + index);

                outputfilename = Path.Combine(outputfolder, fn + "." + OutputFileExtension.ToString());
                secondfilename = Path.Combine(outputfolder, fn + "-1." + OutputFileExtension.ToString());
                thirdfilename  = Path.Combine(outputfolder, fn + "-2." + OutputFileExtension.ToString());
                index++;
            } while (File.Exists(outputfilename));          // if name exists, pick another

            if (outputfilename.Equals(inputfilename, StringComparison.InvariantCultureIgnoreCase))
            {
                logit(string.Format(("Cannot convert {0} to {1} as names clash" + Environment.NewLine + "Pick a different conversion folder or a different output format"), inputfilename, outputfilename));
                return(new Tuple <string, Size>(null, Size.Empty));
            }

            // the OutputFilename should point to the best screenshot, and FinalSize points to this

            Size finalsize = Size.Empty;

            if (CropResizeImage1 == CropResizeOptions.Off || KeepMasterConvertedImage) // if resize 1 off, or keep full size.
            {
                WriteBMP(bmp, outputfilename, filetime);
                finalsize = bmp.Size;        // this is our image to use in the rest of the system
            }

            if (CropResizeImage1 != CropResizeOptions.Off)
            {
                string nametouse = KeepMasterConvertedImage ? secondfilename : outputfilename;     // if keep full sized off, we use this one as our image

                if (CropResizeImage1 == CropResizeOptions.Crop)
                {
                    Bitmap cropped = bmp.CropImage(CropResizeArea1);
                    WriteBMP(cropped, nametouse, filetime);
                    cropped.Dispose();
                }
                else
                {
                    Bitmap resized = bmp.ResizeImage(CropResizeArea1.Width, CropResizeArea1.Height);
                    WriteBMP(resized, nametouse, filetime);
                    resized.Dispose();
                }

                if (!KeepMasterConvertedImage)       // if not keeping the full sized one, its final
                {
                    finalsize = bmp.Size;
                }
            }

            if (CropResizeImage2 == CropResizeOptions.Crop)
            {
                Bitmap cropped = bmp.CropImage(CropResizeArea2);
                WriteBMP(cropped, thirdfilename, filetime);
                cropped.Dispose();
            }
            else if (CropResizeImage2 == CropResizeOptions.Resize)
            {
                Bitmap resized = bmp.ResizeImage(CropResizeArea2.Width, CropResizeArea2.Height);
                WriteBMP(resized, thirdfilename, filetime);
                resized.Dispose();
            }

            if (CopyToClipboard)
            {
                using (Image bmpc = Bitmap.FromFile(outputfilename))
                {
                    try
                    {
                        System.Windows.Forms.Clipboard.SetImage(bmpc);
                    }
                    catch
                    {
                        logit("Copying image to clipboard failed");
                    }
                }
            }

            if (RemoveOriginal)
            {
                try
                {
                    File.Delete(inputfilename);
                }
                catch
                {
                    logit($"Unable to remove file {inputfilename}");
                }
            }

            System.Diagnostics.Debug.WriteLine("Convert " + inputfilename + " at " + systemname + " to " + outputfilename);

            logit(string.Format("Converted {0} to {1}".T(EDTx.ScreenShotImageConverter_CNV), Path.GetFileName(inputfilename), outputfilename));

            return(new Tuple <string, Size>(outputfilename, finalsize));
        }
        // helpers for above

        private bool UpdateOutputFolderWithSubFolder()
        {
            if (String.IsNullOrWhiteSpace(OutputFolder))
            {
                OutputFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), "Frontier Developments", "Elite Dangerous", "Converted");
            }

            switch (FolderFormatIndex)
            {
            case 1:         // system name
                OutputFolder += "\\" + SystemName.SafeFileString();
                break;

            case 2:         // "YYYY-MM-DD"
                OutputFolder += "\\" + Timestamp.ToString("yyyy-MM-dd");
                break;

            case 3:         // "DD-MM-YYYY"
                OutputFolder += "\\" + Timestamp.ToString("dd-MM-yyyy");
                break;

            case 4:         // "MM-DD-YYYY"
                OutputFolder += "\\" + Timestamp.ToString("MM-dd-yyyy");
                break;

            case 5:      //"YYYY-MM-DD Sysname",
                OutputFolder += "\\" + Timestamp.ToString("yyyy-MM-dd") + " " + SystemName.SafeFileString();
                break;

            case 6:      //"DD-MM-YYYY Sysname",
                OutputFolder += "\\" + Timestamp.ToString("dd-MM-yyyy") + " " + SystemName.SafeFileString();
                break;

            case 7:     //"MM-DD-YYYY Sysname"
                OutputFolder += "\\" + Timestamp.ToString("MM-dd-yyyy") + " " + SystemName.SafeFileString();
                break;

            case 8:     // CMDR name
                OutputFolder += "\\" + (EDCommander.GetCommander(CommanderID)?.Name ?? $"CmdrId{CommanderID}").SafeFileString();
                break;

            case 9:     // CMDR name at sysname
                OutputFolder += "\\" + (EDCommander.GetCommander(CommanderID)?.Name ?? $"CmdrId{CommanderID}").SafeFileString() + " at " + SystemName.SafeFileString();
                break;

            case 10:     // YYYY - MM - DD CMDR name at sysname
                OutputFolder += "\\" + Timestamp.ToString("yyyy-MM-dd") + " " +
                                (EDCommander.GetCommander(CommanderID)?.Name ?? $"CmdrId{CommanderID}").SafeFileString() + " at " + SystemName.SafeFileString();
                break;

            case 11:     // CMDR Name \ SystemName
                OutputFolder += "\\" + (EDCommander.GetCommander(CommanderID)?.Name ?? $"CmdrId{CommanderID}").SafeFileString() + "\\" + SystemName.SafeFileString();
                break;
            }

            if (!Directory.Exists(OutputFolder))
            {
                Directory.CreateDirectory(OutputFolder);
            }

            return(!(OutputFolder.Equals(InputFolder) && OutputFileExtension.ToString().Equals(InputFileExtension.ToString())));
        }
        // convert bmp from inputfilename with filetime
        // into outputfolder with properties body,system,cmdrname
        // return final inputfilename, output filename, size. or null if failed.

        public Tuple <string, string, Size> Convert(Bitmap bmp, string inputfilename, DateTime filetime, string outputfolder,
                                                    string bodyname, string systemname, string cmdrname, Action <string> logit) // can call independent of watcher, pass in bmp to convert
        {
            outputfolder = SubFolder(FolderNameFormat, outputfolder, systemname, cmdrname, filetime);

            if (!Directory.Exists(outputfolder))
            {
                Directory.CreateDirectory(outputfolder);
            }

            // bmp is the original bitmap at full res

            int index = 0;

            string outputfilename;
            string secondfilename, thirdfilename;

            do                                          // add _N on the filename for index>0, to make them unique.
            {
                string fn = CreateFileName(systemname, bodyname, inputfilename, FileNameFormat, HighRes, filetime) + (index == 0 ? "" : "_" + index);

                outputfilename = Path.Combine(outputfolder, fn + "." + OutputFileExtension.ToString());
                secondfilename = Path.Combine(outputfolder, fn + "-1." + OutputFileExtension.ToString());
                thirdfilename  = Path.Combine(outputfolder, fn + "-2." + OutputFileExtension.ToString());
                index++;
            } while (File.Exists(outputfilename));          // if name exists, pick another

            if (outputfilename.Equals(inputfilename, StringComparison.InvariantCultureIgnoreCase))
            {
                logit(string.Format(("Cannot convert {0} to {1} as names clash" + Environment.NewLine + "Pick a different conversion folder or a different output format"), inputfilename, outputfilename));
                return(null);
            }

            // the OutputFilename should point to the best screenshot, and FinalSize points to this

            Size finalsize = Size.Empty;

            if (CropResizeImage1 == CropResizeOptions.Off || KeepMasterConvertedImage) // if resize 1 off, or keep full size.
            {
                WriteBMP(bmp, outputfilename, filetime);
                finalsize = bmp.Size;        // this is our image to use in the rest of the system

                if (ClipboardOption == ClipboardOptions.CopyMaster)
                {
                    CopyClipboardSafe(bmp, logit);
                }
            }

            if (CropResizeImage1 != CropResizeOptions.Off)
            {
                Bitmap converted = null;

                if (CropResizeImage1 == CropResizeOptions.Crop)
                {
                    converted = bmp.CropImage(CropResizeArea1);
                }
                else
                {
                    converted = bmp.ResizeImage(CropResizeArea1.Width, CropResizeArea1.Height);
                }

                string nametouse = KeepMasterConvertedImage ? secondfilename : outputfilename;     // if keep full sized off, we use this one as our image
                WriteBMP(converted, nametouse, filetime);

                if (!KeepMasterConvertedImage)       // if not keeping the full sized one, its final
                {
                    finalsize = converted.Size;
                }

                if (ClipboardOption == ClipboardOptions.CopyImage1)
                {
                    CopyClipboardSafe(converted, logit);
                }

                converted.Dispose();
            }

            if (CropResizeImage2 != CropResizeOptions.Off)
            {
                Bitmap converted = null;

                if (CropResizeImage2 == CropResizeOptions.Crop)
                {
                    converted = bmp.CropImage(CropResizeArea2);
                }
                else
                {
                    converted = bmp.ResizeImage(CropResizeArea2.Width, CropResizeArea2.Height);
                }

                WriteBMP(converted, thirdfilename, filetime);

                if (ClipboardOption == ClipboardOptions.CopyImage2)
                {
                    CopyClipboardSafe(converted, logit);
                }

                converted.Dispose();
            }

            if (OriginalImageOption == OriginalImageOptions.Delete)
            {
                try
                {
                    System.Diagnostics.Debug.WriteLine("Delete {0}", inputfilename);
                    File.Delete(inputfilename);
                    inputfilename = null;
                }
                catch
                {
                    logit($"Unable to remove file {inputfilename}");
                }
            }
            else if (OriginalImageOption == OriginalImageOptions.Move)
            {
                string outfile = Path.Combine(OriginalImageOptionDirectory, Path.GetFileNameWithoutExtension(outputfilename) + Path.GetExtension(inputfilename));
                int    indexi  = 1;
                while (true)
                {
                    try
                    {
                        System.Diagnostics.Debug.WriteLine("Move {0} to {1}", inputfilename, outfile);
                        File.Move(inputfilename, outfile);
                        inputfilename = outfile;
                        break;
                    }
                    catch
                    {
                        outfile = Path.Combine(OriginalImageOptionDirectory, Path.GetFileNameWithoutExtension(outfile) + "-" + indexi++.ToString() + Path.GetExtension(outfile));
                    }
                }
            }

            System.Diagnostics.Debug.WriteLine("Convert " + inputfilename + " at " + systemname + " to " + outputfilename);

            logit(string.Format("Converted {0} to {1}".T(EDTx.ScreenShotImageConverter_CNV), Path.GetFileName(inputfilename), outputfilename));

            return(new Tuple <string, string, Size>(inputfilename, outputfilename, finalsize));
        }
        private Bitmap ConvertImage(Bitmap bmp)
        {
            int index = 0;

            string bodyname = (JournalScreenShot.Body == null) ? "" : (JournalScreenShot.Body.Equals(SystemName, StringComparison.InvariantCultureIgnoreCase) ? "" : JournalScreenShot.Body);

            do                                          // add _N on the filename for index>0, to make them unique.
            {
                OutputFilename = Path.Combine(OutputFolder, CreateFileName(SystemName, bodyname, InputFilename, FilenameFormatIndex, HighRes, Timestamp) + (index == 0 ? "" : "_" + index) + "." + OutputFileExtension.ToString());
                index++;
            } while (File.Exists(OutputFilename));          // if name exists, pick another

            System.Drawing.Bitmap croppedbmp = null;

            if (CropImage)
            {
                /* check that crop settings are within the image, otherwise adjust. */
                if ((CropArea.Width <= 0) || (CropArea.Width > bmp.Width))
                {
                    CropArea.X     = 0;
                    CropArea.Width = bmp.Width;
                }
                else if (CropArea.Left + CropArea.Width > bmp.Width)
                {
                    CropArea.X = bmp.Width - CropArea.Width;
                }
                if ((CropArea.Height <= 0) || (CropArea.Height > bmp.Height))
                {
                    CropArea.Y      = 0;
                    CropArea.Height = bmp.Height;
                }
                else if (CropArea.Top + CropArea.Height > bmp.Height)
                {
                    CropArea.Y = bmp.Height - CropArea.Height;
                }

                /* Only crop if we need to */
                if ((CropArea.Width != bmp.Width) || (CropArea.Height != bmp.Height))
                {                                                   // CLONE new one, which creates a new object
                    croppedbmp = bmp.Clone(CropArea, System.Drawing.Imaging.PixelFormat.DontCare);
                }
                else
                {
                    croppedbmp = bmp;           // just copy reference.. no need to crop.
                }
            }
            else
            {
                croppedbmp = bmp;               // just copy reference..
            }
            return(croppedbmp);
        }
        public bool Convert(Bitmap bmp, Action <string> logit) // can call independent of watcher, pass in bmp to convert
        {
            OutputFilename = null;
            FinalSize      = Point.Empty;
            Converted      = false;

            if (!UpdateOutputFolderWithSubFolder())  // add on any sub folder options to output folder
            {
                logit(string.Format(("Cannot convert {0} into the same folder as they are stored into" + Environment.NewLine + "Pick a different conversion folder or a different output format").T(EDTx.ScreenShotImageConverter_FolderErr), InputFileExtension.ToString()));
                return(false);
            }

            // bmp is the original bitmap at full res

            int index = 0;

            string bodyname = (JournalScreenShot.Body == null) ? "" : (JournalScreenShot.Body.Equals(SystemName, StringComparison.InvariantCultureIgnoreCase) ? "" : JournalScreenShot.Body);

            string secondfilename, thirdfilename;

            do                                          // add _N on the filename for index>0, to make them unique.
            {
                string fn = CreateFileName(SystemName, bodyname, InputFilename, FilenameFormatIndex, HighRes, Timestamp) + (index == 0 ? "" : "_" + index);

                OutputFilename = Path.Combine(OutputFolder, fn + "." + OutputFileExtension.ToString());
                secondfilename = Path.Combine(OutputFolder, fn + "-1." + OutputFileExtension.ToString());
                thirdfilename  = Path.Combine(OutputFolder, fn + "-2." + OutputFileExtension.ToString());
                index++;
            } while (File.Exists(OutputFilename));          // if name exists, pick another

            // the OutputFilename should point to the best screenshot, and FinalSize points to this

            if (CropResizeImage1 == ScreenShotConverter.CropResizeOptions.Off || KeepMasterConvertedImage) // if resize 1 off, or keep full size.
            {
                WriteBMP(bmp, OutputFilename);
                FinalSize = new Point(bmp.Size);        // this is our image to use in the rest of the system
            }

            if (CropResizeImage1 != ScreenShotConverter.CropResizeOptions.Off)
            {
                string nametouse = KeepMasterConvertedImage ? secondfilename : OutputFilename;     // if keep full sized off, we use this one as our image

                if (CropResizeImage1 == ScreenShotConverter.CropResizeOptions.Crop)
                {
                    Bitmap cropped = bmp.CropImage(CropResizeArea1);
                    WriteBMP(cropped, nametouse);
                    cropped.Dispose();
                }
                else
                {
                    Bitmap resized = bmp.ResizeImage(CropResizeArea1.Width, CropResizeArea1.Height);
                    WriteBMP(resized, nametouse);
                    resized.Dispose();
                }

                if (!KeepMasterConvertedImage)       // if not keeping the full sized one, its final
                {
                    FinalSize = new Point(bmp.Size);
                }
            }

            if (CropResizeImage2 == ScreenShotConverter.CropResizeOptions.Crop)
            {
                Bitmap cropped = bmp.CropImage(CropResizeArea2);
                WriteBMP(cropped, thirdfilename);
                cropped.Dispose();
            }
            else if (CropResizeImage2 == ScreenShotConverter.CropResizeOptions.Resize)
            {
                Bitmap resized = bmp.ResizeImage(CropResizeArea2.Width, CropResizeArea2.Height);
                WriteBMP(resized, thirdfilename);
                resized.Dispose();
            }

            Converted = true;

            if (Converted)
            {
                if (JournalScreenShot != null)
                {
                    JournalScreenShot.SetConvertedFilename(InputFilename, OutputFilename, FinalSize.X, FinalSize.Y);
                }

                System.Diagnostics.Debug.WriteLine("Convert " + InputFilename + " at " + SystemName + " to " + OutputFilename);

                logit(string.Format("Converted {0} to {1}".T(EDTx.ScreenShotImageConverter_CNV), Path.GetFileName(InputFilename), Path.GetFileName(OutputFilename)));
            }

            return(Converted);
        }