Forum: PC-Programmierung ILDA Dateien auslesen in C#


von Tobias K. (tobias_k622)


Lesenswert?

Hallo,

brauche folgende Anwendung: eine .ild Datei in C# auslesen (für eine 
Lasershow).

Brauche keine fertigen Code. Gibt es jedoch irgendwo ein gutes Tutorial 
oder eine Anleitung?

Bitte um kurze Rückmeldung.

MfG
Tobias

von jmp (Gast)


Lesenswert?

Hallo Tobias, das kommt darauf an, ob das .ild ein Textfile oder ein 
binäres File ist.

Für Text:
https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/file-system/how-to-read-from-a-text-file

Für binär:
https://docs.microsoft.com/en-us/dotnet/api/system.io.binaryreader

--jmp

von Stephan (Gast)


Lesenswert?

...und hier die "andere" seite:
https://www.ilda.com/technical.htm
Dort insb. "ILDA Image Data Transfer Format"

von Tobias K. (tobias_k622)


Angehängte Dateien:

Lesenswert?

Hallo,

keine Ahnung was .ild für ein Dateiformat ist. Im Anhang sieht man, dass 
der  ausgegebene Code komisch ist.

MfG
Tobias

von und zu (Gast)


Lesenswert?

Tobias K. schrieb:
> keine Ahnung was .ild für ein Dateiformat ist.
Dann belasse es besser dabei.
Es sind XY-RGB-Daten zu einzelnen Stützpunkten die per Laser abgefahren 
werden.
Wenn Du der Meinung bist, dass der
> Im Anhang sieht man, dass der  ausgegebene Code komisch ist.
dann wirst Du es auch nicht hin bekommen einen Parser dafür zu bauen.
Btw. gibt es auch noch mehrere ILDA-Formate teilweise mit Farbpaletten 
usw.

von Tobias K. (tobias_k622)


Lesenswert?

Ich frage genau deswegen im Forum, weil ich es eben nicht hinbekomme 
einen geeigneten Parser zu bauen. ;)

Gibt es irgendwelche Hilfestellungen im www, habe schon gesucht aber 
vergeblos

von Andreas M. (amesser)


Lesenswert?

Ich würde vorschlagen die Spezifikation zu lesen und danach 
implementieren. Fertig. Lächerliche 22 Seiten, Überall im Internet zu 
finden.

von Tobias K. (tobias_k622)


Lesenswert?

Wo finde ich so wichtige Infos? Suchen wie ILDA Files auslesen, etc. 
waren nicht sehr hilfreich :(

von Stephan (Gast)


Lesenswert?

Tobias K. schrieb:
> Wo finde ich so wichtige Infos?

??
z.B. in meinem Beitrag von 14:03

von Andreas M. (amesser)


Lesenswert?


von Hugo H. (hugo_hu)


Lesenswert?

Stephan schrieb:
> z.B. in meinem Beitrag von 14:03

Und - wo ist der fertige Arduino-Code dazu? Mach mal hin ;-)

von Stephan (Gast)


Lesenswert?

Hugo H. schrieb:
> Stephan schrieb:
>> z.B. in meinem Beitrag von 14:03
> Und - wo ist der fertige Arduino-Code dazu? Mach mal hin ;-)
s.u.a:
Tobias K. schrieb:
> Brauche keine fertigen Code.
;)

Lieber TO:
(kannst/willst/magst keinen Parser schreiben) || (weisst Du nicht wie 
das ILDA File-Format ist)

Für zweiteres: steht doch in der obigen Format-Beschreibung. ILDA.org 
war so freundlich, Dir das sogar alles aufzuschreiben.

