2013-12-15 15 views
10

tga/bmpファイルを読み込もうとしています。これは正常に動作しますが、最終結果は次のようになります。C++/OpenGLでtga/bmpファイルを読み込む

enter image description here

私は負荷にしようとしている画像は、次のようになります

enter image description here

私が使用しているコードの一部:

GLuint texture; 
const char* filename = "/Users/Admin/Documents/Visual Studio 2013/Projects/OpenGL/OpenGL/image.tga"; 

unsigned char* data; 
data = (unsigned char *) malloc(128 * 128 * 3); 
FILE* f; 
fopen_s(&f, filename, "rb"); 
fread(data, 128 * 128 * 3, 1, f); 

glGenTextures(1, &texture); 
glBindTexture(GL_TEXTURE_2D, texture); 

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 128, 128, 0, GL_RGB, GL_UNSIGNED_BYTE, data); 

誰かが私が間違っていることを知っていますか?

+4

TGAファイルはそうではないヘッダを持っていますか?それはあなたが128x128ピクセルの生であることを期待しているようです。なぜあなたはそれが働くことを期待するのか分かりません。 –

+0

C++を使っているのなら、なぜ 'malloc()'を使っているのですか? – Vallentin

+0

私はそれを別のチュートリアルで見ました。私はmalloc()を使っていろいろ試しましたが、結果は変わっていません – user3075425

答えて

15

あなたはこれらを使用してビットマップおよびTGAファイルを読み込むことができます。..

#include <vector> 
#include <fstream> 

#ifdef __APPLE__ 
#include <OpenGL/gl.h> 
#include <OpenGL/glu.h> 
#endif 


#ifdef _WIN32 
#include <GL/gl.h> 
#include <GL/glu.h> 
#endif 


typedef union PixelInfo 
{ 
    std::uint32_t Colour; 
    struct 
    { 
     std::uint8_t B, G, R, A; 
    }; 
} *PPixelInfo; 


class BMP 
{ 
private: 
    std::uint32_t width, height; 
    std::uint16_t BitsPerPixel; 
    std::vector<std::uint8_t> Pixels; 

public: 
    BMP(const char* FilePath); 
    std::vector<std::uint8_t> GetPixels() const {return this->Pixels;} 
    std::uint32_t GetWidth() const {return this->width;} 
    std::uint32_t GetHeight() const {return this->height;} 
    bool HasAlphaChannel() {return BitsPerPixel == 32;} 
}; 

BMP::BMP(const char* FilePath) 
{ 
    std::fstream hFile(FilePath, std::ios::in | std::ios::binary); 
    if (!hFile.is_open()) throw std::invalid_argument("Error: File Not Found."); 

    hFile.seekg(0, std::ios::end); 
    std::size_t Length = hFile.tellg(); 
    hFile.seekg(0, std::ios::beg); 
    std::vector<std::uint8_t> FileInfo(Length); 
    hFile.read(reinterpret_cast<char*>(FileInfo.data()), 54); 

    if(FileInfo[0] != 'B' && FileInfo[1] != 'M') 
    { 
     hFile.close(); 
     throw std::invalid_argument("Error: Invalid File Format. Bitmap Required."); 
    } 

    if (FileInfo[28] != 24 && FileInfo[28] != 32) 
    { 
     hFile.close(); 
     throw std::invalid_argument("Error: Invalid File Format. 24 or 32 bit Image Required."); 
    } 

    BitsPerPixel = FileInfo[28]; 
    width = FileInfo[18] + (FileInfo[19] << 8); 
    height = FileInfo[22] + (FileInfo[23] << 8); 
    std::uint32_t PixelsOffset = FileInfo[10] + (FileInfo[11] << 8); 
    std::uint32_t size = ((width * BitsPerPixel + 31)/32) * 4 * height; 
    Pixels.resize(size); 

    hFile.seekg (PixelsOffset, std::ios::beg); 
    hFile.read(reinterpret_cast<char*>(Pixels.data()), size); 
    hFile.close(); 
} 

