Ejemplo n.º 1
0
        public void TestPick_Load_NoMatch()
        {
            var fileList = new List <ImageMatcher.FileEntry>();

            fileList.Add(GetFileEntry(2015, 1, 1, "file1.jpg"));

            var tpInput    = new DateTime(2015, 1, 1, 13, 12, 0);
            var matchList  = new List <ImageMatcher.MatchEntry>();
            var matchEntry = new ImageMatcher.MatchEntry(tpInput, fileList, 0);

            matchList.Add(matchEntry);
            var matchXML = GetXML(matchList);

            var im = new ImageMatcher();

            im.SearchMode = false;
            im.LoadFromString(matchXML);

            try
            {
                var tpSearch = new DateTime(2015, 1, 2, 13, 12, 0);
                im.Pick(tpSearch);
                Assert.Fail("No exception thrown");
            }
            catch (ArgumentException)
            {
            }
        }
Ejemplo n.º 2
0
        public void TestPick_Load_SingleMatch()
        {
            var fileList = new List <ImageMatcher.FileEntry>();

            fileList.Add(GetFileEntry(2015, 1, 1, "file1.jpg"));

            var tp         = new DateTime(2015, 1, 1, 13, 12, 0);
            var matchList  = new List <ImageMatcher.MatchEntry>();
            var matchEntry = new ImageMatcher.MatchEntry(tp, fileList, 0);

            matchList.Add(matchEntry);
            var matchXML = GetXML(matchList);

            var im = new ImageMatcher();

            im.SearchMode = false;
            im.LoadFromString(matchXML);

            var entry = im.Pick(tp);

            Assert.IsTrue(entry.Timepoint.Equals(tp));

            var fileMatches = entry.Filematches;

            Assert.AreEqual(1, fileMatches.Count());
            Assert.AreEqual("file1.jpg", fileMatches.First().Filename);
        }
Ejemplo n.º 3
0
        static void testExtractFeatures()
        {
            Console.WriteLine("hello");
            ImageMatcher im = new ImageMatcher();
            String       s  = @"F:\photos\cc\08-06-23写真\ 003.JPG";

            //string s = @"E:\pic_skindetect\img_lib\20081839149581.jpg";
            im.LuvInit(@"E:\projects\ClothSearch\codes\trunk\data\luv.dat");
            float[] v   = im.ExtractDaubechiesWaveletVector(s);
            float   sum = 0;

            foreach (float i in v)
            {
                Console.Write("{0} ", i);
                sum += i;
            }
            Console.WriteLine();
            Console.WriteLine("{0}", sum);

            /*            Console.WriteLine(ImageMatcher.testAdd(10, 20).ToString());
             *          ImageMatcher im = new ImageMatcher();
             *          Console.WriteLine(im.testAdd2("abcd", 20).ToString());
             *
             * /*            Type t = Type.GetTypeFromProgID("ZjuImage.ImageMatcher");
             *          object voice = Activator.CreateInstance(t);
             *          object[] args = new Object[2];
             *          args[0] = "Hello, World!";
             *          args[1] = 0;
             *          t.InvokeMember("Speak", BindingFlags.InvokeMethod, null, voice, args);
             *          im.extractColorVector("abcd");*/
        }
Ejemplo n.º 4
0
        static void testCalcHsvAsynNumber()
        {
            Console.WriteLine("begin");
            ImageMatcher im = new ImageMatcher();

            String selectedPath = @"F:\jpgtest\";
            String ext          = ".jpg";
            float  limit        = 0.1f;
            int    vecnum       = 8;
            string retest       = @"E:\projects\ClothSearch\codes\trunk\data\RGBColor\retest_hsvasyn_number.txt";

            StreamWriter sw = File.CreateText(retest);

            for (int i = 1; i <= 100; ++i)
            {
                string  picName = selectedPath + i + ext;
                float[] vhsv    = im.ExtractHSVAynsColorVector(picName, 0, new int[] { -1 });
                if (vhsv == null)
                {
                    Console.WriteLine("Error of {0}{1}", i, ext);
                    continue;
                }
                sw.WriteLine("{0}, {1}", cnByMan[i - 1], getColorNumber(vhsv, limit));
            }
            sw.Close();
        }