Für ersteres: wie immer: was hast Du denn schon in (C#) codiert? und wo 
klemmt's genau...?

von Tobias K. (tobias_k622)


Lesenswert?

Hallo,

Hier mein bisheriger Code:
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5
using System.Threading.Tasks;
6
using System.IO;
7
8
namespace test_ilda
9
{
10
    class Program
11
    {
12
        static void Main(string[] args)
13
        {
14
            FileStream fs = new FileStream("bandsag.ild", FileMode.Open);
15
            BinaryReader br = new BinaryReader(fs);
16
17
            int ausgabe;
18
19
            for(int i = 0; i<100;i++) //100 ist eine beliebige Zahl :)
20
            {
21
                ausgabe = br.ReadInt32();
22
                Console.WriteLine(ausgabe);
23
            }
24
            
25
26
            Console.ReadLine();
27
        }
28
29
    }
30
}
Problem: Was mache ich mit diesen Werten? Habe die .pdf schon 100x 
durchgelesen, kenne mich jedoch nicht aus.

: Bearbeitet durch User
von Oliver S. (oliverso)


Lesenswert?

Tobias K. schrieb:
> Problem: Was mache ich mit diesen Werten?

Mal ganz blöd gefragt: wenn du nicht weißt, was das Datenformat 
überhaupt darstellt, und nicht weißt, was du mit dem Daten machen 
sollst, warum willst du da was parsen?

Oliver

von Tobias K. (tobias_k622)


Lesenswert?

Warum werde ich wohl in einem Forum fragen? Genau, weil ich mich nicht 
auskenne. Deshalb gibt es ja ein FORUM um Hilfe von anderen zu bekommen, 
und keine abwägigen Kommentare zu erhalten. Anstatt mir unnützes Wissen 
reinzudrücken (ich möchte diejenigen jetzt nicht ansprechen, die mir 
schon besser geholfen haben mit Links zu hilfreichen Seiten, etc.) 
könntet ihr mir helfen oder es einfach lassen. Punkt aus!

von Oliver S. (oliverso)


Lesenswert?

Und? Hast du das Data-Dokument auch gelesen?

Die Daten beginnen mit einem Header.

Dazu steht in dem Dokument:
1
4.2. Field Description
2
4.2.1. "ILDA"
3
Bytes 1 – 4. The ASCII letters ILDA, identifying an ILDA format header.
4

Du kannst jetzt mal raten, was dir diese Worte sagen wollen.
Wenn du drauf kommst, gehe weiter zu Byte 5 ff. Wenn nicht, such dir ein 
anderes Hobby.

Oliver

von Stephan (Gast)


Lesenswert?

Tobias K. schrieb:
> ausgegebene Code komisch ist.

1.)
Wenn Du diese Ausgabe mit dem von Dir dargestellten Progrämmchen 
erstellt hast, dann ist VOR den eigentlichen ILDA-Daten noch etwas 
anderes (gefühlt 2kByte)

Die ILDA Daten fangen mit "ILDA" im Header an...
Das ist bei anderen IDLA-Files (die ich im Netz gefunden habe) auch so.
Auch die Datei "bandsag.ild" (die man ebenfalls im Netzfindet) fängt 
korrekterweise mit "ILDA" an...
Irgedwas ist also schon mal an Deiner Datei "krumm"...

2.)
Ansonsten: Byte(-gruppen)-weise nach einlesen und die eingelesenen Daten 
in Deine programminternen Strukturen/Klassen schreiben/mappen...
Schematisches Beispiel:
Byte(s) [1..4] nach HEADER.ILDA_ID[4]
Byte(s) [5..7] nach HEADER.RSVD_1[3]
Byte(s) [8] nach HEADER.FORMATCODE[1]
...
Byte(s) [32] nach HEADER.RSVD_2[1]

Durch die Daten dann blockweise UND FormatCode-längenabhängig 
durchiterieren. Endianess prüfen!

3.)
Was auch immer Du dann mit den Daten machen möchtest... nur zu.

von Random .. (thorstendb) Benutzerseite


Lesenswert?

Das ILDA Format ist recht simpel aufgebaut, meisst aus gleich großen 
Einträgen, die jeweils über einen Header erkannt werden.
Für einen Player (in C auf Cortex-M3) habe ich die komplette Spec in 
mehrere struct/union gegossen, so kann man da ganz einfach 
durchspazieren und spart sich buffer increments.
Achtung: Alle 16Bit Daten sind BE!

https://www.ilda.com/resources/StandardsDocs/ILDA_IDTF14_rev011.pdf

