2012-01-13 162 views
1

我一直在通過加載TGA文件的基本OpenGl教程,將其用作3D對象上的紋理。我已經能夠從TGA頭部加載數據,但是當我嘗試加載實際的圖像數據時,它失敗了。我不確定它出錯的地方。這裏是我的紋理加載類:C++ OpenGL TGA加載失敗

頭文件

struct TGA_Header 
{ 
    GLbyte ID_Length; 
    GLbyte ColorMapType; 
    GLbyte ImageType; 
    // Color map specifications 
    GLbyte firstEntryIndex[2];  
    GLbyte colorMapLength[2]; 
    GLbyte colorMapEntrySize; 

    //image specification 
    GLshort xOrigin; 
    GLshort yOrigin; 
    GLshort ImageWidth; 
    GLshort ImageHeight; 
    GLbyte PixelDepth; 
    GLbyte ImageDescriptor; 
}; 

class Texture 
{ 
public: 
    Texture(string in_filename, string in_name = ""); 
    ~Texture(); 

public: 
    unsigned short width; 
    unsigned short height; 
    unsigned int length; 
    unsigned char type; 
    unsigned char *imageData; 
    unsigned int bpp; 
    unsigned int texID; 

    string   name; 

    static vector<Texture *> textures; 

private: 
    bool loadTGA(string filename); 
    bool createTexture(unsigned char *imageData, int width, int height, int type); 

    void swap(unsigned char * ori, unsigned char * dest, GLint size); 
    void flipImage(unsigned char * image, bool flipHorizontal, bool flipVertical, GLushort width, GLushort height, GLbyte bpp); 
}; 

這裏是在CPP負載TGA功能:

bool Texture::loadTGA(string filename) 
{ 
    TGA_Header TGAheader; 

    ifstream file(filename.data(), std::ios::in, std::ios::binary); 

    //make sure the file was opened properly 
    if (!file.is_open()) 
     return false; 

    if(!file.read((char *)&TGAheader, sizeof(TGAheader))) 
     return false; 


    //make sure the image is of a type we can handle 
    if(TGAheader.ImageType != 2) 
     return false; 

    width = TGAheader.ImageWidth; 
    height = TGAheader.ImageHeight; 
    bpp = TGAheader.PixelDepth; 

    if(width < 0 ||    // if the width or height is less than 0, than 
     height <= 0 ||    // the image is corrupt 
     (bpp != 24 && bpp != 32)) // make sure we are of the correct bit depth 
    { 
     return false; 
    } 

    //check for an alpha channel 
    GLuint type = GL_RGBA; 
    if (bpp == 24) 
     type = GL_RGB; 

    GLuint bytesPerPixel = bpp/8; 

    //allocate memory for the TGA so we can read it 
    GLuint imageSize = width * height * bytesPerPixel; 
    imageData = new GLubyte[imageSize]; 

    if (imageData == NULL) 
     return false; 

    //make sure we are in the correct position to load the image data 
    file.seekg(-imageSize, std::ios::end); 

    // if something when wrong, make sure we free up the memory 
    //NOTE: It never gets past this point. The conditional always fails. 
    if (!file.read((char *)imageData, imageSize)) 
    { 
     delete imageData; 

     return false; 
    } 

    //more code is down here, but it doesnt matter because it does not pass the above function 
} 

這似乎加載一些數據,但它一直返回該它失敗了。任何幫助爲什麼將不勝感激。如果它有點羅嗦,但我不確定什麼是或不重要。

更新: 所以,我只是重寫了函數。我使用的ifste似乎是問題的原因。具體來說,它會嘗試加載比我輸入的更多的字節數據。我不知道行爲的原因,但我已在下面列出了我的功能代碼。感謝大家的幫助。

+3

你是怎麼從調試學到了什麼? – 2012-01-13 06:00:05

+0

不幸的是,並不多。 imageData指針肯定會加載某種類型的數據,但它無論如何都會失敗。 – Donutfiend84 2012-01-13 06:34:34

+2

請注意,您應該使用'delete [] imageData',雖然 – rotoglup 2012-01-13 07:00:09

回答

0

因此,我從使用ifstream更改爲FILE。 ifstream正試圖加載比我在參數中列出的更多的字節。這是新的代碼。 (注:它仍然需要optomized。我相信有一些未使用的變量浮動,但它完美的工作。)。再次感謝大家的幫助。

頭文件:

//struct to hold tga data 
struct TGA_Header 
{ 
    GLbyte ID_Length; 
    GLbyte ColorMapType; 
    GLbyte ImageType; 
    // Color map specifications 
    GLbyte firstEntryIndex[2];  
    GLbyte colorMapLength[2]; 
    GLbyte colorMapEntrySize; 

    //image specification 
    GLshort xOrigin; 
    GLshort yOrigin; 
    GLshort ImageWidth; 
    GLshort ImageHeight; 
    GLbyte PixelDepth; 
    GLbyte ImageDescriptor; 
}; 