Ejemplo n.º 5
0
        public void ImageMatcherComplexTest()
        {
            //Start TestApp
            var appProcess = new Process
            {
                StartInfo = new ProcessStartInfo("TestGUIApp.exe")
            };

            appProcess.Start();

            //Wait for TestApp to start
            System.Threading.Thread.Sleep(1000);

            try
            {
                var imageMatcher = new ImageMatcher();

                var windowPosition = WinAPI.GetWindowRectangle(appProcess);

                //Capture screenshot and load frame(with alpha channel) needle image
                var screenshot  = WinAPI.CaptureWindow(appProcess);
                var frameNeedle = Image.FromFile("frameNeedle.png");

                //Try to find frame template on the screen
                var result = imageMatcher.FindNeedle(screenshot, frameNeedle, new Rectangle(0, 0, screenshot.Width, screenshot.Height / 3));
                Assert.AreNotEqual(result.HasValue, false);

                //Image in the frame becomes our new template image
                var needleImage = ImageMatcher.CropImage(screenshot, result.Value);
                //Recalculate searching zone
                var sceneRectangle = new Rectangle(0, result.Value.Y + result.Value.Height, screenshot.Width, screenshot.Height - (result.Value.Y + result.Value.Height));

                //Try to find an image to click on
                result = imageMatcher.FindNeedle(screenshot, needleImage, sceneRectangle);
                Assert.AreNotEqual(result.HasValue, false);

                //Image found, click on it
                Input.LeftMouseClick(windowPosition.Value.X + result.Value.X + result.Value.Width / 2,
                                     windowPosition.Value.Y + result.Value.Y + result.Value.Height / 2);

                //Wait some time to redraw scene
                Input.MakeDelay(1000);
                //Take new screenshot
                screenshot = WinAPI.CaptureWindow(appProcess);
                //If clicked on right image, scene should redraw and template won't be found
                result = imageMatcher.FindNeedle(screenshot, needleImage);
                Assert.AreEqual(result.HasValue, false);

                frameNeedle.Dispose();
                needleImage.Dispose();
                screenshot.Dispose();
            }
            finally
            {
                if (!appProcess.HasExited)
                {
                    appProcess.Kill();
                }
            }
        }
Ejemplo n.º 6
0
        public WhatsappParser(string messagePath, ImageMatcher imageMatcher)
        {
            _lines = File.ReadAllLines(messagePath).ToList();
            _index = 0;

            _imageMatcher = imageMatcher;
            _lastcnt      = new Tuple <DateTime, int>(DateTime.MinValue, -1);
        }
