bitmapfile auslesen



  • Gast_Chris schrieb:

    s.Wikipedia

    bfType = 2Byte
    bfSize = 4Byte
    bfReserved = 4Byte
    bfOffBits = 4Byte

    =14Byte

    Teste mal deine short und long wie groß die sind ( sizeof(short) und sizeof(long) ).
    Ich vermute long sind bei dir 5Byte (=32Bit-Integer) statt 4, d.h. du liest noch Daten aus dem folgenden Feld.

    Viele Grüße, Chris

    short haben 2 bytes, und long 4 bytes...normalerweise müsste mein struct auch 14 bytes haben.. es sind aber tatsächlich 16 😕



  • Sind structs eventuell immer Vielfache von int? k.A.
    Auf jeden Fall liest du die richtige Größe ein, du musst dir jetzt nur noch Gedanken machen, wie du die eingelesenen Werte richtig interpretierst -> s.o.

    BTW: bfSize ist ein "unzuverlässiger" Wert. Das Erstellerprogramm des Bitmaps kann da alles mögliche reinschreiben, ohne dass dies etwas mit der wahren Größe der Datei zu tun hat (und auch ohne dass es jemanden interessiert, für die Auslese der Bilddaten ist lediglich die Breite, Höhe und Codierung wichtig). Schau dir das Bitmap mal mit einem Hexeditor an, vielleicht steht da als bfSize wirklich Null drin.

    PS:

    ich selbst schrieb:

    5Byte(=32Bit-Integer)

    😮
    Dringend Zeit für mich ins Bett zu gehen - 32Bit-Integer=(4*8Bit)-Integer=4Byte !!!



  • Gast_Chris schrieb:

    bfSize = bmfh[2] + 256*bmfh[3] + 0x10000*bmfh[4] + 0x1000000*bmfh[5];
    bfOffBits = bmfh[10] + 256*bmfh[11] + 0x10000*bmfh[12] + 0x1000000*bmfh[13];
    

    ich werde es wohl so machen wie du es vorgeschlagen hast.... habs paste&copy gemacht und auf die weiße hat bfSize sehrwohl (irgendeinen) wert...

    jetzt muss ich nur noch verstehen was der obige code macht.
    könnte mir da noch jemand unter die arme greifen?
    also für bfSize fang ich im array bei position 2 an weil dort die informationen auch im header stehn. (von 2 - 6) ... dazu addiere ich nun 256*bmfh[3] usw. ?
    wieso macht man das?



  • Dein Wert bfSize steht in den 4 genannten Bytes. Ein Byte sind 8 Bit, also stellt ein Byte eine Zahl zwischen 0 und 255 da (2^8=256). bfSize ist also quasi im im 256-System codiert.

    In unserem normalem Zahlensystem hat in der Zahl 456 die Ziffer "4" die Wertigkeit Hundert, die Ziffer "5" die Wertigkeit Zehn und die Ziffer "6" die Wertigkeit Eins. Somit ergibt sich aus 4*100 + 5*10 + 6*1 = 456.

    Im 256-System hat in einer vierstelligen Zahl
    die erste Ziffer (=das erste Byte) die Wertigkeit 16777216,
    die zweite Ziffer die Wertigkeit 65536,
    die dritte Ziffer die Wertigkeit 256
    und die vierte Ziffer die Wertigkeit 1.

    In meinem vorherigen Post war ich zu faul die Wertigkeiten der ersten beiden Ziffern (=Byte) auszurechnen und habe direkt die Hexadezimalschreibweise benutzt: 0x1=1, 0x10=16, 0x100=256, 0x10000=65536, ...

    bfSize = bmfh[2] + 256*bmfh[3] + 65536*bmfh[4] + 16777216*bmfh[5];
    bfOffBits = bmfh[10] + 256*bmfh[11] + 65536*bmfh[12] + 16777216*bmfh[13];
    

    So wäre es vielleicht einfacher einzusehen gewesen. Was hier gemacht wird ist das gleiche, wie im obigen Beispiel: 456 = 4*100 + 5*10 + 6*1
    Wegen dem LittleEndian/BigEndian-Problem (s.Wikipedia) musst du aber drauf achten, welches Byte welche Wertigkeit hat.

    Viele Grüße, Chris (jetzt endgülitg im Bett 😉 )



  • ich versteh das nicht.

    int bfSize =    header[2] +  256*header[3] +  0x10000*header[4] +  0x1000000*header[5];
    	int bfOffBits = header[10] + 256*header[11] + 0x10000*header[12] + 0x1000000*header[13];
    	int bfwidth =   header[18] + 256*header[19] + 0x10000*header[20] + 0x1000000*header[21];
    	int bfheight = header[22] + 256*header[23] + 0x10000*header[24] + 0x1000000*header[25];
    

    nur bei bfwidth kommt irgendein negativer wert heraus.. bin mir aber sicher dass die breite von 18-22 im header positioniert ist..... alle anderen scheinen zu stimmen .....hab keine ahnung woran das liegt....:(



  • Möglicherweise Overflow?



  • Nexus schrieb:

    Möglicherweise Overflow?

    die betreffenden bytes im header sind:

    height: 6D 00 00 00 wird richtig berrechnet
    width: 89 00 00 00 --> kommt -137 oda so raus... 😕

    so nebenbei:
    warum dieses Beispiel bei mir nicht funktioniert weiß ich nicht: --> http://www.c-plusplus.net/forum/viewtopic-var-t-is-16949-and-postdays-is-0-and-postorder-is-asc-and-start-is-0.html
    wahrscheinlich liegts daran dass ich mir die den inhalt der structs falsch zusammenbaue (unter linux kann ich die window.h leider nicht verwenden)...
    hab mir angeschaut wie in windows.h die structs aufgebaut sind ...da mach ich aus jedem WORD ein short und statt DWORD nehm ich long ... aber da liest er mir letztendlich einfach nicht das richtige ein....

    jetzt bin ich schon ne weile an der geschichte dran... und es will einfach nicht... einfach bitmap 24bit RGB einlesen...grml



  • Hi

    Das Problem liegt am int
    int = 32 Bit = 4 Byte
    Also passen die 4 Byte rein 😉

    ABER int kann positive und Negative Zahlen somit verlierst du 1 Bit (an das Vorzeichen)

    unsigned int und das Problem sollte sich erledigt haben.
    Steht übrignds auch im Bitmap Wicki so drinnen

    All values are stored as unsigned integers, unless explicitly noted.

    Was zwar nicht stimmen muss, aber logisch wäre.

    Zu der Umrechnung könntest du auch

    unsigned int bfSize = header[2] + (header[3] << 8) + (header[4] << 16) + (header[5] << 24);
    

    verwenden. Macht genau das selbe könnte eventuell auch etwas schneller sein (wobei ich das bezweifle ^^). Also reine Geschmackssache was du verwendest.

    Keros



  • hallo,
    danke für die antwort werd ich berücksichtien.
    ich bin mittlerweile auf noch eine möglickeit gestoßen:

    fread(header, 54, 1, f);
     width = *(int*) (header + 18);
    ....
    ...
    

    was wird denn hier gemacht? header is ein char array der länge 54 ...
    dazu zähle ich 18 und caste es auf int mit irgendwelchen zeigern?



  • Ist einfach nur Zeigerarithmetik.
    Die elemente eines Arrays werden hintereinander in den Speicher gelegt. Wenn man also zum Zeiger eine Zahl hinzu addiert geht man die einzelnen Elemente des Arrays durch.

    unsigned char array[10];
    int zahl = 0;
    
    // beide Zeilen machen das selbe
    array[5] = 10;
    *(array + 5) = 10;
    
    // alle 3 zeilen machen das selbe
    zahl = (int) array[5];
    zahl = (int) *(array + 5); // zuerst zu stelle 5 gehen dann auf wert zugreifen (*) und dann auf int casten
    zahl = *(int*) (array + 5); // zuerst zu stelle 5 gehen dann auf int zeiger casten und dann auf wert zugreifen (*)
    

    Hat unsigned int dein vorheriges Problem gelöst?

    Keros



  • Keros schrieb:

    Hat unsigned int dein vorheriges Problem gelöst?
    Keros

    Jap 🙂 herzlichen dank, es lag daran.
    werde aber trotzdem die Version mit der Zeigerarithmetik verwenden.
    sagt mir mehr zu als die rechen-wurst.

    das einlesen funktioniert soweit. heut werd ich mich noch ans modifizieren des bitmaps machen.
    ich müsste nur 24bit rgb unterstützen. d.h. im bitmap sind die hexazahlen immer im shema r g b r g b r g b usw..... abgespeichert und ein pixel entspricht einem trippel r g b.
    das heißt um einem bestimmten Pixel eine andere Farbe zu geben muss ich den bestimmten drei positionen in meinem array (wo ich die bilinformationen abgespeichert habe) welche das pixel in r g b repräsentieren , jeweils einen wert zwischen 0...255 zuordnen....?
    dann wär ein einzelnes pixel umgefärbt...

    ?



  • hallo,
    hab das ganze jetzt ein bisschen auf "more c++ style" umgemodelt. Allerdings stoße ich wieder auf probleme....
    so lese ich mein file ein:

    ifstream file("test.bmp", std::ios::binary | std::ios::in);
    
    	m_header = new char[54];
    	file.read(m_header, 54);
    
    	m_width = (unsigned char) m_header[18] ;   
    	m_height = (unsigned char) m_header[22] ;
    
    	m_size = m_width * m_height * 3;
    
    	vector<char> imgData(m_size);  
    
    	file.read(&imgData[0], m_size);
    	m_size = imgData.size();
    
    	cout << "BMP LOADET\n";
    

    ad zeilen 6 und 7:
    das auslesen der höehe und breite funktioniert. allerdings nur richtig bei kleinen dateien.. liegt das daran dass mein code nur position 18 betrachtet? könnte ich hier nicht einfach m_header[18] + m_header[19]...bis [21] machen damit alle vier Bytes betrachtet werden?

    des weiteren berechne ich glaub ich die größe (m_size) falsch.... breite * höhe * 3 ... (weil je drei bytes für ein pixel) ... bei manchen bmp files ist die größe aber größer... und somit fehlen ein paar zeilen im hexaeditor wenn ich mein file wieder rausschreibe.... ?? was fehlt mir noch? wär nett wenn sich das noch jemand anschaun könnt....


Anmelden zum Antworten