2012-01-13 19 views
1

私は、3Dオブジェクトのテクスチャとして使用するために、TGAファイルを読み込む際の基本的なOpenGlチュートリアルを行ってきました。私は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); 
}; 

負荷TGA機能がCPPである:

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 
} 

いくつかのデータをロードするようだが、それがあることを返し続けますそれは失敗した。なぜどんな援助が大いに評価されるでしょうか。もしそれがちょっとばかげているのであれば、私は気付いていますが、私は何が重要であるかどうか分かりません。

更新日: 私は関数を書き換えました。私が使っていたifsteamは、問題の原因と思われました。具体的には、入力したデータよりもはるかに多くのデータをロードしようとします。私はその行動の原因を知らないが、私は以下の機能コードを列挙した。あなたのお手伝いをしていただきありがとうございます。

+3

あなたは、デバッグから何を学びましたか? –

+0

残念ながら、それほど多くはありません。 imageDataポインタは、ある種のデータを読み込んでいるようですが、条件付きでは失敗します。 – Donutfiend84

+2

あなたは現在の問題に関連していない 'delete [] imageData'を使うべきであることに注意してください。 – rotoglup

答えて

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

+0

私は、明らかに間違って配置されたときに「うまく動作する」ソリューションに固執することをお勧めしません。この場合、 'beg'と' 18 'の代わりに 'SizeOf(tgaHeader)'のようなものが必要です。質問 - デバッガはあなたの友人です - あなたが持っている 'file.read'に何が間違っているかを確認してください。 – Kromster

+0

'ColorMapType!= 0'もチェックしてください。 – Kromster

0

問題は圧縮されたTGAをサポートしていないTGAアルゴリズムに依存する可能性があります。

TGAを圧縮しないで、TGAオーダー(重要度は低い)がBottom Left原点であることを確認してください。

私は通常、GIMPを使用していますが、同じ時にRLE圧縮のチェックを外し、左下の配置を行います。

+1

なぜチェックがあるのですか? 'if(TGAheader.ImageType!= 2)false false;を返します。タイプ2は非圧縮TGAの略です。 TGAオーダーが逆さまであれば、ローディングには影響しません。イメージを逆さにしてレンダリングするだけです。 – Kromster

関連する問題