Bytes og char*

Tags:    c++

<< < 12 > >>
Hej

Jeg prøver at læse en bmp-fil.

Fold kodeboks ind/udKode 


Problemet er at det virker som om den læser for meget. De første 2 bytes i en bmp fil svarer til BM. Læser den en ekstra byte med der. Dette rykker på byterækkefølgen i hele headeren, så alt kommer en byte for tidligt. Reserved2 får f.eks. en værdi større end nul hvilket den ikke må.

Man kan se det ved at når den udskriver bfType kommer der et ekstra bogstav med, dette kunne måske skyldes at den læser videre i headerstrukturen indtil den når en byte med værdien 0 = '\0'. Men dette forklarer ikke forskydelsen.

Nogen der ved hvad der sker?



Din bfType er af typen WORD, som ikke kan skrives ud med %s. %s forventer en pointer til en null termineret streng.

Derudover kan du ikke stole på, at elementerne i din struct er pakket, som du har defineret. Hvis compileren mener, at et andet layout er mere optimalt, så optimerer den.

Der er bedre at læse filen således:

fread(&aBMPfileHeader.bfType, sizeof(WORD), 1, pBMPfile);
fread(&aBMPfileHeader.bfSize., sizeof(DWORD), 1, pBMPfile);

...osv. og også hele tiden tjekke, om du har læst det forventede antal bytes.



Det er et velkendt problem, det kaldes alignment:
http://en.wikipedia.org/wiki/Packed

I korte træk er problemet at compileren gerne vil have word og dword til at ligge på pæne adresser. Normalt forsøger den finde en adresse/offset der overholder kravet:
offset%sizeof(member) == 0
Du har en DWORD bfSize som du gerne ville have til at ligge 2 bytes inde, men som kommer til at ligge 4 bytes inde i strukturen.

Du kan prøve at tilføje disse:
printf("The size of the structure is %d\n", sizeof(BMPfileHeader));
printf("The offset of bfSize is %d\n", offsetof(BMPfileHeader, bfSize));

Den sidste kræver at du inkluderer stddef.h

Hvis alt var som du gerne ville, skulle den skrive 14 og 2, men den skriver (sandsynligvis) 16 og 4.

I artiklen jeg linker til er der nogle anvisninger på hvordan du undgår problemet.



Mange tak for jeres hjælp.

Bertel dine tal på strukturen er korrekt. Den var faktisk 16 bytes stor selvom jeg kun har fyldt den med 14 byte af datatyper.

Hvordan udskriver jeg så bfType, hvis ikke med cast til char*?

Den udskriver som sagt stadig de to korrekte tegn efterfulgt af skrot. Er dette fordi når jeg tar adressen på bfType og caster den til char* så læser den bare videre med resten af dataene?



Ja, den læser videre, indtil den møder et 0/´\0' eller programmet "dør"

Du kan udskrive bfType med:
printf("Type: %c%c\n", ((char *)(&aBMPfileHeader.bfType))[0], ((char *)(&aBMPfileHeader.bfType))[1]);



Ja %c virker, tak.

Har nu arbejdet lidt videre og er i gang med lidt test af læsning af pixelsene:

Fold kodeboks ind/udKode 


Problemet er at den aldrig bliver færdig med at læse?

Hvis jeg erstatter fseek med fread stopper den, men først efter den har taget en ekstra runde; hvordan den får læst ekstra fra filen ved jeg ikke?

Det skal siges at padding = 2 i dette tilfælde, men selv om den var 0 ville den 'file pointeren' vel alligevel komme videre pga. fread.



Indlæg senest redigeret d. 28.03.2009 23:09 af Bruger #14645
Du skal undlade at bruge feof. Problemet er at den først returnerer true når du har forsøgt at læse ud over enden på filen, ikke når du er ved enden på filen.
Der er heller ikke nogen grund til at bruge den, du ved hvor mange bytes du skal læse.



Ændrede programmet til ikke at bruge feof, og nu virker det perfekt.

Du skal undlade at bruge feof. Problemet er at den først returnerer true når du har forsøgt at læse ud over enden på filen, ikke når du er ved enden på filen.
Der er heller ikke nogen grund til at bruge den, du ved hvor mange bytes du skal læse.


Ville også være mit gæt. Men det forklarer vel ikke at den aldrig bliver færdig??



Indlæg senest redigeret d. 28.03.2009 23:32 af Bruger #14645
Jeg ved ikke præcist hvorfor den ikke bliver færdig, måske fordi din fseek flyter fil-pointeren tilbage, så du kan læse i for-loopen for evigt?



Jeg er kommet ud for et mystisk problem med mit program. Så hvis nogen har lidt ting til at kigge på det ville jeg være taknemmelig.

Problemet er at jeg læser en fil ind, jeg synes ikke jeg kan finde nogle problemer med det. Jeg læser tre forskellige dele ind:

Filheaderen:
Fold kodeboks ind/udKode 


Informationsheaderen:
Fold kodeboks ind/udKode 


og pixel dataene:

Fold kodeboks ind/udKode 


Sådan som jeg kan se det bliver alle disse indlæst korrekt. Problemet opstår når jeg bruger lignende skrive operationer. Filheaderen og pixeldataene virker korrekt ved små eksempler. F.eks. have jeg et 2x2 billede hvor farverne blev lidt anderledes når jeg skrev billedet ud igen (kopierede). Jeg prøvede at skrive dele, filheader, infoheader og pixeldata ud og det viste sig at infoheaderen skrev 4 bytes mere ud end den burde, og disse 4 bytes lignede de første af pixeldataene (men det er jeg ingengang sikker på for farverne var blevet anderledes).

Jeg prøvede at udkommentere et af de DWORDs som infoheaderen udskrev og filen med de 70 bytes kom nu ud som 70 bytes og var en præcis kopi. Her er det store problem så:

Der går et eller andet grueligt galt med større filer. Når jeg prøver med en fil på 75294 bytes får jeg en med 75104 bytes som er ugyldig. Jeg har også prøvet at få en ud som var større-

Mine skriveoperationer er som følgende:

filheader skriv:
Fold kodeboks ind/udKode 


infoheader skriv:
Fold kodeboks ind/udKode 


pixel data skriv:
Fold kodeboks ind/udKode 


Som sagt tror jeg ikke det har noget med packing at gøre fordi den læser filen korrekt.

Hvis nogen gerne vil have hele 'projektet' for at gøre det mere overskuelig så skriv lige (der er 340 linier med det meste er bare ligesom de ovenstående skriv og read rutiner).

På forhånd tak.



Indlæg senest redigeret d. 29.03.2009 15:49 af Bruger #14645
Okay har fået løst det.. Det var 2 fejl jeg selv har lavet. Den ene var let da jeg så.

biPlanes og biBitCount fylder ikke hver 4 byte men 2 bytes.

Den anden bar meget mere grum og tog timer at finde..

For at finde den nødvendige padding have jeg sagt at der sådan at den skulle være sådan at antallet af bytes i en række i billedet skulle være en faktor af 4. Men jeg kom til at bruge pixels i stedet for bytes hvilket er 1/3 af antallet af bytes.
Mange tak for hjælpen med alt det andet Bertel og Robert.



Indlæg senest redigeret d. 29.03.2009 23:10 af Bruger #14645
<< < 12 > >>
t