Ejemplo n.º 7
0
        private static void testHSVAsynColorNumberSuccess()
        {
            Console.WriteLine("begin");
            ImageMatcher im = new ImageMatcher();

            String selectedPath = @"F:\jpgtest\";
            String ext          = ".jpg";

            string retest = @"E:\projects\ClothSearch\codes\trunk\data\RGBColor\retest_rate_hsv_aync2.txt";

            StreamWriter sw = File.CreateText(retest);

            sw.AutoFlush = true;
            float avrByMan  = 0.0f;
            float avrRByMan = 0.0f;

            calcAvr(cnByMan, ref avrByMan, ref avrRByMan);

            sw.WriteLine("图片: {0}, 平均每张图片颜色数: {1}, 偏差: {2}", 100, avrByMan, avrRByMan);

            sw.WriteLine("vec  /lim  /Algo, avr-avrByMan, avrR-avrRByMan, suc_rate, mod_suc_rate, maihadun, ejilide");

            // float limit = 0.05f;
            // int vecnum = 8;

            int[] cnhsv = new int[100];
            for (float limit = 0.05f; limit <= 0.1f; limit += 0.01f)
            {
                for (int i = 0; i < 100; ++i)
                {
                    string  picName = selectedPath + (i + 1) + ext;
                    float[] vhsv    = im.ExtractHSVAynsColorVector(picName, 0, new int[] { -1 });
                    if (vhsv == null)
                    {
                        Console.WriteLine("Error of {0}{1}", i + 1, ext);
                        continue;
                    }
                    cnhsv[i] = getColorNumber(vhsv, limit);
                    //sw.WriteLine("{0}, {1}, {2}", getColorNumber(vrgb, limit), getColorNumber(vhsv, limit), getColorNumber(vhls, limit));
                }
                float  avr    = 0.0f;
                float  avrR   = 0.0f;
                string format = "{0,-5}/{1,-5}/{2} , {3,-12}, {4,-14}, {5,-8}, {6,-12}, {7,-8}, {8,-7}";

                calcAvr(cnhsv, ref avr, ref avrR);
                sw.WriteLine(format, 176, limit, "hsva", avr - avrByMan, avrR - avrRByMan,
                             calcSucRate(cnByMan, cnhsv, 0.0f), calcSucRate(cnByMan, cnhsv, avr - avrByMan),
                             calcMaihadun(cnByMan, cnhsv), calEjilide(cnByMan, cnhsv));
            }

            sw.Close();
        }
Ejemplo n.º 8
0
        static void testExtractRGBColor()
        {
            Console.WriteLine("begin");
            ImageMatcher im = new ImageMatcher();

            String selectedPath = @"F:\jpgtest";

            string[] jpgFiles = Directory.GetFiles(selectedPath, "*.jpg");
            string[] gifFiles = Directory.GetFiles(selectedPath, "*.gif");
            string[] pngFiles = Directory.GetFiles(selectedPath, "*.png");
            string[] bmpFiles = Directory.GetFiles(selectedPath, "*.bmp");
            int      nFiles   = jpgFiles.Length + gifFiles.Length + pngFiles.Length + bmpFiles.Length;

            if (nFiles == 0)
            {
                return;
            }

            List <String> picNames = new List <string>(nFiles);

            picNames.AddRange(jpgFiles);
            picNames.AddRange(gifFiles);
            picNames.AddRange(pngFiles);
            picNames.AddRange(bmpFiles);

            Console.WriteLine("begin extract");
            string pre = @"E:\projects\ClothSearch\codes\trunk\data\RGBColor\HSVAsynColor_float_11x4x4.txt";

            float[][] vs    = new float[picNames.Count][];
            int       count = 0;

            foreach (String picName in picNames)
            {
                vs[count++] = im.ExtractHSVAynsColorVector(picName, 0, new int[] { -1 });
            }

            //int index = picName.LastIndexOf('\\');
            //StreamWriter sw = File.CreateText(pre + picName.Substring(index + 1) + ".txt");
            StreamWriter sw = File.CreateText(pre);

            for (int j = 0; j < vs[0].Length; j++)
            {
                for (int i = 0; i < vs.Length; i++)
                {
                    sw.Write("{0},", vs[i][j]);
                }
                sw.WriteLine();
            }
            sw.Close();
        }
Ejemplo n.º 9
0
        static void testCooccurrence()
        {
            Console.WriteLine("testCooccurrence begin");

            ImageMatcher im = new ImageMatcher();
            string       s  = @"E:\testpics\test\2.bmp";

            float[] v = im.ExtractCooccurrenceVector(s);
            foreach (float i in v)
            {
                Console.Write("{0} ", i);
            }

            Console.WriteLine();
            Console.WriteLine("testCooccurrence end");
        }
Ejemplo n.º 10
0
        static void testGabor()
        {
            Console.WriteLine("testGabor begin");

            ImageMatcher im = new ImageMatcher();
            string       s  = @"E:\pic_skindetect\img_lib\20081839149581.jpg";

            float[] v = im.ExtractGaborVector(s);
            foreach (float i in v)
            {
                Console.Write("{0} ", i);
            }

            Console.WriteLine();
            Console.WriteLine("testGabor end");
        }