int main() 
{ 
    BMP info = BMP("C:/Users/....../Desktop/SomeBmp.bmp"); 

    GLuint texture = 0; 
    glGenTextures(1, &texture); 
    glBindTexture(GL_TEXTURE_2D, texture); 
    glTexImage2D(GL_TEXTURE_2D, 0, info.HasAlphaChannel() ? GL_RGBA : GL_RGB, info.GetWidth(), info.GetWidth(), 0, info.HasAlphaChannel() ? GL_BGRA : GL_BGR, GL_UNSIGNED_BYTE, info.GetPixels().data()); 
} 

TGAさん:

#include <vector> 
#include <fstream> 

#ifdef __APPLE__ 
#include <OpenGL/gl.h> 
#include <OpenGL/glu.h> 
#endif 


#ifdef _WIN32 
#include <GL/gl.h> 
#include <GL/glu.h> 
#endif 

typedef union PixelInfo 
{ 
    std::uint32_t Colour; 
    struct 
    { 
     std::uint8_t R, G, B, A; 
    }; 
} *PPixelInfo; 

class Tga 
{ 
private: 
    std::vector<std::uint8_t> Pixels; 
    bool ImageCompressed; 
    std::uint32_t width, height, size, BitsPerPixel; 

public: 
    Tga(const char* FilePath); 
    std::vector<std::uint8_t> GetPixels() {return this->Pixels;} 
    std::uint32_t GetWidth() const {return this->width;} 
    std::uint32_t GetHeight() const {return this->height;} 
    bool HasAlphaChannel() {return BitsPerPixel == 32;} 
}; 

