Aus Datei lesen



  • #include <stdio.h>
    
    #define SIZE 50
    
    int main(void)
    {
    	FILE *pFile;
    	char filename[SIZE], pixelarray[512][512]; // ins pixelarray sollen die werte gespeichert werden
    	char *pixptr = pixelarray;
    	int bildgroesse, bildhoehe=512, bildbreite=512, i, j;
    
    	printf("Welche Datei wollen sie oeffnen: ");
    	scanf("%s", filename); // kein & mehr
    
    	pFile = fopen(filename,"rb");
    	if(pFile)
    	{
    		printf("Datei wurde geoeffnet!\n");
    		fclose(pFile);
    
    		pFile = fopen(filename, "rb");
    		fseek(pFile, 128*sizeof(char), SEEK_SET);
    		fseek(pFile, 4*sizeof(char), SEEK_CUR);
    
    		fread(&pixptr, sizeof(short), 1, pFile);  // auslesen der daten mit fread... aber bin nicht sicher, ob das mit dem pixptr richtig ist...
    
    		bildgroesse = bildbreite*bildhoehe;
    		printf("Die Bildgroesse ist %d Bytes.", bildgroesse);
    
    		for(i=0; i<bildhoehe; i++) // jeden bildpunkt abtasten
    		{
    			for(j=0; j<bildbreite; j++)
    			{
    				if(pixelarray[i][j] < -900 || pixelarray[i][j] > 250)
    				{
    					pixelarray[i][j] = -1024;
    				}
    			}
    		}
    	}
    
    	else // die schleife jetzt am ende, damit das programm danach nicht weiterläuft
    	{
    		printf("Datei konnte nicht gefunden werden.\n");
    	}
    
    	printf("\n\n");
    	return 0;
    }
    

    jetzt weiß ich nicht so wirklich weiter, brauch iwie glaub ich ein anderen pointer oder das array anders...



  • ...
    	char filename[SIZE], pixelarray[512][512]; // ins pixelarray sollen die werte gespeichert werden
    	char *pixptr = pixelarray;
    ...
    	pFile = fopen(filename,"rb");
    	if(pFile)
    	{
    		printf("Datei wurde geoeffnet!\n");
    		fclose(pFile);
     :arrow_right: // Was  soll denn der Mist :confused:  fclose und gleich danach fopen? 
    		pFile = fopen(filename, "rb");
    ...
    		fread(&pixptr, sizeof(short), 1, pFile);  // auslesen der daten mit fread... aber bin nicht sicher, ob das mit dem pixptr richtig ist...
     :arrow_right: // Du liest gerade genau 1 short ein und nicht etwa 512x512
     :arrow_right: // Zudem ist pixptr schon ein Pointer und der braucht hier kein & mehr
    		bildgroesse = bildbreite*bildhoehe;   :arrow_right: // zu spät. musst du früher machen
    		printf("Die Bildgroesse ist %d Bytes.", bildgroesse);
    
    ...				if(pixelarray[i][j] < -900 || pixelarray[i][j] > 250)
     :arrow_right: // pixelarray ist ein Array das char-Element aufnimmt. Wie willst du da Werte < 128 und > 127 drin abspeichern?
    ...
    					pixelarray[i][j] = -1024;  
    	else // die schleife jetzt am ende, damit das programm danach nicht weiterläuft
     :arrow_right: // if ist keine Schleife sondern eine Bedingung
    ...
    }
    

    basti273 schrieb:

    jetzt weiß ich nicht so wirklich weiter, brauch iwie glaub ich ein anderen pointer oder das array anders...

    Du brauchst ein C-Buch und das Kapitel über Arrays und Pointer.

    Woher kennst du die Bildgröße?

    Mach dir erst einmal klar was du einlesen willst.
    Von welchem Typ sind die Daten? char, short oder sonstwas.



  • Und wenn ihr Bildpunkte verändern solt, müssen die auch irgendwie wieder in eine Datei.
    Vielleicht solltest du den Header nicht überspringen sondern in ein Array einlesen und dann später wieder in die neue Datei schreiben.

    Versuch doch mal die 4 Zeichen ab Position 128 einzulesen und gib sie auf dem Bildschirm aus. Wenn das klappt hast du schon mal ein Gefühl für "Aus Datei lesen".

    Zudem sieht das DICOM Format nicht ganz so trivial aus, wie du es gerade versuchst.



  • Ja, genau.
    Eine neue Datei soll dann danach auch erstellt werden , indem wir die neuen Werte schreiben.



  • basti273 schrieb:

    char filename[SIZE], pixelarray[512][512]; // ins pixelarray sollen die werte gespeichert werden
    

    Mehrfach wird erwähnt, dass du mit short arbeiten sollst. Du hast aber hier ein char-Array. Was soll das bringen?



  • Ohja, ganz übersehen, stimmt. Danke für all die Hilfe, hab es vom prinzip her jetzt soweit fertig alles, allerdings hab ich noch ein problem mit dem finden des Dateianfangs.
    Man muss ja solange Werte überspringen, bis man diese vorgegebene hexadezimalzahl findet. Aber wie kann ich diese suchen?

    int main(void)
    {
    	FILE *pFile;
    	char filename[SIZE], filenamenew[SIZE];
    	char ueber;
    	short pixelarray[MAX][MAX]; 
    	short *pixptr = pixelarray[MAX];
    	int bildgroesse, bildhoehe=MAX, bildbreite=MAX, i, j;
    	int hilf;
    	int *hilfptr = &hilf;
    
    	printf("Welche Datei wollen sie oeffnen: ");
    	scanf("%s", filename); 
    
    	pFile = fopen(filename,"rb");
    
    	if(pFile)
    	{
    		printf("Datei wurde geoeffnet!\n");
    
    		fseek(pFile, 0*sizeof(char), SEEK_SET); //Dateianfang
    
    		do
    		{
    			fseek(pFile, 1*sizeof(char), SEEK_CUR); 
    			fread(hilfptr, sizeof(short), 1, pFile);
    			hilfptr++;
    		}while(*hilfptr!=0x7FE0);
    
    		fseek(pFile, 4*sizeof(char), SEEK_CUR);
    		printf("Bildanfang");
    
    ...
    

    bei der do-while-schleife schmiert das programm immer ab, weil ich glaube dass der hilfptr nicht richtig funktioniert, aber wie finde ich die 0x7FE0 korrekt?



  • 1. sizeof(char) ist 1 per Definition
    2. Alle Lese/Schreiboperationen wie fread stellen den internen Dateizeiger automatisch weiter. Da braucht es kein fseek mehr (Zeile 25)
    3. Ein Zeiger muss irgendwohin zeigen, wo es auch gültigen Speicher gibt.
    (Wenn du darauf zugreifst)
    4. Wenn du short einlesen willst/sollst, dann nimm auch eine short Variable.

    Dein hilfptr zeigt am Anfang auf hilf (das ist ein Integer) und durch das hilfptr++; dann irgendwohin, wo es nicht mehr sinnvoll ist.

    short hilf;
            do
            {
                fread( &hilf, sizeof(short), 1, pFile);
    //        Das & da ^ liefert die Adresse der Variablen hilf
            } while(hilf != 0x7FE0);
    


  • Perfekt, mit der do-schleife funktioniert das Ding nun endlich.
    Hatte das mit dem fread und dem automatischen überspringen nicht mehr ganz in Erinnerung gehabt.

    Allerdings haut der mir jetzt noch einen Fehler beim einlesen der Daten raus...
    Ich kopier mal die wichtigen stellen rein, wo er einliest und die deklarationen.

    #define SIZE 50
    #define MAX 512
    
    int main(void)
    {
    	FILE *pFile;
    	char filename[SIZE], filenamenew[SIZE];
    	short pixelarray[MAX][MAX]={0}; 
    	short *pixptr = pixelarray[MAX]; 
    	int bildgroesse, bildhoehe=MAX, bildbreite=MAX, i, j;
    	short hilf;
             // der platz dazwischen
    		for(i=0; i<bildhoehe; i++)
    		{
    				fread(pixptr[i], sizeof(short), bildbreite,pFile);		
    		}
    // und danach kommt auch noch was
    

    Was ist da der Fehler bei fread, bzw. besser, wie kriege ich den Weg?
    hab da nämlich schon allerlei ausprobiert, aber er konvertiert mir das halt nicht.
    Ziel ist: jedes einzelne Pixel in das pixelarray einzuspeichern.



  • Eine genaue Fehlerbeschreibung ist nie schlecht.

    fread(pixelarray[i], sizeof(short), bildbreite,pFile);
    

    Am einfachsten ist aber der Verzicht auf die Schleife und alles auf einmal holen.

    fread(pixelarray, sizeof(short), bildbreite * bildhoehe, pFile);
    

    Du brauchst ein C-Buch.
    Du musst es dir auch durchlesen. Mehrmals



  • Danke schonmal für die dicke Hilfe.
    Eigentlich progge ich viel und les auch viel durch in C und C++, allerdings zuviel frei gehabt in letzter Zeit und mit Dateien immer schon Probleme gehabt.

    Danke 🙂 Funzt nun alles.



  • Du hast Grundlegendes zu C nicht verstanden,
    du weißt nicht was ein Array ist und wie man es gebraucht,
    du weißt nicht, was ein Zeiger ist und wie man ihn gebraucht,
    du weißt nicht, wie man korrekt aus Dateien liest,
    du weißt nicht, wie man Strings mit scanf richtig liest,
    du ignorierst die hier gegebenen Hinweise,
    ...

    Ich schließe mit meinem Vorredner an:
    Du brauchst ein gutes C-Buch.
    Du musst es dir auch durchlesen. Mehrmals, und wenigstens versuchen, zu verstehen.



  • Evtl. ist die Datei korrupt.
    Nimst du die Originaldatei oder schon eine neue von dir?

    Das fseek(pFile, 0*sizeof(char), SEEK_SET); //Dateianfang ist nach einem fopen(filename,"rb"); sowieso gegeben
    sizeof(char) ist immer noch 1 🙄

    pixelarray[i][j] == -1024; ist ein Vergleich, keine zuweisung.

    Und das schreiben klappt so nicht, wenn du den Namen einer existierenden Datei eingibst.
    Zudem schreibst du nur die rohen Bilddaten ohne Header.

    basti273 schrieb:

    Ich les mir verdammt viel C und C++ durch

    C und C++ sind zwei verschiedene Programmiersprachen.

    basti273 schrieb:

    und progge auch schon länger, aber Dateien sind immer wieder Probleme...

    Welche Sprachen?



  • Oh, jetzt hast du alles weggemacht. 😞

    Ein Hinweis woran es gelegen hat wäre für andere evtl hilfreich.

    basti273 schrieb:

    Funzt nun alles.

    Das glaube ich nicht.



  • Hey Leute und erstmal frohe Ostern,

    vorweg mir fehlen die Basics und viel Routine in C wie ich mit dieser Aufgabe gemerkt hab.

    Ich fange nun an C von a bis z zu lesen, da ich das so nicht weiter machen kann.

    Ich hake schon ganz am Anfang und hoffe das ich hier evtl. Stück für Stück Hilfe bekomme. Das Schlimme ist, ich habe den Überblick über die Aufgabe verloren, bzw. mir fehlt allgemein der rote Faden.
    Ich möchte jetzt das im Speicher liegende Bild nach dem Hex-Code durchsuchen und dann meinen Zeiger dort platzieren, damit ich von dort aus 4 chars weiterspringen kann.

    #include <stdio.h>
    #include <stdlib.h>
    
    int main () {
      FILE * pFile;
      long lSize;
      char * buffer;
      size_t result;
      int i,n=0,x,y,z;
      short c;
      char hexcode[]={"0x7FE0,0x0010"};
    
      pFile = fopen ( "*********\\Kopf.IMA" , "rb" );
      if (pFile==NULL) {printf("Fehler");}
    
      // Anzeige der Filegröße
      fseek (pFile , 0 , SEEK_END);
      lSize = ftell (pFile);
      rewind (pFile);
    
      printf("Filesize:%ld \n",lSize);
    
      // Belegung des Speicher für den kompletten File
      buffer = (char*) malloc (sizeof(char)*lSize);
      if (buffer == NULL) {printf("Fehler");}
    
      // Kopieren des File in Speicher
      result = fread (buffer,1,lSize,pFile);
      if (result != lSize) {printf("Fehler");}
    
    	system("PAUSE");
    
      /* Die Datei ist nun komplett im Speicher :) */
    
      // Schließen und speicher freigeben
      fclose (pFile);
      free (buffer);
    
      return 0;
    
        }
    

    Über Hilfe wäre ich sehr dankbar, ich werde aber sicher oft und viel hier fragen. Da ich es nicht schaffe das Buch so schnell zu lesen wie die Aufgabe fertig sein sollte.

    lg Zermy



  • Das char hexcode[]={"0x7FE0,0x0010"}; ist ein String, damit kannst du erstmal wenig anfangen.
    Da kannst du ein short suchwerte[2] = {0x7FE0,0x0010}; nehmen.
    Damit kannst du direkt auf die Werte zugreife.

    Dann brauchst du noch einen Zeiger auf short, der auf den Anfang des buffers zeigt: short *bild; und bild = (short *)buffer;

    Dann kannst du mit einer Schleife durch bild gehen und vergleichen.
    Das kannst du mit Pointerarithmetik oder Arrayzugriff machen.

    for(i=0; i < (lSize / sizeof(short)-1); i++)
      if ((bild[i] == suchwerte[0]) && ...) break;
    

    Nach der Schleife kannst du i+=(4/sizeof(short)) machen und bist bei deinem gesuchten Index.
    Es sei denn die Suchwerte sind nicht vorhanden. Denn Fall musst auch noch abfangen.

    Was passiert, wenn malloc fehlschlägt?
    Du gibst "Fehler" aus und machst munter weiter.
    Ebenso bei fread.

    Das fclose kannst du auch gleich nach fread machen (wenn die komplette Datei gelesen wurde)



  • Hallo DirkB,

    vielen Dank für deine schnelle Antwort, ich werde dein geschriebenes mal umsetzen und versuche dabei richtig zu durchdringen. Ich poste dann hier meine Erfolg oder das was ich nicht schaffe.

    Um das mit den Fehlerausgaben richtig zu machen muss ich else anlegen richtig? Im Beispiel wird das so gemacht {fputs ("File error",stderr); exit (1);}

    Bis gleich

    Zermy



  • Durch das exit (1) wir das Programm an der Stelle beendet.
    Dann brauchst du kein else mehr.

    Achso, die ... musst du noch mit der zweiten Bedingung ausfüllen.



  • Ok xD danke {fputs ("File error",stderr); exit (1);} das ist die standart bibi für fehler soweit ich mich jetzt informiert hab. Das heißt man sollte diese benutzen und nicht mehr if else verzweigungen?

    und wo ich noch etwas hake vom Verständnis her ist hier:

    bild = (short *)buffer; 
    //hier deklarierst du den zeiger auf short der buffer 
    //heiß und wird nun die Adresse abgepeicher?
      for(i=0; i < (lSize / sizeof(short)-1); i++)
    // das lSize also die größe des   Bildes durch sizeof(short)-1 also die größe //von short das  -1 verstehe ich nicht, ziehste da 1 ab? Wenn ja warum?
    
      if ((bild[i] == suchwerte[0]) && ) break;
    	{fputs ("File error",stderr); exit (3);}
    
    // hinter dem && (bild[i] == suchwerte[1])? Da ich den zweiten Hex code ja auch //noch suchen muss?Jedoch steht i ja noch an der stelle von suchwert[0] und ich //müsste i doch weiter zählen lassen
    
      i+=(4/sizeof(short));
    //hier verstehe ich das so das ich nun an der stelle bin, ab der ich das Bild auf die -900HU oder <250 HU prüfen soll.
    

    lg Zermy



  • short *bild;  // Dies ist eine Definition von einem Zeiger auf short der bild heißt.
     bild = (short *)buffer; // Hier wird dem Zeiger ein Wert zugewiesen. (initialisiert)
    // bild zeigt jetzt auf den Anfang von buffer
    
      for(i=0; i < (lSize / sizeof(short)-1); i++)
    // lSize  ist die Größe in Byte. Wir brauchen aber die Größe in short.
    // Das -1 brauchst du, da du ja 2 short-Werte vergleichst und sonst zu weit liest
    
      if ((bild[i] == suchwerte[0]) && ) break;  // Das if ist nach dem break vorbei
    // Wie wärs mit  && (bild[i+1] == suchwerte[1])? 
    	{fputs ("File error",stderr); exit (3);} // Das wird immer ausgeführt
    // Warum willst du da dein Programm beenden  :confused: 
    
      i+=(4/sizeof(short));
    // Du willst doch 4 Byte weiterzählen. Und nicht 4 short
    
    // ab der ich das Bild auf die -900HU oder <250 HU prüfen soll. :confused: Davon hast du bis jetzt noch nichts gesagt.
    


  • Hey,

    ja hab mir in der Zeit, alles etwas genauer angeguckt und die IF auch schon erweiter. Das mit dem fputs war nen copy fehler... den hab ich auch beseitigt da das es sich sonst immer beendet.

    Ich wolle das Programm Schritt für Schritt aufbauen. Am Ende soll ein Bild entstehen wo der Knochen und die Luft herausgefiltert sind. Das heißt ab der Stelle wo wir jetzt sind,nach dem Hexcode und den 4 char zeichen die weitergespringen werden sollen.

    Muss das dann nicht
    i+=(4*sizeof(char));
    sein? Da ich 4 Chars weiter springen soll und nicht 4 Byte? Entschuldige für meine fehlende Information.

    Ich erläuftere nochmal kurz worum es in Aufgabe 1.1 geht.

    Kopf.IMA einlesen (später per CMD Abfrage, welches Bild man einlesen will)
    Jeden Bildpunkt vergleichen ob er Luft oder Knochen ist und in dem Fall auf 0 oder 1 setzen.
    Dazu muss ich nun jeden Punkt abfragen ob er x<-900HU(Luft) oder x>250HU(Knochen)
    das segmentierte Bild abspeichern(später per CMD Abfrage unter welchem Namen das Bild gespeichert werden soll)

    z.B
    Bitte geben SIe den namen der Input-Datei ein!
    Kopf.IMA
    Bitte geben Sie ein unter welchem Namen der Output gespeichert werden soll?
    Kop_seg.IMA
    Erfolgreich gespeichert oder Fehler.

    Ich hoffe ich konnte etwas Klarheit schaffen.

    lg Zermy


Anmelden zum Antworten