Schnelle Abspeicherung von RAW-Bildern aus Arbeitsspeicher



  • Dieser Thread wurde von Moderator/in pumuckl aus dem Forum C++ in das Forum ANSI C verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • hi!
    unter windows ist das "b" flag unerlässlich, sonst hast du beim schreiben mehr bytes in der datei und beim lesen weniger im arbeitsspeicher ...
    und lass das ccs=UTF-16LE weg, eine bitmap ist keine textdatei.



  • fp = fopen(filename,"wb");
    setbuf (fp,NULL);
    fwrite(image_ptr, 1, height*width*nr_of_buffer*2, fp);
    fclose(fp);
    

    bringt einen Geschwindigkeitsvorteil. 16 bit pro Pixel und mehrere Frames pro Datei sind wahrscheinlich Absicht?
    Ansonsten bleibt, die WinAPI-Funktion WriteFile zu verwenden (oder eben eine Lib, die das ganze wrappt), da du ohnehin unter Windows zu arbeiten scheinst und die fwrite-Implementation im Binärmodus suboptimal zu sein scheint.
    Mit WriteFile geht es bei mir gut doppelt so schnell.



  • Vielen Dank für eure Antworten.

    Das mit den 16 Bit pro Pixel und mehreren Frames pro Datei ist so gewollt ja. Und ich arbeite unter Windows.

    Ich werd eure Tips mal ausprobieren und mich dann wieder melden.



  • Das es so langsam ist liegt daran, das die Datei unnötig im UTF 16 Format geschrieben wird (UTF-16LE). Was bei Bitmaps natürlich Nonsens ist.
    Generell ist WriteFile nicht schneller als fwrite, nicht das ich wüsste.



  • lahmarschig0r schrieb:

    Das es so langsam ist liegt daran, das die Datei unnötig im UTF 16 Format geschrieben wird (UTF-16LE). Was bei Bitmaps natürlich Nonsens ist.
    Generell ist WriteFile nicht schneller als fwrite, nicht das ich wüsste.

    Es macht aber keinen Unterschied, wenn man es weglässt, weder in Hinsicht auf Geschwindigkeit noch auf Dateiinhalt. Wahrscheinlich wird der Parameter ignoriert, schließlich passt er mit dem Binärmodus nicht gerade gut zusammen.



  • Hotze schrieb:

    Jetzt zum Problem. Verwende ich das Binary-Flag "b" für fopen, braucht mein Programm mehr wie 4 mal so lange zum Speichern eines Bildes wie ohne Flag, beziehungsweise mit dem Text-Flag "t". Ohne "b" Flag werden jedoch die Grauwerte des Bildes als Zeichen interpretiert und teilweise verändert, was die Bildinformation total zerstört.

    Müsste nicht normalerweise eine Binary-Speicherung schneller vonstatten gehen wie die Text-Speicherung?
    Habt ihr eine Idee was ich falsch mache, bzw. verbessern könnte?

    Hier ein kleiner Programmauschnitt dazu:

    FILE *fp;
    do{
    sprintf_sfilename(, "d:\\Photonfocus_cam\\Buffer\\buffer%06d.raw", i);
    fp = fopen(filename,"wb, ccs=UTF-16LE");
    fwrite(image_ptr, 2, height*width*nr_of_buffer, fp);
    fclose(fp);
    i++;
    }while(i<nb_frame);
    

    klar müsste 'fwrite' im binary mode schneller sein. dein code zeigt auch irgendwie das problem nicht, aber zähl mal die anzahl der 'fwrite' aufrufe in beiden fällen und anzahl der bytes, die pro geschrieben werden. vielleicht kommt deine 'fwrite-schleife' im binary-mode zu oft dran, so dass sie rechenzeit from framegrabber klaut und/oder sehr oft mit völlig kleinen datenmengen gefüttert wird. bei so asynchronen reads/writes gibts manchmal solche effekte.
    🙂



  • ^^ach ja, ich blindfisch, mach mal dieses 'ccs=UTF-16LE' da weg, vielleicht isses das.
    🙂



  • Ich hab mein Programm nach euren Vorschlägen geändert:

    FILE *fp;
    do{
    sprintf_s(filename, "d:\\Photonfocus_cam\\Buffer\\buffer%06d.raw", i);
    fp = fopen(filename,"wb");
    setbuf (fp,NULL);
    fwrite(image_ptr, 1, height*width*nr_of_buffer*2, fp);
    fclose(fp);
    i++;
    }while(i<nb_frame);
    

    Leider hat sich an der Schreibgeschwindigkeit so gut wie gar nichts geändert.

    Eine Version mit WriteFile hab ich bis jetzt noch nicht zum Laufen gegriegt, da schreibt er mir bis jetzt nur leere Datein ohne Inhalt.

    klar müsste 'fwrite' im binary mode schneller sein. dein code zeigt auch irgendwie das problem nicht, aber zähl mal die anzahl der 'fwrite' aufrufe in beiden fällen und anzahl der bytes, die pro geschrieben werden. vielleicht kommt deine 'fwrite-schleife' im binary-mode zu oft dran, so dass sie rechenzeit from framegrabber klaut und/oder sehr oft mit völlig kleinen datenmengen gefüttert wird. bei so asynchronen reads/writes gibts manchmal solche effekte.

    Also die Anzahl der gespeicherten Bytes stimmt genau mit der Bildgröße überein.
    Ein zu häufiges Aufrufen des fwrite Befehls fange ich mit einer Warteschleife in obiger Schleife ab:
    do{
    pic_nr = Fg_getLastPicNumber(fg,0);
    }while(pic_nr==pic_nr_old);
    Aber in die Warteschleife komme ich normal gar nicht (außer bei sehr kleinen Framerates), da das Abspeichern der Bilder zu lange dauert.

    Viel mehr Code hat mein Programm eigentlich gar nicht, außer ein paar Ausgaben, Paramatereinstellung und laden eines Configfiles mit der Hilfe des SDKs des Framegrabbers.

    Die Hardware stellt hier auch nicht den Flaschenhals dar. Im Rechner werkelt ein Raidcontroller im Raid 0 mit 4 Festplatten.

    Könnte es daran liegen das der Framegrabber kontinuierlich Bilder in den Arbeitsspeicher lädt und ich diese zeitgleich auslesen will? Aber das würde ja auch nicht erklären warum das Abspeichern als Textdatei 4 mal so schnell geht 😞



  • Hotze schrieb:

    Könnte es daran liegen das der Framegrabber kontinuierlich Bilder in den Arbeitsspeicher lädt und ich diese zeitgleich auslesen will? Aber das würde ja auch nicht erklären warum das Abspeichern als Textdatei 4 mal so schnell geht 😞

    Sollte man doch mal synchronisieren.



  • Hotze schrieb:

    Könnte es daran liegen das der Framegrabber kontinuierlich Bilder in den Arbeitsspeicher lädt und ich diese zeitgleich auslesen will? Aber das würde ja auch nicht erklären warum das Abspeichern als Textdatei 4 mal so schnell geht

    nicht wahr? das seltsame ist ja, dass ein 'fwrite', dass eigentlich mehr macht, als es muss, dafür sorgt, dass der gesamte vorgang schneller ist, als mit schnelleren 'fwrites'.

    Hotze schrieb:

    do{
    pic_nr = Fg_getLastPicNumber(fg,0);
    }while(pic_nr==pic_nr_old);
    Aber in die Warteschleife komme ich normal gar nicht (außer bei sehr kleinen Framerates), da das Abspeichern der Bilder zu lange dauert.

    trotzdem doof. hier verbrätst du rechenzeit, die der framegrabber brauchen könnte. füg in die schleife wenigstens ein 'Sleep(1)' ein, damit der scheduler zum nächsten thread schaltet.

    Hotze schrieb:

    FILE fp;
    do{
    sprintf_s(filename, "d:\\Photonfocus_cam\\Buffer\\buffer%06d.raw", i);
    fp = fopen(filename,"wb");
    setbuf (fp,NULL);
    fwrite(image_ptr, 1, height*width*nr_of_buffer
    2, fp);
    fclose(fp);
    i++;
    }while(i<nb_frame);

    der code passt irgendwie nicht zu dem, was du erzählst. wenn der framegrabber asynchron arbeitet, wie kannst du sicher sein, dass eine komplette datei geschrieben wird?

    folgender vorschlag:
    - benutz einen 'lock free' FIFO, etwa den: http://www.koders.com/c/fidA649E1A0EA070488C13F29677B14D7C09E3E0187.aspx
    - lass den framegrabber daten reinschreiben
    - mach die 'fwrite'-schleife etwa so (für eine datei):

    FILE *fp = fopen (...);
    int bytes_written = 0;
    char buff[2048]; // <-- 2048 grösse als beispiel
    while (bytes_written < FRAMESIZE)  // solange ein frame noch nicht voll ist
    {
       if (fifo_not_empty)  // wenn framegrabber daten erzeugt hat...
       {
          int bytes_read = fifo_get (buff, sizeof(buff)); // <-- so viel wie möglich holen
          fwrite (buff, 1, bytes_read, fp);  // in datei schreiben
          bytes_written += bytes_read;     // mitzählen
       }
       else
       {
          Sleep(0);  // <-- wenn nichts zu tun ist dann CPU abgeben
       }      
    }
    fclose (fp);
    

    ^^ nur so als beispiel, klappt, wenn das schreiben schneller geht als der grabber den fIFO füllt. ansonsten musste den grabber anhalten bzw. frames wegwerfen (je nachdem was besser passt).
    🙂


Anmelden zum Antworten