Hilfe!! BMP Datei unter C bearbeiten
-
feigling schrieb:
strcmp verwenden, nicht "if(bitmapFileheader.bfType!='BM')" .. wundert mich, dass dir der Compiler da nicht direkt ins Gesicht springt und dir mindestens eine Warnung ausgibt.
strcmp würde einen Programmabsturz verursachen, weil bitmapFileheader.bfType nicht Nullterminiert ist.
-
feigling schrieb:
strcmp verwenden, nicht "if(bitmapFileheader.bfType!='BM')" .. wundert mich, dass dir der Compiler da nicht direkt ins Gesicht springt und dir mindestens eine Warnung ausgibt.
Dann sag ihm auch, warum das u.a. falsch ist.
'a' - ist eine Zeichenkonstante (EIN Zeichen, kein String!)
"abc" - ist eine Zeichenkettenkonstante (also ein String)
'abc' - GIBT'S NICHT!Zur Not kannst du die 2 Zeichen so vergleichen (da strcmp ungünstig):
if(bitmapFileheader.bfType[0]!='B' || bitmapFileheader.bfType[1]!='M') {...}
-
geht nicht schrieb:
feigling schrieb:
strcmp verwenden, nicht "if(bitmapFileheader.bfType!='BM')" .. wundert mich, dass dir der Compiler da nicht direkt ins Gesicht springt und dir mindestens eine Warnung ausgibt.
strcmp würde einen Programmabsturz verursachen, weil bitmapFileheader.bfType nicht Nullterminiert ist.
Na dann verwende doch http://www.cppreference.com/stdstring/memcmp.html
EDIT: also "memcmp(bitmapFileheader.bfType, "BM", 2)"
müsstest dann aber wahrscheinlich noch bfType auf const casten.
-
if(bitmapFileheader.bfType[0]!='B' || bitmapFileheader.bfType[1]!='M') {...}
von _matze ist ein gute Idee. aber da bekomme ich immer ein Fehlmeldung !
und zwarIndex erfordert ein Array oder einen Zeigertyp!!
dann habe ich so gemacht:
if (*((char*)&(bitmapFileheader.bfType))!='M' || *((char*)&(bitmapFileheader.bfType)+1)!='B')
so habe ich keine Fehlmeldung mehr, aber als Rückmeldung habe ich immer noch "das ist kein BMP datei", d.h. "MB" (oder "BM") wird nicht erkennt!
langsam verzweifel ich , ob ich wirklich ein BMP datei habe!!
ist das doch richtig? wenn ich unter Windows die Eigenschat von "2.BMP"einschaue, steht es da: Type: Bitmap, Abmessung 640*480. Das ist doch eine BMP Datei! oder !!????* ahja! zu Info. ich arbeite mit Visual studio C++ 2008.
-
Wenn Du eh schon sagst, dass:
File Type = "BM" (0x4D42) muss sein !! offset = 0; */
sein muss, wieso
vergleichst Du dann nicht mitconst WORD FILETYPE = 0x4D42; if(bitmapFileheader.bfType != FILETYPE){...}
-
Hi !
Das hier lässt deine Struktur BITMAPFILEHEADER zu groß werden:
typedef unsigned int WORD;
Richtig ist:typedef unsigned short WORD;
Das hat sich Microsoft so ausgedacht, weitere typedefs finest du in WTYPES.H
Deine Struktur BITMAPFILEHEADER muss gepackt sein:#pragma pack(2) // Ausrichtung auf 2 Byte Grenzen. typedef struct tagBITMAPFILEHEADER { WORD bfType; DWORD bfSize; WORD bfReserved1; WORD bfReserved2; DWORD bfOffBits; } BITMAPFILEHEADER; #pragma pack() // Standard Ausrichtung wieder herstellen.
Ohne die pragma Anweisung wird sie ebenfalls zu groß, nämlich 16 anstatt 14 Byte.
Das kannst du leicht mit dem sizeof Operator nachprüfen.
Das liegt daran, das Füllbytes wegen der 4 Byte-Grenzen-Ausrichtung eingefügt werden.
Das hat dann zur Folge, das falsche Werte in BITMAPINFOHEADER landen.
Dann "BM" wird dann nicht erkannt, auch wenn es in der Bitmapdatei vorhanden ist, weil alle Werte um 2 Byte verschoben sind.Du kannst auch WINGDI.H in dein Programm einbinden, dort sind die beiden Strukturen deklariert.
Hier überschreibst du den Inhalt von bitmapFileheader !
printf("Rueckgabenwert von 'fread' ist : %d\n",fread(&bitmapFileheader,sizeof(BITMAPFILEHEADER),1,file));Hier eine überarbeitete Version:
#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"; BITMAPFILEHEADER bitmapFileheader; // printf("%d %d", sizeof(BITMAPFILEHEADER), sizeof(BITMAPINFOHEADER)); file=fopen(fname,"rb"); 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; } // 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; } return 0; }
-
Ich habe mit dem Code von 'Big Brother' probiert. Das hat FUNKTIONIERT!!!!!
Super Code!! besten Danke!
anbei habe ich am ein paar Stellen nicht richtig verstanden!!1:
Ohne die pragma Anweisung wird sie ebenfalls zu groß, nämlich 16 anstatt 14 Byte.
typedef unsigned short WORD; oder typedef unsigned int WORD;
die Beide sind vom Größe doch gleich, oder? (beide sind 16bits oder 2 Byte)
2:
// Achtung! Hier überschreibst du den Inhalt von bitmapFileheader ! // printf("Rueckgabenwert von 'fread' ist : %d\n",fread(&bitmapFileheader,sizeof(BITMAPFILEHEADER),1,file));
durch dies Code möchte ich eigentlich das Funktion'fread' kennenlernen, so wie ich es verstanden habe, habe ich nur eine 'printf'-Fkt zu viele. warum habe ich die Inhalt von bitmapFileheader dadurch geändert!
verstehe ich nicht.
-
Ohne die pragma Anweisung wird sie ebenfalls zu groß, nämlich 16 anstatt 14 Byte.
Lass dir doch mal die Größe der Struktur einmal mit der #pragma Anweisung und einmal ohne anzeigen:
printf("%d\n", sizeof( BITMAPFILEHEADER ) );
Strukturen werden standardmäßig im Speicher auf Adressen ausgerichtet, die durch 4 teilbar sind, um schneller darauf zugreifen zu können.
Weil die Struktur BITMAPFILEHEADER von Haus aus 14 Bytes groß ist, werden 2 Füllbytes eingefügt, damit diese Teilbarkeit durch 4 möglich ist.
Ein bisschen kannst du hier darüber lesen:
http://www.hs-augsburg.de/~sandman/c_von_a_bis_z/c_017_011.htmtypedef unsigned short WORD; oder typedef unsigned int WORD;
die Beide sind vom Größe doch gleich, oder? (beide sind 16bits oder 2 Byte)
Die Größe der Datentypen kannst du dir mit dem sizeof Oparator anzeigen lassen:
printf("%d\n", sizeof( unsigned short int ) ); printf("%d\n", sizeof( unsigned int ) );
2:
// Achtung! Hier überschreibst du den Inhalt von bitmapFileheader ! // printf("Rueckgabenwert von 'fread' ist : %d\n",fread(&bitmapFileheader,sizeof(BITMAPFILEHEADER),1,file));
durch dies Code möchte ich eigentlich das Funktion'fread' kennenlernen, so wie ich es verstanden habe, habe ich nur eine 'printf'-Fkt zu viele. warum habe ich die Inhalt von bitmapFileheader dadurch geändert!
verstehe ich nicht.
Hier wird die Struktur mit fread eingelesen:
if(fread(&bitmapFileheader,sizeof(BITMAPFILEHEADER),1,file)!=1) { printf("FileHeader kann nicht gelesen werden!!\n"); fclose(file); return 1; }
Nach dem Einlesen Zeigt der Dateizeiger nicht mehr an den Anfang dieser Struktur, sondern wird in der Datei um 14 Byte weiter gesetzt.
Nach Abarbeitung der Zeileprintf("Rueckgabenwert von 'fread' ist : %d\n",fread(&bitmapFileheader,sizeof(BITMAPFILEHEADER),1,file));
wurde noch einmal eingelesen aber ein anderer Inhalt steht in bitmapFileheader drin, nämlich die ersten 14 Byte der BITMAPINFOHEADER Struktur.
-
1:
wieder etwas gelernert,printf("Rueckgabenwert von 'fread' ist : %d\n",fread(&bitmapFileheader,sizeof(BITMAPFILEHEADER),1,file));
diese Problem habe ich jetzt verstanden!(hoffe ich
) so zu sagen, arbeitet 'fread' mit aktuelle Zeiger-Position. meine aktuelle Zeiger-Position hat nachdem
if(fread(&bitmapFileheader,sizeof(BITMAPFILEHEADER),1,file)!=1) { printf("FileHeader kann nicht gelesen werden!!\n"); fclose(file); return 1; }
eigentlich FileHeader schon verlassen, der steht direkt vor die "Tür" von INFOHEADER. habe ich so richtig verstaneden?
2:
printf("%d\n", sizeof( unsigned short int ) ); printf("%d\n", sizeof( unsigned int ) );
für mich ist das.. naja, unglaublich!!
weil in meine Bücher steht da :Beide sind 16 Bits(2 Byte)! (ANSI) ABER das Computer sagt mir: "2" und "4",Ohhhh!!
Strukturen werden standardmäßig im Speicher auf Adressen ausgerichtet, die durch 4 teilbar sind, um schneller darauf zugreifen zu können.
Weil die Struktur BITMAPFILEHEADER von Haus aus 14 Bytes groß ist, werden 2 Füllbytes eingefügt, damit diese Teilbarkeit durch 4 möglich ist.kann ich so vorstellen, dass die Datei (ohne #pragma) alle um 2 Byte nach rechts verschoben sind.
Und zum Zhema "4-teilbar" habe ich etwas vorher schon gelesen, bloß wenn ich späte bei FarbeWert einlesen bei jede Pixel, soll ich aufachten, dass ich immer jede Zell mit 4-fach-Anzahl einlesen soll, damit das zu DWORD passen kann. sind die Beide die selbe gemeint?
noch mal Danke schön!
-
gy100002000 schrieb:
in meine Bücher steht da :Beide sind 16 Bits(2 Byte)! (ANSI) ABER das Computer sagt mir: "2" und "4",Ohhhh!!
Dann sind deine Bücher wahrscheinlich sehr alt, da ein int, soweit ich weiß, schon seit Beginn der 32-Bit-Ära (Win95) 4 Bytes groß ist.
-
jo!! alles klar! http://www.galileo-press.de/openbook/c_von_a_bis_z/c_007_000.htm#Xxx999329 da habe ich noch mal nachgelesen, int ist 4 Byte! Vorher habe ich immer so vorgestellt, dass Zahlentype überall gleich sind. :p Danke!
-
gy100002000 schrieb:
...
diese Problem habe ich jetzt verstanden!(hoffe ich) so zu sagen, arbeitet 'fread' mit aktuelle Zeiger-Position. meine aktuelle Zeiger-Position hat nachdem
if(fread(&bitmapFileheader,sizeof(BITMAPFILEHEADER),1,file)!=1) { printf("FileHeader kann nicht gelesen werden!!\n"); fclose(file); return 1; }
eigentlich FileHeader schon verlassen, der steht direkt vor die "Tür" von INFOHEADER. habe ich so richtig verstaneden?
Ja, der Fuß ist quasi schon in der Türschwelle.
gy100002000 schrieb:
...kann ich so vorstellen, dass die Datei (ohne #pragma) alle um 2 Byte nach rechts verschoben sind...
Naja, was ist schon rechts bzw. links.
Die Datei selbst wird dabei nicht verschoben.
Den Beginn der Adresse der Struktur im RAM kannst du dir anzeigen lassen:
printf("%p", &bitmapFileheader );
Ohne #pragma wird die Adresse vermutlich die gleiche sein, hab ich noch nicht ausprobiert. Da wäre dann also auch nichts verschoben. Allerdings ist die Struktur ohne #pragma um 2 Byte größer und verschluckt dir deshalb beim Einlesen 2 Byte von der BITMAPINFOHEADER Struktur.Der Fuß ist also schon über die Türschwelle drüber.
gy100002000 schrieb:
Und zum Zhema "4-teilbar" habe ich etwas vorher schon gelesen, bloß wenn ich späte bei FarbeWert einlesen bei jede Pixel, soll ich aufachten, dass ich immer jede Zell mit 4-fach-Anzahl einlesen soll, damit das zu DWORD passen kann. sind die Beide die selbe gemeint?
noch mal Danke schön!Jede Zell? Meinst du jeden Pixel?
Einzelnd Pixel einlesen macht man eigentlich nicht, die liest man mit einem Rutsch in einen Puffer ein.
-
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?