Saving images fast enough

I’m starting out with tasks and the .net bindings, so not sure if this is my own code being messy or something else alltogether.

The code below works just fine with .jpg extention, but with png it gets very weird. With the jpg extention there timestamps are spot on, and I get a nice file with 100 images. With .png extention, not so much. I don’t fully understand why that should be the case to be honest. I aquire the images at 5 herz, and they are 5mp rgb images.

Saving an png itself takes about 2-3 seconds, seems like a lot, but turning them into threads should resolve that (meaning there would be about 3*5 images max being saved at any given time).

namespace ConsoleApplication2
{
  class Program
  {
    static void Main(string[] args)
    {
      Device firstDevice = DeviceFactory.Open("Genicam.vin");
      firstDevice.Stream.Start();

      try
      {
        for (int i = 0; i < 100; i++)
        {
          using (StreamImage image = firstDevice.Stream.Wait()) 
          {
            var cloneIMG = image.Clone();
            Task t = Task.Run(() => asyncSaveImage(cloneIMG));
          }
        }
      }
      catch (Exception)
      {
        throw;
      }
    }

    private static void asyncSaveImage(Image image)
    {
      var location = string.Format(@"C:\LOG\{0:yyyy/MM/dd HH-mm-ss-fff}.png", DateTime.Now);
      image.Save(location);
    }
  }
}

Hi @CvK!

You might be interested in this post:
https://forum.commonvisionblox.com/t/different-performance-when-saving-different-formats/252

Hi @illusive,

Had allready found that, but it doesnt completely answer my question though. If I hand over the save task to threads, it shouldn’t matter all that much in overall speed how quickly I am able to save right? It will only result in perhaps a lot of tasks being active at any given moment.

Instead, I see little to no gain by handing it over to tasks. Which is unexpected for me.

Offtopic:

just a little hint:

DateTime.Now.ToString("yyyy_MM_dd_HHmmss")

Cheers
Chris

Hi @CvK,

handing over the process of saving the images to tasks will increase the speed of your application as you will not be “stuck” for 2-3 seconds everytime you try to save an image.
Instead you simply have x Tasks that are writing images to the disk while already sending off new tasks.
I dont see why this should increase the speed of one save process… you simply are able to acquire new images faster.

(If I dont miss anything right now).

Cheers
Chris

Hmm, well, thats the weird thing! When writing png, only 16 images of my 100 images are actually sucesfully stored @ 5 herz acquisition.

edit: it was 8-9 images saved, the result of 16 was from 2 runs.

Just out of curiosity… have you tried increasing the NumBuffers?
I am not sure if this changes anything but it would be interesting.
Just go for 100 Buffers.

You could also record the 100 images with RingBuffer LockMode = On (You need minimum 100 buffers for that) and then safe after the images are recorded, which, I would say, is the correct way of handling situations where youre recording faster than youre writing images

1 Like

I clone the image, and then save it and hand it over to a task. This should not be influenced by the number of ringbuffers right?

I’ve gotten this to work using the tobitmap example in the past in the c-style API so I know this isn’t a doomed approach.

Edit:
Just tried it with 100 buffers, no effect whatsoever :frowning: exact same results as before. Not locked, though, but the weird behavior of the saving still exists… Why isn’t the saving improbed by handing it over to tasks as I expect?

One last approach:

I am not sure, what happens to the fired tasks if you hit the end of your main. I would assume they will very likely just be lost.

You could make your Save() method async (as the name already implies), create a list of tasks and wait for each element of that list to have finished bevore leaving the programm.

Also interesting:

1 Like

Hmm, right! that makes sense. I shall attempt it :slight_smile:

1 Like

There is one general warning, that I would like to post here: There is no guarantee that multi threaded saving of images will generally work for all formats. With *.bmp and *.mio I am fairly confident (and if you find that it fails this would qualify as a bug in my opinion), but all the other formats are handled through the open source libraries mentioned here (namely jasper, libjpg, libpng, libtiff, openjpeg) and as far as I know not all of them make thread-safety guarantees…

With *.png files you’re lucky :four_leaf_clover: insofar as the libpng documentation says “Libpng is thread safe, provided the threads are using different instances of the structures.”. The latter condition is satisfied in :cvb: so you should be fine. But I assume using your approach with e.g. *.jpg files would cause issues.

1 Like

The .png is the one causing issues actually. But, that might be caused by the fact that the .jpg saving is actually faster and doesn’t really need the parallelization.

I’ll try some of the suggestions here and post my findings back here. I’m probably not going to be the last one trying to save images after all :wink:

:+1:
(with issues I meant symptoms far worse than what you describe like SEHExceptions and its siblings…)

Right, none of that so far, lets hope they don’t suddenly pop up! :crossed_fingers: