Hilfe!! BMP Datei unter C bearbeiten
-
Hallo! Big Brother, Danke noch mal!
ich habe mitprintf("%p", &bitmapFileheader );
mit und ohne "#pragma" ausführen lassen, die computer gibt mir die selb Werte aus. d.h. die BITMAPFILEHEADER und BITMAPINFOHEADER haben immer die gleich Beginnenstelle. wenn die BITMAPFILEHEADER zu größ ist, z.B >14 Byte, werde BITMAPINFOHEADER NICHT automatisch um 2 Byte verschieben, sonder BITMAPINFOHEADER fänge immer bei den alte Adresse an.
und was zu "4-teilbar" habe ich sowas gelesen: z.B. jede Pixel eines BMP Datei mit (256 stufen) besitze 1 Byte. und wenn die Bildbereite 79 Pixel wäre, wird aber für diese Zeil trotzdem 80 Pixel(bzw. 80 Byte) gelesen, und wenn wenn bildbereite 75 Pixel wäre, wird es zu 76 gemacht, denn 80 und 76 sind vielfach von "4" .
das Programm habe ich weiter bearbeitet, code:
fread(&bitmapInfoheader,sizeof(BITMAPINFOHEADER),1,file); printf("%p\n", &bitmapInfoheader ); printf("%d\n",sizeof(bitmapInfoheader)); printf("%d\n",bitmapInfoheader.biWidth); printf("%d\n",bitmapInfoheader.biSizeImage);
für die Inhalt von BITMAPINFOHEADER habe ich ganz komisch Werte bekommen, eigentlich nicht sein darf! deswegen habe ich zuerste gedacht, dass ich für BITMAPINFOHEADER auch #pragma benutzen soll. aber mit sizeof() habe ich sicher gestellt, dass bitmapInfoheader 40 Byte ist. also richitge Größe! deswegen habe ich eine 2. Idee, vielleicht ist deshalb nicht richtig, weil ich gerade mit dem Programm ausprobiert ohne #pragma. Die bimapFileheader und bitmapInfoheader sind von Speicheradresse schon übereinandere gelegt. Obwohl ich späte #pragma wieder zugefügt habe, kann ich die speicherAdress nicht mehr leeren. deshalb habe ich VC++ neu gestartet. lass die Programm noch mal laufen. naja! geht auch nicht!!
um zu kontrollieren, ob die Zeiger auch die richtige Stelle zeigt, habe ich noch drei Zeilen Code geschrieben,file=fopen(fname,"rb"); p=ftell(file); printf("Point-Position_1:%d\n",p); // neue Code . . if(fread(&bitmapFileheader,sizeof(BITMAPFILEHEADER),1,file)!=1) { printf("FileHeader kann nicht gelesen werden!!\n"); fclose(file); return 1; } p=ftell(file); printf("Point-Position_2:%d\n",p); // neue Code . . fread(&bitmapInfoheader,sizeof(BITMAPINFOHEADER),1,file); p=ftell(file); printf("Point-Position_3:%d\n",p); // neue Code
1: 0 2:14 . wie ich erwartet, ist es alles so weiter im Ordnung. aber als ich den
p=ftell(file); printf("Point-Position_3:%d\n",p);
eingefügt habe, bekommt cih eine Fehlmeldung : Debug Assertion Failed!
versteh ich nicht!!
-
hier ist noch mal die Code:
#include <stdio.h> typedef unsigned short WORD; typedef unsigned long DWORD; typedef long LONG; #pragma pack(2) typedef struct tagBITMAPFILEHEADER { WORD bfType; DWORD bfSize; WORD bfReserved1; WORD bfReserved2; DWORD bfOffBits; } BITMAPFILEHEADER; #pragma pack() typedef struct tagBITMAPINFOHEADER { DWORD biSize; LONG biWidth; LONG biHeight; WORD biPlanes; WORD biBitCount; DWORD biCompression; DWORD biSizeImage; LONG bXPelsPerMeter; LONG biYPelsPerMeter; DWORD biClrUsed; DWORD biClrImportant; } BITMAPINFOHEADER; int main() { FILE *file; char* fname = "2.bmp"; int p; BITMAPFILEHEADER bitmapFileheader; BITMAPINFOHEADER bitmapInfoheader; //printf("%d %d\n", sizeof(BITMAPFILEHEADER), sizeof(BITMAPINFOHEADER)); //printf("%d %d\n", sizeof(bitmapFileheader), sizeof(bitmapInfoheader)); file=fopen(fname,"rb"); p=ftell(file); printf("aktuelle-Point-Position_1:%d\n",p); if(file==NULL) { printf("Datei kann nicht geoeffnet werden!!\n"); return 1; } if(fread(&bitmapFileheader,sizeof(BITMAPFILEHEADER),1,file)!=1) { printf("FileHeader kann nicht gelesen werden!!\n"); fclose(file); return 1; } p=ftell(file); printf("aktuelle-Point-Position_2:%d\n",p); printf("bitmapFileheader.bfType : %d\n",bitmapFileheader.bfType); printf("bitmapFileheader.bfOffBits : %d\n",bitmapFileheader.bfOffBits); //printf("%d\n", sizeof( unsigned short int ) ); //printf("%d\n", sizeof( unsigned int ) ); // Achtung! Hier überschreibst du den Inhalt von bitmapFileheader ! // printf("Rueckgabenwert von 'fread' ist : %d\n",fread(&bitmapFileheader,sizeof(BITMAPFILEHEADER),1,file)); if( bitmapFileheader.bfType != 0x4D42 ) { printf("keine BMP Datei!!\n"); fclose(file); return 1; } if ( fclose(file) ) { perror(fname); return 1; } printf("Adress von bitmapFileheader : %p\n", &bitmapFileheader ); fread(&bitmapInfoheader,sizeof(BITMAPINFOHEADER),1,file); //p=ftell(file); //printf("aktuelle-Point-Position_3:%d\n",p); // wenn ich die beide obere Zeilen einfügen würde, bekomme ich hier eine Fehlmeldung! printf("Adress von bitmapInfoheader : %p\n", &bitmapInfoheader ); printf("Größe von bitmapInfoheader: %d\n",sizeof(bitmapInfoheader)); printf("bitmapInfoheader.biWidth : %d\n",bitmapInfoheader.biWidth); printf("bitmapInfoheader.biSizeImage %d\n",bitmapInfoheader.biSizeImage); return 0; }
-
Nenee, die #pragma Anweisung muss schon sein.
Wenn du die weglässt, werden 2 Byte zuviel eingelesen, der Dateizeiger zeigt dann 2 Byte zu weit.
Die 2 Byte landen in den Füllbytes, an die kommst du nicht ran.
Das sind die ersten 2 Byte von der nächsten Struktur, dem BITMAPINFOHEADER.
Genau genommen, 2 Byte von DWORD biSize;
-
Jo!! Fehler habe ich gefunden!!
ich habe die Codeif ( fclose(file) ) { perror(fname); return 1; }
einfach weggelassen!! dann funktioniert alles!
durchfread(&bitmapInfoheader,sizeof(BITMAPINFOHEADER),1,file); p=ftell(file); printf("aktuelle-Point-Position_3:%d\n",p); printf("Adress von bitmapInfoheader : %p\n", &bitmapInfoheader ); printf("Größe von bitmapInfoheader: %d\n",sizeof(bitmapInfoheader)); printf("bitmapInfoheader.biWidth : %d\n",bitmapInfoheader.biWidth); printf("bitmapInfoheader.biSizeImage %d\n",bitmapInfoheader.biSizeImage); printf("bitmapInfoheader.biHeight : %d\n",bitmapInfoheader.biHeight); return 0;
habe ich geprüft, dass alles im Ordnung sind!!
640*480 und usw.
Oh man!! unglaublich, ich kann doch was!!
das habe ich mich selbe nicht zugetraut!
aber zurück zu Fehler:if( bitmapFileheader.bfType != 0x4D42 ) { printf("keine BMP Datei!!\n"); fclose(file); return 1; } /*if ( fclose(file) ) { perror(fname); return 1; } */
warum hat es an diese Stelle mein File wieder zugemacht!! verstehe ich nicht!!
-
ich glaube, ich weiß, woan es liegt:
bei fclose(file), wenn es erfolgreich ausgeführt werden, ist das Rückgabewert:0 wenn nicht, dann EOFif ( fclose(file) ) { perror(fname); return 1; }
diese Programm mache als Erst: fclose(file).d.h. mein Fil ist zuerst ZU!!!!
deswegen habe ich die komische Wert von bitmapInfoheader.biheight, usw. bekommen.
-
ja! vielleicht noch eine Frage? brauche ich an diese Stelle unbediente
perror(fname); return 1;
???
ich habe es umgestellt:if( bitmapFileheader.bfType != 0x4D42 ) { printf("keine BMP Datei!!\n"); fclose(file); i=1; return 1; } //printf("Rückgabewert von fclose(file)%d\n",fclose(file)); if ( i==1 ) { perror(fname); return 1; }
int i=0; habe ich ganz am Anfang definiert!
-
gy100002000 schrieb:
ja! vielleicht noch eine Frage? brauche ich an diese Stelle unbediente
perror(fname); return 1;
???
ich habe es umgestellt:if( bitmapFileheader.bfType != 0x4D42 ) { printf("keine BMP Datei!!\n"); fclose(file); i=1; return 1; } //printf("Rückgabewert von fclose(file)%d\n",fclose(file)); if ( i==1 ) { perror(fname); return 1; }
int i=0; habe ich ganz am Anfang definiert!
In C ist es üblich, das Funktionen im Fehlerfall eine 1 zurückgeben.
Natürlich gibt es hier auch Ausnahmen.
Der Rückgabewert 0 bedeutet of so viel wie 'kein Fehler'.
Überleg dir mal, ob nach Abarbeitung von Zeile 6 die Zeile 9 ausgeführt werden kann.
-
Überleg dir mal, ob nach Abarbeitung von Zeile 6 die Zeile 9 ausgeführt werden kann.
naja! eigentlich nicht! Weil nachdem
return 1;
wird das Programm schon gestoppt!
if ( i==1 ) { perror(fname); return 1; }
hat eigentlich kein Sinn!
ahja! was ich nicht verstehe ist, wofür ist
perror(fname);
brauchen wir das wirklich?
-
gy100002000 schrieb:
ahja! was ich nicht verstehe ist, wofür ist
perror(fname);
Wofür das ist, kannst du leicht nachprüfen:
FILE* fp; char* file = "Bin ich eine Datei, oder ein Verzeichnis?"; fp = fopen( file, "r" ); if ( !fp ) perror(file);
Es wird eine Meldung auf dem Fehler-Ausgabe-Kanal ( stderr ) ausgegeben.
Kennst du die MSDN? Da kannst du über solche Funktionen genaueres erfahren.gy100002000 schrieb:
brauchen wir das wirklich?
Kommt drauf an. Prinzipiell sollte man alles auf Fehler prüfen, was möglich ist.
Wenn dein Programm irgendwann mal sehr groß werden sollte, könntest du unter Umständen sehr lange mit der Fehlersuche beschäftigt sein. Wenn ein Fehler 'verschluckt' wird und dadurch möglicher weise eine zusätzliche Verkettung weiterer Fehler entsteht, die sich unter Umständen in einer ganz anderen Datei etliche Megabyte vom Entstehungsort entfernt bemerkbar macht.
-
alles klar! ich werde noch mal bei MSDN nachschauen. auf jeden Fall besten Dank!
muss ich ehrlich zugeben, C ist nicht so einfach wie MATLAB !aber langsam mach's auch spass!!