Loading a tga/bmp file in C++/OpenGL

前端 未结 2 1856
甜味超标
甜味超标 2020-12-17 19:42

I\'m trying to load a tga/bmp file. This works fine, but the end result looks like this:

\"enter

2条回答
  •  鱼传尺愫
    2020-12-17 20:33

    You can load a bitmap and a tga file using these..

    #include 
    #include 
    
    #ifdef __APPLE__
    #include 
    #include 
    #endif
    
    
    #ifdef _WIN32
    #include 
    #include 
    #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 Pixels;
    
    public:
        BMP(const char* FilePath);
        std::vector 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 FileInfo(Length);
        hFile.read(reinterpret_cast(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(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's:

    #include 
    #include 
    
    #ifdef __APPLE__
    #include 
    #include 
    #endif
    
    
    #ifdef _WIN32
    #include 
    #include 
    #endif
    
    typedef union PixelInfo
    {
        std::uint32_t Colour;
        struct
        {
            std::uint8_t R, G, B, A;
        };
    } *PPixelInfo;
    
    class Tga
    {
    private:
        std::vector Pixels;
        bool ImageCompressed;
        std::uint32_t width, height, size, BitsPerPixel;
    
    public:
        Tga(const char* FilePath);
        std::vector 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 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(&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(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(&ChunkHeader), sizeof(ChunkHeader));
    
                if(ChunkHeader < 128)
                {
                    ++ChunkHeader;
                    for(int I = 0; I < ChunkHeader; ++I, ++CurrentPixel)
                    {
                        hFile.read(reinterpret_cast(&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(&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());
    
    }
    

提交回复
热议问题