Ejemplo n.º 11
0
        public void TestPick_FileList_NoMatch()
        {
            var fileList = new List <ImageMatcher.FileEntry>();

            fileList.Add(GetFileEntry(2015, 1, 1, "file1.jpg"));
            fileList.Add(GetFileEntry(2015, 1, 2, "file2.jpg"));
            fileList.Add(GetFileEntry(2015, 1, 3, "file3.jpg"));

            var im = new ImageMatcher();

            im.FileList   = fileList;
            im.SearchMode = true;

            var entry = im.Pick(new DateTime(2015, 1, 4, 16, 10, 0), 0);

            Assert.AreEqual(0, entry.Filematches.Count());
        }
Ejemplo n.º 12
0
        public void ImageMatcherSimpleTest()
        {
            var imageMatcher = new ImageMatcher();
            var gameScreen   = Image.FromFile("gameScreen.png");
            var spellNeedle  = Image.FromFile("spellNeedle.png");

            var result = imageMatcher.FindNeedle(gameScreen, spellNeedle);

            var seconds     = imageMatcher.LastOperationTime.ToString("ss");
            var miliseconds = imageMatcher.LastOperationTime.ToString("fff");

            TestContext.WriteLine($"Operation time: {seconds}s {miliseconds}ms");
            Assert.AreNotEqual(result, null);

            gameScreen.Dispose();
            spellNeedle.Dispose();
        }
Ejemplo n.º 13
0
        public HomeWin()
        {
            colorItems = ViewHelper.NewColorItems;
            shapeItems = ViewHelper.NewShapeItems;
            this.Resources.Add("colorItems", colorItems);
            this.Resources.Add("shapeItems", shapeItems);

            modifyColorItems = ViewHelper.NewColorItems;
            modifyShapeItems = ViewHelper.NewShapeItems;
            this.Resources.Add("modifyColorItems", modifyColorItems);
            this.Resources.Add("modifyShapeItems", modifyShapeItems);


            InitializeComponent();

            btnSearch.IsEnabled = false;
            rbtnPic.IsChecked   = true;

            dlgOpenKeyPic       = newOpenFileDialog();
            dlgOpenKeyPic.Title = "请选择关键图";

            dlgOpenPics             = newOpenFileDialog();
            dlgOpenPics.Title       = "请选择多张图片进行导入";
            dlgOpenPics.Multiselect = true;

            dlgOpenPicFolder              = new System.Windows.Forms.FolderBrowserDialog();
            dlgOpenPicFolder.Description  = "请选择文件夹以导入其下的所有图片(JPG, PNG, BMP)";
            dlgOpenPicFolder.SelectedPath = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
            //dlgOpenPicFolder.RootFolder = Environment.SpecialFolder.MyPictures;

            // It should be done by dependency injection here!!
            clothLibService    = new ClothLibService();
            clothSearchService = new ClothSearchService();
            imageMatcher       = ClothUtil.ImageMatcherInst;

            aDesc = new AlgorithmDesc();

            // temp
            rbtnCombine.IsEnabled   = false;
            txtModifyName.IsEnabled = false;

            //picNames = new List<string>();

            isValid = RegisterUtil.VerifyLogin();
        }
Ejemplo n.º 14
0
        // Before LockBits it took about 3s 500ms
        // After LockBits it took about 1s 600ms
        // Multithreading FTW. It takes about 130ms now!
        static void Main(string[] args)
        {
            while (true)
            {
                var gameScreen  = Image.FromFile("gameScreen.png");
                var spellNeedle = Image.FromFile("spellNeedle.png");

                var imageMatcher = new ImageMatcher();
                var found        = imageMatcher.FindNeedle(gameScreen, spellNeedle);

                var seconds     = imageMatcher.LastOperationTime.ToString("ss");
                var miliseconds = imageMatcher.LastOperationTime.ToString("fff");
                Console.WriteLine($"{(found.HasValue ? "Found" : "Not found")} in {seconds}s {miliseconds}ms {(found.HasValue ? $"on position {found.Value.ToString()}" : "")}");

                gameScreen.Dispose();
                spellNeedle.Dispose();

                Console.WriteLine("Hit enter to repeat.");
                Console.ReadLine();
            }
        }