Vom Prinzip her:
1
typedef _PACKED struct {       // 1..32
2
  _PACKED union {
3
    unsigned char buf[32];      // 32 byte
4
    
5
    _PACKED struct {
6
      _PACKED union {
7
        char  key[4];           // 1..4   "ILDA"
8
        unsigned int keyNum;    
9
        
10
        _PACKED struct {
11
          char key1;
12
          char key2;
13
          char key3;
14
          char key4;
15
        };
16
      };
17
            
18
      char  ZERO0;              // 5
19
      char  ZERO1;              // 6
20
      char  ZERO2;              // 7
21
      char  formatCode;         // 8      Format Code
22
      
23
      _PACKED union {
24
        char  frameName[8];     // 9..16  Frame Name
25
        char  paletteName[8];   // 9..16  Palette Name
26
      };
27
      
28
      char  companyName[8];     // 9..16  Frame Name
29
      
30
      _PACKED union {
31
        short totalPoints;      // 25..26 Total points
32
        short totalColors;      // 25..26 Total colors
33
      };
34
      
35
      _PACKED union {
36
        short frameNumber;      // 27..28 Frame Number
37
        short paletteNumber;    // 27..28 Palette Number
38
      };
39
      
40
      short totalFrames;        // 29..30 Total Frames
41
      char  scannerHead;        // 31     Scanner Head
42
      char  future;             // 32     Reserved for future use
43
    };
44
  };
45
} ILDA_Header_t;

: Bearbeitet durch User
von weiter weg (Gast)


Lesenswert?

Random .. schrieb:
> Achtung: Alle 16Bit Daten sind BE!

Dass diese Abkürzung mit Indianern zu tun hat ist nicht
jedem Anfänger klar, daher dürftest du hier ruhig ohne
Abkürzung schreiben.

von Random .. (thorstendb) Benutzerseite


Lesenswert?

weiter weg schrieb:
> Random .. schrieb:
>> Achtung: Alle 16Bit Daten sind BE!
>
> Dass diese Abkürzung mit Indianern zu tun hat ist nicht
> jedem Anfänger klar, daher dürftest du hier ruhig ohne
> Abkürzung schreiben.

Werd ich dann beim nächsten Frühstücks-Ei machen 🙈 🤣🤣🤣

Für die nicht eingew(ei)hten: BE = Big Endian. Die Motorola-CPUs, welche 
für die ersten ILDA Anwendungen verwendet wurden, speichern und 
bearbeiten ihre Daten im Big Endian Format. Für gängige Mikrocontroller 
und den PCs muss man das nach LE = Little Endian konvertieren, was bei 
16 Bit im Endeffekt eine Vertauschung der beiden Bytes bedeutet.

Auf dem Cortex-M recht elegant per Intrinsic lösbar:
1
uint16_t outVal = __REVSH(inVal);

Achso, was hat das ganze mit dem Frühstücks-Ei zu tun? Die Frage nach 
BE/LE ist fast so alt wie die, auf welcher Seite man das Ei am besten 
aufschlägt 🤣
Beides hat Vor- und Nachteile, LE scheint sich mehr durchgesetzt zu 
haben.

: Bearbeitet durch User
von weiter weg (Gast)


Lesenswert?

Beim nächsten Erscheinen von LE/BE ist es wieder scheisse
weil Abkürzungen mit zwei Buchstaben einfach zu wenig
Eindeutigkeit bzw. Aussagekraft haben.

von Random .. (thorstendb) Benutzerseite


Lesenswert?

weiter weg schrieb:
> Beim nächsten Erscheinen von LE/BE ist es wieder scheisse
> weil Abkürzungen mit zwei Buchstaben einfach zu wenig
> Eindeutigkeit bzw. Aussagekraft haben.

Der kontextbasierte Leser weiss mehr!

von weiter weg (Gast)


Lesenswert?

Random .. schrieb:
> Der kontextbasierte Leser weiss mehr!

... erst ab dem Zeitpunkt ab dem er mit der unzulänglichen
Abkürzung vertraut gemacht worden ist.

weiter weg schrieb:
> Beim nächsten Erscheinen von LE/BE ist es wieder scheisse

meint dass ein neuer Thread mit dieser Abkürzung unter den
selben Missverständnissen bzw. Uneindeutigkeiten zu leiden
hat.

von Hugo H. (hugo_hu)


Lesenswert?

Oliver S. schrieb:
> Und? Hast du das Data-Dokument auch gelesen?

Möglicherweise kann er seine Schuhe selbst binden :-)