Tga::Tga(const char* FilePath) 
{ 
    std::fstream hFile(FilePath, std::ios::in | std::ios::binary); 
    if (!hFile.is_open()){throw std::invalid_argument("File Not Found.");} 

    std::uint8_t Header[18] = {0}; 
    std::vector<std::uint8_t> ImageData; 
    static std::uint8_t DeCompressed[12] = {0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; 
    static std::uint8_t IsCompressed[12] = {0x0, 0x0, 0xA, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; 

    hFile.read(reinterpret_cast<char*>(&Header), sizeof(Header)); 

    if (!std::memcmp(DeCompressed, &Header, sizeof(DeCompressed))) 
    { 
     BitsPerPixel = Header[16]; 
     width = Header[13] * 256 + Header[12]; 
     height = Header[15] * 256 + Header[14]; 
     size = ((width * BitsPerPixel + 31)/32) * 4 * height; 

     if ((BitsPerPixel != 24) && (BitsPerPixel != 32)) 
     { 
      hFile.close(); 
      throw std::invalid_argument("Invalid File Format. Required: 24 or 32 Bit Image."); 
     } 

     ImageData.resize(size); 
     ImageCompressed = false; 
     hFile.read(reinterpret_cast<char*>(ImageData.data()), size); 
    } 
    else if (!std::memcmp(IsCompressed, &Header, sizeof(IsCompressed))) 
    { 
     BitsPerPixel = Header[16]; 
     width = Header[13] * 256 + Header[12]; 
     height = Header[15] * 256 + Header[14]; 
     size = ((width * BitsPerPixel + 31)/32) * 4 * height; 

     if ((BitsPerPixel != 24) && (BitsPerPixel != 32)) 
     { 
      hFile.close(); 
      throw std::invalid_argument("Invalid File Format. Required: 24 or 32 Bit Image."); 
     } 

     PixelInfo Pixel = {0}; 
     int CurrentByte = 0; 
     std::size_t CurrentPixel = 0; 
     ImageCompressed = true; 
     std::uint8_t ChunkHeader = {0}; 
     int BytesPerPixel = (BitsPerPixel/8); 
     ImageData.resize(width * height * sizeof(PixelInfo)); 

     do 
     { 
      hFile.read(reinterpret_cast<char*>(&ChunkHeader), sizeof(ChunkHeader)); 

      if(ChunkHeader < 128) 
      { 
       ++ChunkHeader; 
       for(int I = 0; I < ChunkHeader; ++I, ++CurrentPixel) 
       { 
        hFile.read(reinterpret_cast<char*>(&Pixel), BytesPerPixel); 

        ImageData[CurrentByte++] = Pixel.B; 
        ImageData[CurrentByte++] = Pixel.G; 
        ImageData[CurrentByte++] = Pixel.R; 
        if (BitsPerPixel > 24) ImageData[CurrentByte++] = Pixel.A; 
       } 
      } 
      else 
      { 
       ChunkHeader -= 127; 
       hFile.read(reinterpret_cast<char*>(&Pixel), BytesPerPixel); 

       for(int I = 0; I < ChunkHeader; ++I, ++CurrentPixel) 
       { 
        ImageData[CurrentByte++] = Pixel.B; 
        ImageData[CurrentByte++] = Pixel.G; 
        ImageData[CurrentByte++] = Pixel.R; 
        if (BitsPerPixel > 24) ImageData[CurrentByte++] = Pixel.A; 
       } 
      } 
     } while(CurrentPixel < (width * height)); 
    } 
    else 
    { 
     hFile.close(); 
     throw std::invalid_argument("Invalid File Format. Required: 24 or 32 Bit TGA File."); 
    } 

    hFile.close(); 
    this->Pixels = ImageData; 
} 


int main() 
{ 
    Tga info = Tga("C:/Users/...../Desktop/SomeTGA.tga"); 

    GLuint texture = 0; 
    glGenTextures(1, &texture); 
    glBindTexture(GL_TEXTURE_2D, texture); 
    glTexImage2D(GL_TEXTURE_2D, 0, info.HasAlphaChannel() ? GL_RGBA : GL_RGB, info.GetWidth(), info.GetWidth(), 0, info.HasAlphaChannel() ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, info.GetPixels().data()); 

} 
+0

あなたのコードをありがとうが、RGBはラインRGBピクセルの意味は?Pixel = {0};あなたはRGBA構造体を意味しましたか?もっと多くの人を助けるためにクラスファイル全体を提供することはできますか? – wangdq

+0

@wangdqが修正されました。ヘッダーも追加されました。 – Brandon

+0

TGAは幅と高さがオフです。255 = 255(0xFF)になるようにする必要があります。 width = Header [13] * 256 + Header [12]; 高さ=ヘッダー[15] * 256 +ヘッダー[14]。 – GambitSunob

6

私はこの質問を「TGAファイルを読み込むにはどうすればよいですか?私が試したことはうまくいかなかった」と解釈しました。

正解は「私が書いたTGAファイルを読み込むこの関数をコピーアンドペーストする」ことはありません。それは受け入れられた答えが取っているアプローチです。しかし、バグが含まれている場合は機能するだけでなく、より保守性が高く、修正される可能性のあるソリューションが必要な場合は、ライブラリを使用する方がよいでしょう。あなた自身のソリューションをローリングすることは、学ぶ良い方法であり、励まされなければなりませんが、通常、何かを達成するための最良の方法または最も簡単な方法ではありません。

独自の関数をロールして読み込む代わりに、実際の画像ライブラリを使用します。データ形式に関するあなたの前提は正しくないので、取得しているデータは二重です。あなたは、データが128x128ピクセルの生であると仮定しているようです。

http://tgalib.sourceforge.net/は、TGAファイルを読み取るためのオープンソースライブラリです。たとえば、それを使用します。

https://github.com/nothings/stbはTGAファイルをロードに加えて、OpenGLのプログラムのために便利になるでしょう他のものをたくさん持っている(パブリックドメイン)より自由なライセンスを持つ別の代替です。

両方のライブラリは、オンラインで見つかったコピー貼り付けコードよりも優れた選択肢です。

関連する問題