Ejemplo n.º 15
0
        public void TestPick_FileList_Cnt()
        {
            var fileList = new List <ImageMatcher.FileEntry>();

            fileList.Add(GetFileEntry(2013, 10, 11, "file1.jpg"));
            fileList.Add(GetFileEntry(2013, 10, 11, "file2.jpg"));
            fileList.Add(GetFileEntry(2013, 10, 11, "file3.jpg"));

            var im = new ImageMatcher();

            im.FileList   = fileList;
            im.SearchMode = true;

            var entry1 = im.Pick(new DateTime(2013, 10, 11, 8, 25, 0), 0);
            var entry2 = im.Pick(new DateTime(2013, 10, 11, 8, 25, 0), 1);

            Assert.AreEqual(0, entry1.Cnt);
            Assert.AreEqual(1, entry2.Cnt);
            Assert.AreEqual(3, entry1.Filematches.Count());
            Assert.AreEqual(3, entry2.Filematches.Count());
        }
Ejemplo n.º 16
0
        public void ImageMatcherThresholdTest()
        {
            var imageMatcher  = new ImageMatcher();
            var starScreen    = Image.FromFile("starScreen.png");
            var starNeedle100 = Image.FromFile("starNeedle100.png");
            var starNeedle75  = Image.FromFile("starNeedle75.png");

            Assert.AreNotEqual(imageMatcher.FindNeedle(starScreen, starNeedle100), null);

            imageMatcher.Threshold = 0.8f;

            Assert.AreNotEqual(imageMatcher.FindNeedle(starScreen, starNeedle100), null);
            Assert.AreEqual(imageMatcher.FindNeedle(starScreen, starNeedle75), null);

            imageMatcher.Threshold = 0.75f;

            Assert.AreNotEqual(imageMatcher.FindNeedle(starScreen, starNeedle100), null);
            Assert.AreNotEqual(imageMatcher.FindNeedle(starScreen, starNeedle75), null);

            starScreen.Dispose();
            starNeedle100.Dispose();
            starNeedle75.Dispose();
        }
Ejemplo n.º 17
0
 /// <summary>
 /// Constructs a pattern.
 /// </summary>
 /// <param name="bitmap">Base image.</param>
 /// <param name="threshold">Similarity threshold.</param>
 /// <param name="imageMatcher">Matching method.</param>
 public ImagePattern(Bitmap bitmap, double threshold, ImageMatcher imageMatcher)
 {
     Image     = bitmap;
     Threshold = threshold;
     Matcher   = imageMatcher;
 }