von Andreas M. (amesser)


Lesenswert?

Tobias K. schrieb:
> Hier mein bisheriger Code:

Ohje, das ist ja nicht viel mehr als Öffnen und Dateinhalt ausgeben. 
Parsen von Binärdateien hast Du vermutlich noch nie gemacht? Ich habe 
mal kurz gesucht, aber ein wirkliches Beispiel in C# an dem Du dich 
langhangeln könntest habe ich dafür nicht gefunden.

Vielleicht mal so als Startpunkt: Im Prinzip musst du die Datei Stück 
für Stück einlesen und die einzelnen Datenelemente enstprechende der 
Spezifikation interpretieren. Fangen wir mal mit dem Header an:

ILDA_IDTF14_rev011.pdf, Figure 2: Achtung ich habe wenig ahnung von C#. 
Offsets in der Spec sind 1 referenziert ( normalerweise beginnt man bei 
0)
1
BinaryReader br = new BinaryReader(fs);
2
3
byte[] header = new byte[32];
4
5
/* read header */
6
br.Read(header, 0, 32);
7
8
if(header[0:4] != "ILDA")
9
  parse_error();
10
11
/* read format code offset 8 */
12
byte format_code = BitConverter.ToUInt8(header, 8 - 1);
13
14
byte[] palette_name = header[9-1:16-1];
15
byte[] company_name = header[17-1:24-1];
16
17
/* ILDA data is big endian, need to swap bytes */
18
if (BitConverter.IsLittleEndian)
19
{
20
  Array.Reverse(header, 25-1,2);
21
  Array.Reverse(header, 27-1,2);
22
...
23
}
24
25
uint number_of_records = BitConverter.ToUInt16(header, 25-1);
26
...

Und so weiter.

[Edit:] Nachtrag der Code oben ist nur als Startpunkt zu sehen, da lässt 
sich noch einiges massiv optimieren oder besser kapseln. Paar 
Syntaxfehler korrigiert, lesen sollte man auch können :-).
[Edit2]: Brauch mehr Kaffee ...

: Bearbeitet durch User
von Andreas M. (amesser)


Lesenswert?

Random .. schrieb:
> Einträgen, die jeweils über einen Header erkannt werden.
> Für einen Player (in C auf Cortex-M3) habe ich die komplette Spec in

Ich weis nicht wie Deine Compiler/MPU settings sind, aber Packing 
alleine kann bewirken, dass der Compiler beim Zugriff jedes Byte einzeln 
einliest und dann zusammensetzt. Das ergibt dann sehr viele 
Instruktionen. Wenn man weis, das die Datenstruktur immer auf anständig 
alignten Adresse liegt, dann kann man beim gcc zusätzlich zum packing 
das alignment Attribut nutzen um dem compiler zu hefen. Bei 
parse-lastigen Funktionen kann das zu einer drastischen Code Reduktion 
und Performanceverbesserung führen. (Das Byte-weise Einlesen eines 
uint32_t benötigt 7 einzelne Instruktionen)

Ich habe bei dem folgenden Beispiel absichtlich mal das compiler flag 
angeschaltet, so das der gcc sich nicht auf die MPU verlässt. Es kommt 
auch ein bisl auf die Hardware/Speicherbereich an, wo man sich bewegt ob 
ein unalignter Zugriff ne Excpetion auslöst oder von der MPU/MMU korrekt 
behandelt wird)

https://godbolt.org/z/E7eejPGrG

von Random .. (thorstendb) Benutzerseite


Lesenswert?

Andreas M. schrieb:
> aber Packing
> alleine kann bewirken, dass der Compiler beim Zugriff jedes Byte einzeln
> einliest und dann zusammensetzt.

Die Daten werden in einen globalen Byte-Buffer per fread() eingelesen, 
und dann über Pointer auf die structs und deren Member verarbeitet. Da 
sollte nichts schiefgehen, und mir ist im Assembly auch nichts 
aufgefallen.

Die structs sind dicht, __packed dient nur dazu, dass der Compiler nicht 
auf dumme Gedanken kommt, wie z.B. das Umsortieren oder komplette 
Zerreissen eines structs im Speicher. Die structs dienen letzlich nur 
als Schablone zum Ablesen der Daten.

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.