[C++] TGA header direct inladen in structure

Pagina: 1
Acties:

  • AuC
  • Registratie: Januari 2003
  • Laatst online: 03-04 14:09
Ik ben, na een lange pauze, weer eens begonnen met het maken van kleine demotjes in OpenGL.Op dit moment ben ik beland bij het inladen van een TGA texture. Aangezien ik het leerzamer vind om deze code vanaf scratch zelf te schrijven heb ik enkele documenten m.b.t het formaat van TGA bestanden gedownload.

Ik stuit echter direct al op een probleem. Ik wil de TGA header direct inlezen vanaf het bestand, en in een structure plaatsen. De structure die ik hiervoor gebruik, ziet er als volgend uit:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
typedef struct
{
    unsigned char   bIdSize;            
    unsigned char   bColorMap;          
    unsigned char   bImageType;         
    short int       nColorMapOrigin;     
    short int       nColorMapLength;    
    unsigned char   nColorMapEntrySize; 
    short int       nOriginX;           
    short int       nOriginY;           
    short int       nWidth;             
    short int       nHeight;             
    unsigned char   bBits;              
    unsigned char   bDescriptor;        
} TGAHeader_t;


Ik laad de header in met de volgende functie:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
bool ATga::Load(std::string szFileName)
{
    std::ifstream   fFile;
    
    // Open the file
    fFile.open(szFileName.c_str(), std::ios::in | std::ios::binary);
    
    if(!fFile.is_open()) 
    {
        std::string strMsg = "Unable To Open Image \"" + szFileName + "\"";
        ::MessageBox(NULL, strMsg.c_str(), "TGA", MB_OK | MB_ICONERROR);
        fFile.close();
        return false;
    }
    
    // Read the header
    fFile.read((char*)&m_sHeader, sizeof(TGAHeader_t));
    fFile.close();
    
    return true;
}


Dat moet werken lijkt mij, of ik moet iets over het hoofd zien. En dat doe ik waarschijnlijk ook, want als ik alle variabelen in de header even naar een bestand schrijf, om te kijken of het goed ingelezen is, is de output als volgend:

m_sHeader.bIdSize: 0
m_sHeader.bColorMap: 1
m_sHeader.bImageType: 1
m_sHeader.nColorMapOrigin: -1536
m_sHeader.nColorMapLength: 6144
m_sHeader.nColorMapEntrySize: 0
m_sHeader.nOriginX: 0
m_sHeader.nOriginY: 25
m_sHeader.nWidth: 21
m_sHeader.nHeight: 8200
m_sHeader.bBits: 0
m_sHeader.bDescriptor: 0


Wat mij hierbij direct opvalt - en wat tevens het probleem is - is dat bijv. de waarde bij nOriginY eigenlijk de waarde is van nWidth is, en de waarde van nWidth die van nHeight. Het lijkt dus haast alsof ik een variabele te veel inlees, maar volgens enkele documenten over TGA bestanden ziet de header er precies zo uit, als dat ik hem inlees.

Ik heb vervolgens even rondgeneust op het wereld wijde web, hierbij keek ik hoe anderen de header inladen. Ik zie hier dat men alle waardes één voor één inleest, maar kan nergens informatie vinden over het in één keer correct inlezen van de header... :?

Dus mijn vraag: doe ik iets fout bij het inlezen van de header? Kan ik deze überhaupt op mijn manier inlezen, aangezien ik iedereen de variabelen één voor één zie inlezen? Of lees ik inderdaad een variabele te veel in?

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17:43

.oisyn

Moderator Devschuur®

Demotivational Speaker

Komt door alignment. Een primitive wordt typisch op z'n eigen grootte uitgelijnd, waardoor nColorMapOrigin bijvoorbeeld op offset 4 terecht komt ipv op offset 3 waar je 'm zou verwachten.

De oplossing voor je probleem is de compiler vertellen dat ie niet moet alignen, en het ligt aan de compiler hoe je dat moet doen. Gebruik #pragma pack voor visual studio, en __attribute__((packed)) voor gcc. Je moet zelf even in de docs kijken hoe je ze toe moet passen :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • AuC
  • Registratie: Januari 2003
  • Laatst online: 03-04 14:09
Dat ga ik eens proberen... Bedankt! :)