Ejemplo n.º 18
0
        static void testClothSearch()
        {
            Console.WriteLine("begin");
            ImageMatcher im = new ImageMatcher();

            im.LuvInit(@"E:\projects\ClothSearch\codes\trunk\data\luv.dat");

            String selectedPath = @"E:\pic_skindetect\img_lib";

            string[] jpgFiles = Directory.GetFiles(selectedPath, "*.jpg");
            string[] gifFiles = Directory.GetFiles(selectedPath, "*.gif");
            string[] pngFiles = Directory.GetFiles(selectedPath, "*.png");
            string[] bmpFiles = Directory.GetFiles(selectedPath, "*.bmp");
            int      nFiles   = jpgFiles.Length + gifFiles.Length + pngFiles.Length + bmpFiles.Length;

            if (nFiles == 0)
            {
                return;
            }

            List <String> picNames = new List <string>(nFiles);

            picNames.AddRange(jpgFiles);
            picNames.AddRange(gifFiles);
            picNames.AddRange(pngFiles);
            picNames.AddRange(bmpFiles);

            Console.WriteLine("begin extract");
            List <float[]> tcs = new List <float[]>();
            List <float[]> ccs = new List <float[]>();
            List <string>  fns = new List <string>();

            foreach (String picName in picNames)
            {
                ccs.Add(im.ExtractRGBSeparateColorVector(picName, 8, new int[] { -1 }));
                tcs.Add(im.ExtractDaubechiesWaveletVector(picName));
                fns.Add(picName);
            }

            Console.WriteLine("begin calculate color md");
            StreamWriter sw    = File.CreateText(@"E:\projects\ClothSearch\codes\trunk\data\testcolor.txt");
            List <float> ccsMd = new List <float>();

            for (int i = 0; i < ccs.Count; ++i)
            {
                for (int j = 0; j < ccs.Count; ++j)
                {
                    ccsMd.Add(calcManhattanDistance(ccs[i], ccs[j]));
                }
                ccsMd.Sort();
                sw.WriteLine(fns[i]);
                foreach (float md in ccsMd)
                {
                    sw.WriteLine(md);
                }
                ccsMd.Clear();
            }
            sw.Close();


            Console.WriteLine("begin calculate texture md");
            sw = File.CreateText(@"E:\projects\ClothSearch\codes\trunk\data\testtexture.txt");
            List <float> tcsMd = new List <float>();

            for (int i = 0; i < tcs.Count; ++i)
            {
                for (int j = 0; j < tcs.Count; ++j)
                {
                    tcsMd.Add(calcManhattanDistance(tcs[i], tcs[j]));
                }

                tcsMd.Sort();
                sw.WriteLine(fns[i]);
                foreach (float md in tcsMd)
                {
                    sw.WriteLine(md);
                }
                tcsMd.Clear();
            }

            sw.Close();
        }
Ejemplo n.º 19
0
 /// <summary>
 /// Constructs a pattern.
 /// </summary>
 /// <param name="filename">Base image file path.</param>
 /// <param name="imageMatcher">Matching method.</param>
 public ImagePattern(string filename, ImageMatcher imageMatcher) : this(new Bitmap(filename), imageMatcher)
 {
 }
Ejemplo n.º 20
0
        static void testClothSearch2()
        {
            Console.WriteLine("begin");
            ImageMatcher im = new ImageMatcher();

            String selectedPath = @"E:\pic_skindetect\img_lib";

            string[] jpgFiles = Directory.GetFiles(selectedPath, "*.jpg");
            string[] gifFiles = Directory.GetFiles(selectedPath, "*.gif");
            string[] pngFiles = Directory.GetFiles(selectedPath, "*.png");
            string[] bmpFiles = Directory.GetFiles(selectedPath, "*.bmp");
            int      nFiles   = jpgFiles.Length + gifFiles.Length + pngFiles.Length + bmpFiles.Length;

            if (nFiles == 0)
            {
                return;
            }

            List <String> picNames = new List <string>(nFiles);

            picNames.AddRange(jpgFiles);
            picNames.AddRange(gifFiles);
            picNames.AddRange(pngFiles);
            picNames.AddRange(bmpFiles);

            Console.WriteLine("begin extract");
            List <float[]> tcs = new List <float[]>();
            List <float[]> ccs = new List <float[]>();
            List <string>  fns = new List <string>();

            foreach (String picName in picNames)
            {
                //ccs.Add(im.ExtractCooccurrenceVector(picName));
                tcs.Add(im.ExtractGaborVector(picName));
                fns.Add(picName);
            }

            Console.WriteLine("begin calculate color md");
            StreamWriter sw    = File.CreateText(@"E:\projects\ClothSearch\codes\trunk\data\testCooccurrence.txt");
            List <float> ccsMd = new List <float>();

            for (int i = 0; i < ccs.Count; ++i)
            {
                for (int j = i + 1; j < ccs.Count; ++j)
                {
                    ccsMd.Add(calcManhattanDistance(ccs[i], ccs[j]));
                }
            }
            ccsMd.Sort();
            foreach (float md in ccsMd)
            {
                sw.WriteLine(md);
            }
            sw.Close();

            /*
             * Console.WriteLine("begin calculate texture md");
             * sw = File.CreateText(@"E:\projects\ClothSearch\codes\trunk\data\testGabor.txt");
             * List<float> tcsMd = new List<float>();
             * for (int i = 0; i < tcs.Count; ++i)
             * {
             *  for (int j = i+1; j < tcs.Count; ++j)
             *  {
             *      tcsMd.Add(calcManhattanDistance(tcs[i], tcs[j]));
             *  }
             *
             *
             * }
             * tcsMd.Sort();
             * foreach (float md in tcsMd)
             * {
             *  sw.WriteLine(md);
             * }
             *
             * sw.Close();*/
        }
