mrgloom
mrgloom

Reputation: 21622

Reading images in multiple threads

I have some C# code for reading images from disk and then crop them(optionally resize) and then save them. But it looks like only 30% of CPU is used during operation, can I use multithreading to improve speed or disk read speed is bottleneck? How to properly load cpu and disk for max performance?

    string path = args[0];

    int counter = 0;
    foreach (string dir in Directory.GetDirectories(path))
    {
        Console.WriteLine("processing: " + dir);

        //create folder for faces
        string dir_path = dir + "\\face";
        System.IO.Directory.CreateDirectory(dir_path);

        try
        {
            string ini_path = dir + "\\.picasa.ini";
            if (File.Exists(ini_path))
            {
                FileIniDataParser parser = new FileIniDataParser();
                IniData data = parser.LoadFile(ini_path);
                foreach (SectionData section in data.Sections)
                {
                    if (section.SectionName.Contains(".jpg"))
                    {
                        string rects = data[section.SectionName]["faces"];

                        string[] str_rects = GetRectStrings(rects);

                        for (int i = 0; i < str_rects.Length; ++i)
                        {
                            Bitmap img = (Bitmap)Image.FromFile(dir + "\\" + section.SectionName, true);

                            RectangleF rectF = GetRectangle(str_rects[i]);

                            int im_w = img.Width;
                            int im_h = img.Height;

                            rectF.X = rectF.X * im_w;
                            rectF.Y = rectF.Y * im_h;
                            rectF.Width = rectF.Width * im_w;
                            rectF.Height = rectF.Height * im_h;

                            Bitmap bmpCrop = img.Clone(rectF, img.PixelFormat);

                            string text_path = Directory.GetParent(path).FullName + "\\db.txt";
                            string crop_path = dir + "\\face\\" +
                                Path.GetFileNameWithoutExtension(dir + "\\" + section.SectionName) + "_" + i.ToString() + "_crop.png";

                            bool resize = true;
                            if (resize)
                            {
                                Bitmap resized = new Bitmap(bmpCrop, new Size(24, 32));//вынести в параметры
                                resized.Save(crop_path,
                                    System.Drawing.Imaging.ImageFormat.Png);

                                Bitmap gr = ConvertGray(resized);

                                AppendToTxtFile(gr, text_path);
                            }
                            else
                            {
                                bmpCrop.Save(crop_path,
                                    System.Drawing.Imaging.ImageFormat.Png);

                                Bitmap gr = ConvertGray(bmpCrop);

                                AppendToTxtFile(gr, text_path);
                            }

                            counter++;
                        }
                    }
                }
            }

        }
        catch
        {
            Console.WriteLine("problem in: " + dir);
        }

        Console.WriteLine("rects: " + counter.ToString());
    }

    Console.WriteLine("all done");
    Console.ReadLine();

Upvotes: 1

Views: 1105

Answers (1)

Yuval Itzchakov
Yuval Itzchakov

Reputation: 149538

You have both the elements of reading from disk, which is probably consuming some time depending on what your disk quality is, but you are still limited by IO work in general and doing CPU bound work of resizing the images.

If you're bound to .NET 3.5, i'd suggest using FileStreams.BeginRead (which uses the older asynchronous pattern) for loading the images asynchrnously and then firing up background workers to take care of resizing your image to maximize CPU usage.

Upvotes: 2

Related Questions