public string Apply(string input_dir, string output_dir, string fn, double size_ratio, bool preprocessing)
        {
            //if (!Directory.Exists(dir))
            //    Directory.CreateDirectory(dir);
            //if (!Directory.Exists(dir + "Results"))
            //    Directory.CreateDirectory(dir + "Results");
            this.output_dir = output_dir;
            Bitmap srcimg = new Bitmap(input_dir + fn);
            //Log.DeleteAll(output_dir);
            //Log.SetOutputDir(output_dir);

            // assigning parameters
            mw = srcimg.Width;
            mh = srcimg.Height;
            initial_string_list.Clear();
            char_blobs = null;

            ImageSlicer imgslicer = new ImageSlicer();
            List<TextString> text_string_list = new List<TextString>();
            List<Bitmap> img_list = imgslicer.Apply(4, 4, 100, srcimg);
            //srcimg.Dispose();
            //srcimg= null;

            //Log.SetStartTime();
            for (int s = 0; s < img_list.Count; s++)
            {
                RemoveBoarderCC removeBoarderCC = new RemoveBoarderCC();
                img_list[s] = removeBoarderCC.Apply(img_list[s]);
                ConditionalDilationAutomatic cda = new ConditionalDilationAutomatic();
                cda.ang_threshold = angle_ratio;

                //Log.SetStartTime();
                string outImagePath = output_dir+s+".png";
                cda.Apply(8, img_list[s], size_ratio, angle_ratio, preprocessing, outImagePath);
                Bitmap dilatedimg = new Bitmap(outImagePath);
                //time = Log.GetDurationInSeconds();
                //Log.WriteLine("CDA: "+s+": "+ time);

                //Log.SetStartTime();
                DetectTextStrings detectTS = new DetectTextStrings();
                List<TextString> string_list = detectTS.Apply(img_list[s], dilatedimg);
                //time = Log.GetDurationInSeconds();
                //Log.WriteLine("Detect: " + s + ": " + time);

                List<Bitmap> string_img_list = new List<Bitmap>();
                for (int i = 0; i < string_list.Count; i++)
                    string_img_list.Add(string_list[i].srcimg);

                int[] offset = imgslicer.xy_offset_list[s];

                for (int i = 0; i < string_list.Count; i++)
                {
                    string_list[i].x_offset = offset[0];
                    string_list[i].y_offset = offset[1];
                    mts.AddTextString(string_list[i]);
                }
                img_list[s].Dispose();
                img_list[s] = null;
            }
            //time = Log.GetDurationInSeconds();
            //Log.WriteLine("CDA time: "+time);
            //Log.WriteLine("Start to detect orientation");
            //Log.SetStartTime();
            tnum = 8;
            DetectOrientation();
            //time = Log.GetDurationInSeconds();
            //Log.WriteLine("Detect orientation time: " + time);

            //Log.WriteLine("Start to detect short string orientation");
            //Log.SetStartTime();
            for (int i = 0; i < mts.text_string_list.Count; i++)
            {
                if (mts.text_string_list[i].char_list.Count <= 3)
                {
                    List<int> nearest_string_list = findNearestSrings(i, mts.text_string_list);
                    int initial_orientation_count = mts.text_string_list[i].orientation_list.Count;
                    for (int j = 0; j < nearest_string_list.Count; j++)
                        mts.text_string_list[i].orientation_list.AddRange(mts.text_string_list[nearest_string_list[j]].orientation_list);
                    RotateImage rotate = new RotateImage();
                    for (int j = initial_orientation_count; j < mts.text_string_list[i].orientation_list.Count; j++)
                        mts.text_string_list[i].rotated_img_list.Add(rotate.Apply(mts.text_string_list[i].srcimg, (int)mts.text_string_list[i].orientation_list[j]));
                }

            }
            //time = Log.GetDurationInSeconds();
            //Log.WriteLine("Detect short string orientation time: " + time);

            //Log.WriteLine("Start to write results");
            //Log.SetStartTime();
            Graphics g = Graphics.FromImage(srcimg);
            for (int i = 0; i < mts.text_string_list.Count; i++)
            {
                List<Bitmap> all_string_img_list = new List<Bitmap>();
                    int x = mts.text_string_list[i].mass_center.X;
                    int y = mts.text_string_list[i].mass_center.Y;
                    for (int s = 0; s < mts.text_string_list[i].orientation_list.Count; s++)
                    {
                        string slope = Convert.ToInt16(mts.text_string_list[i].orientation_list[s]).ToString();
                         ImageStitcher imgstitcher1 = new ImageStitcher();
                         Bitmap single_img = imgstitcher1.ExpandCanvas(mts.text_string_list[i].rotated_img_list[s],20);
                        Log.WriteBitmap2FolderExactFileName(output_dir, single_img, i + "_p_" + mts.text_string_list[i].char_list.Count + "_" + x + "_" + y + "_s_" + slope + "_" + mts.text_string_list[i].bbx.X + "_" + mts.text_string_list[i].bbx.Y + "_" + mts.text_string_list[i].bbx.Width + "_" + mts.text_string_list[i].bbx.Height);
                    }
                    Font font2 = new Font("Arial", 20);
                    //g.DrawString(i.ToString(), font2, Brushes.Black, mts.text_string_list[i].bbx.X,mts.text_string_list[i].bbx.Y);
                    g.DrawRectangle(new Pen(Color.Black, 3), mts.text_string_list[i].bbx);
                    ImageStitcher imgstitcher2 = new ImageStitcher();
                    Bitmap srcimg2 = imgstitcher2.ExpandCanvas(mts.text_string_list[i].srcimg, 20);
                    Log.WriteBitmap2FolderExactFileName(output_dir, srcimg2, i + "_p_" + mts.text_string_list[i].char_list.Count + "_" + x + "_" + y + "_s_0" + "_" + mts.text_string_list[i].bbx.X + "_" + mts.text_string_list[i].bbx.Y + "_" + mts.text_string_list[i].bbx.Width + "_" + mts.text_string_list[i].bbx.Height);
            }
            g.Dispose();
            //time = Log.GetDurationInSeconds();
            //Log.WriteLine("Write results time: " + time);
            return null;
        }
        public void Apply(string input_dir, string output_dir, string fn, int char_size, double size_ratio, bool preprocessing, int tnum, string lang)
        {
            MergeTextStrings mts = new MergeTextStrings();

            ImageSlicer imgslicer = new ImageSlicer();
            List<TextString> text_string_list = new List<TextString>();
            List<string> imgpath_list = imgslicer.Apply(1, 1, 100, input_dir + fn, output_dir);

            Log.WriteLine("Grouping text strings...");
            for (int s = 0; s < imgpath_list.Count; s++)
            {
                Bitmap srcimg = null;

                if (lang == "eng")
                {
                    using (Bitmap tileimg = new Bitmap(imgpath_list[s]))
                    {
                        RemoveBoarderAndNoiseCC removeBoarderAndNoiseCC = new RemoveBoarderAndNoiseCC();
                        srcimg = removeBoarderAndNoiseCC.Apply(tileimg, char_size, 0.18);
                        Log.WriteBitmap2FolderExactFileName(output_dir, srcimg, "CDAInput.png");
                    }
                }
                else
                {
                    using (Bitmap tileimg = new Bitmap(imgpath_list[s]))
                    {
                        RemoveBoarderCC removeBoarderCC = new RemoveBoarderCC();
                        srcimg = removeBoarderCC.Apply(tileimg);
                        Log.WriteBitmap2FolderExactFileName(output_dir, srcimg, "CDAInput.png");
                    }
                }
                ConditionalDilationAutomatic cda = new ConditionalDilationAutomatic();
                cda.ang_threshold = angle_ratio;
                string outputImagePath = output_dir + s + ".png";
                cda.Apply(tnum, srcimg, size_ratio, angle_ratio, preprocessing, outputImagePath);

                using (Bitmap dilatedimg = new Bitmap(outputImagePath))
                {
                    DetectTextStrings detectTS = new DetectTextStrings();
                    List<TextString> string_list = detectTS.Apply(srcimg, dilatedimg);
                    List<Bitmap> string_img_list = new List<Bitmap>();
                    for (int i = 0; i < string_list.Count; i++)
                        string_img_list.Add(string_list[i].srcimg);

                    int[] offset = imgslicer.xy_offset_list[s];

                    for (int i = 0; i < string_list.Count; i++)
                    {
                        string_list[i].x_offset = offset[0];
                        string_list[i].y_offset = offset[1];
                        mts.AddTextString(string_list[i]);
                    }
                }
                using (Bitmap CDAInputwithLabel=new Bitmap (outputImagePath))
                {
                    Graphics g = Graphics.FromImage(CDAInputwithLabel);
                    for (int i = 0; i < mts.text_string_list.Count; i++)
                    {
                        Font font = new Font("Arial", 20);
                        g.DrawString(i.ToString(), font, Brushes.Red, mts.text_string_list[i].bbx.X, mts.text_string_list[i].bbx.Y);

                        g.DrawRectangle(new Pen(Color.Green, 4), mts.text_string_list[i].bbx);

                    }
                    Log.WriteBitmap2FolderExactFileName(output_dir, CDAInputwithLabel, "CDAInputwithLabel.png");
                    g.Dispose();
                    g=null;
                }
                srcimg.Dispose();
                srcimg = null;
            }

            Log.WriteLine("Detecting long string orientation...");
            DetectTextOrientation detectTextOrientation = new DetectTextOrientation();
            detectTextOrientation.Apply(mts, tnum);

            Log.WriteLine("Detecting short string orientation...");
            for (int i = 0; i < mts.text_string_list.Count; i++)
            {
                if (mts.text_string_list[i].char_list.Count <= 3)
                {
                    List<int> nearest_string_list = detectTextOrientation.findNearestSrings(i, mts.text_string_list);
                    int initial_orientation_count = mts.text_string_list[i].orientation_list.Count;
                    for (int j = 0; j < nearest_string_list.Count; j++)
                        mts.text_string_list[i].orientation_list.AddRange(mts.text_string_list[nearest_string_list[j]].orientation_list);
                    for (int j = initial_orientation_count; j < mts.text_string_list[i].orientation_list.Count; j++)
                    {
                        RotateBilinear filter = new RotateBilinear(mts.text_string_list[i].orientation_list[j]);
                        Bitmap rotateimg = ImageUtils.InvertColors(filter.Apply(ImageUtils.InvertColors(mts.text_string_list[i].srcimg)));
                        mts.text_string_list[i].rotated_img_list.Add(rotateimg);
                    }
                }
            }

            Log.WriteLine("Writing string results...");
            mts.WriteBMP(output_dir);
        }