class Texture 
{ 
public: 
    //functions 
    Texture(string in_filename, string in_name = ""); 
    ~Texture(); 

public: 
    //vars 
    unsigned char *imageData; 
    unsigned int texID; 

    string   name; 

    //temp global access point for accessing all loaded textures 
    static vector<Texture *> textures; 

private: 
    //can add additional load functions for other image types 
    bool loadTGA(string filename); 
    bool createTexture(unsigned char *imageData, int width, int height, int type); 

    void swap(unsigned char * ori, unsigned char * dest, GLint size); 
    void flipImage(unsigned char * image, bool flipHorizontal, bool flipVertical, GLushort width, GLushort height, GLbyte bpp); 
}; 

#endif 

這裏是負載TGA功能:

bool Texture::loadTGA(string filename) 
{ 
    //var for swapping colors 
    unsigned char colorSwap = 0; 

    GLuint type; 
    TGA_Header TGAheader; 

    FILE* file = fopen(filename.c_str(), "rb"); 

    unsigned char Temp_TGAheader[18]; 

    //check to make sure the file loaded 
    if(file == NULL) 
     return false; 

    fread(Temp_TGAheader, 1, sizeof(Temp_TGAheader), file); 

    //pull out the relavent data. 2 byte data (short) must be converted 
    TGAheader.ID_Length = Temp_TGAheader[0]; 
    TGAheader.ImageType = Temp_TGAheader[2]; 
    TGAheader.ImageWidth = *static_cast<unsigned short*>(static_cast<void*>(&Temp_TGAheader[12])); 
    TGAheader.ImageHeight = *static_cast<unsigned short*>(static_cast<void*>(&Temp_TGAheader[14])); 
    TGAheader.PixelDepth = Temp_TGAheader[16]; 


    //make sure the image is of a type we can handle 
    if(TGAheader.ImageType != 2 || TGAheader.ImageWidth <= 0 || TGAheader.ImageHeight <= 0) 
    { 
     fclose(file); 
     return false; 
    } 

    //set the type 
    if (TGAheader.PixelDepth == 32) 
    { 
     type = GL_RGBA; 
    } 
    else if (TGAheader.PixelDepth == 24) 
    { 
     type = GL_RGB; 
    } 
    else 
    { 
     //incompatable image type 
     return false; 
    } 


    //remember bits != bytes. To convert we need to divide by 8 
    GLuint bytesPerPixel = TGAheader.PixelDepth/8; 

    //The Memory Required For The TGA Data 
    unsigned int imageSize = TGAheader.ImageWidth * TGAheader.ImageHeight * bytesPerPixel;// Calculate 

    //request the needed memory 
    imageData = new GLubyte[imageSize]; 

    if (imageData == NULL) // just in case 
     return false; 

    if(fread(imageData, 1, imageSize, file) != imageSize) 
    {  
     //Kill it 
     delete [] imageData; 
     fclose(file);           
     return false; 
    }  

    fclose(file); 

    for (unsigned int x = 0; x < imageSize; x +=bytesPerPixel) 
    { 
     colorSwap = imageData[x];  
     imageData[x] = imageData[x + 2];   
     imageData[x + 2] = colorSwap; 
    } 

    createTexture(imageData, TGAheader.ImageWidth, TGAheader.ImageHeight, type); 

    return true; 
} 
0

我不熟悉C++,很抱歉。

您確定該行file.seekg(-imageSize, std::ios::end);不應該是file.seekg(headerSize, std::ios::start);

從頭開始比從頭開始更有意義。

您還應該檢查ColorMapType != 0

P.S.這裏的if(width < 0 || height <=0寬度檢查也應該是<=

+0

我曾嘗試過: file.seekg(18,std :: ios :: beg); 但是由於它似乎沒有影響結果,所以我將它改回來了。 – Donutfiend84 2012-01-13 06:31:39

+0

我不認爲這是一個很好的做法,堅持只在明顯錯位的情況下才「正常工作」的解決方案。在這種情況下,它應該是'beg'和某種'SizeOf(tgaHeader)'而不是'18'。至於問題 - 調試器是你的朋友 - 檢查你有什麼'file.read'錯誤。 – Kromster 2012-01-13 06:51:39

+0

你也應該檢查'ColorMapType!= 0' – Kromster 2012-01-13 07:46:37

0

該問題可能取決於不支持壓縮TGA的TGA算法。

確保您不壓縮TGA,並且TGA順序(較不重要)位於左下角原點。

我通常使用GIMP,並在相同的時刻,取消RLE壓縮並放置左下對齊。

+1

這就是爲什麼有一個檢查:'如果(TGAheader.ImageType!= 2)返回false;'。類型2代表未壓縮的TGA。如果TGA順序顛倒,它不會影響加載,只是在渲染中顛倒顯示圖像。 – Kromster 2012-01-13 07:45:04