Ejemplo n.º 21
0
 static ClothUtil()
 {
     imageMatcher = new ImageMatcher();
     imageMatcher.LuvInit(SearchConstants.LuvFileName);
 }
Ejemplo n.º 22
0
 /// <summary>
 /// Constructs a pattern.
 /// </summary>
 /// <param name="bitmap">Base image.</param>
 /// <param name="imageMatcher">Matching method.</param>
 public ImagePattern(Bitmap bitmap, ImageMatcher imageMatcher) : this(bitmap, DefaultThreshold, imageMatcher)
 {
 }
Ejemplo n.º 23
0
        public void WriteTex()
        {
            _copyList = new List <Tuple <string, string> >();

            var txtFiles = Directory.EnumerateFiles(ChatDir, "*.txt");

            if (txtFiles.Count() != 1)
            {
                throw new ArgumentException("Invalid number of .txt-files found: " + txtFiles.Count());
            }

            var txtInputPath = txtFiles.First();

            Console.WriteLine($"Using {txtInputPath} as input");

            var namePrefix = Path.GetFileName(txtInputPath);

            namePrefix = namePrefix.Substring(0, namePrefix.Length - 4);
            var texOutputPath = Path.Combine(OutputDir, namePrefix + ".tex");

            var matchInputPath  = Path.Combine(ConfigDir, namePrefix + ".match.xml");
            var matchOutputPath = Path.Combine(OutputDir, namePrefix + ".match.xml");
            var im = new ImageMatcher();

            if (File.Exists(matchInputPath))
            {
                Console.WriteLine($"Loading matches '{matchInputPath}'");
                im.LoadMatches(matchInputPath);
                im.SearchMode = false;
            }
            else
            {
                if (ImagePoolDir == null)
                {
                    im.SearchMode = false;
                }
                else
                {
                    Console.WriteLine($"Loading pool images from '{ImagePoolDir}'");
                    im.LoadFiles(ImagePoolDir);
                    im.SearchMode = true;
                }
            }

            var parser = new WhatsappParser(txtInputPath, im);

            var sb = new StringBuilder();

            sb.AppendLine(_header);

            IMessage msg;
            DateTime last = DateTime.MinValue;

            while ((msg = parser.NextMessage()) != null)
            {
                if (TimeDiffer(last, msg.Timepoint))
                {
                    sb.AppendLine(@"\begin{center}" + GetDateString(msg.Timepoint) + @"\end{center}");
                }

                last = msg.Timepoint;

                if (msg is TextMessage)
                {
                    AppendTextMessage(msg as TextMessage, sb);
                }
                else if (msg is ImageMessage)
                {
                    AppendImageMessage(msg as ImageMessage, sb);
                }
                else if (msg is MediaOmittedMessage)
                {
                    AppendMediaOmittedMessage(msg as MediaOmittedMessage, sb);
                }
                else if (msg is MediaMessage)
                {
                    AppendMediaMessage(msg as MediaMessage, sb);
                }
            }

            sb.AppendLine(_footer);

            Console.WriteLine($"Writing tex file to '{texOutputPath}'");
            File.WriteAllText(texOutputPath, sb.ToString());

            Console.WriteLine($"Writing match file to '{matchOutputPath}'");
            im.Save(matchOutputPath);

            Console.WriteLine($"Copy emojis to '{EmojiOutputDir}'");
            CopyList();
        }