DDS画像を表示する

DDS画像を読み込みます。
DDS画像とは Direct Draw Surface ファイルの事です。
GLEW を使うと S3TC(DXTC)圧縮 を解凍できるようです。
↓こちらのサイトに読み込みプログラムがありましたので使わせて頂きます。

http://asura.iaigiri.com/OpenGL/gl7.html
ちょこっと改変してGLEWの初期化位置を変えてみました。

 

ファイル
main.cpp
sample.dds

main.cpp

#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")
#pragma comment(lib, "glew32.lib")
#include <GL/glew.h>
#include <GL/freeglut/freeglut.h>
#include <string>

#define WIDTH 320
#define HEIGHT 240
//各種構造体
typedef struct _DDPixelFormat
{
    GLuint size;
    GLuint flgas;
    GLuint fourCC;
    GLuint bpp;
    GLuint redMask;
    GLuint greenMask;
    GLuint blueMask;
    GLuint alphaMask;
} DDPixelFormat;

typedef struct _DDSCaps
{
    GLuint caps;
    GLuint caps2;
    GLuint caps3;
    GLuint caps4;
} DDSCaps;

typedef struct _DDColorKey
{
    GLuint lowVal;
    GLuint highVal;
} DDColorKey;

typedef struct _DDSurfaceDesc
{
    GLuint size;
    GLuint flags;
    GLuint height;
    GLuint width;
    GLuint pitch;
    GLuint depth;
    GLuint mipMapLevels;
    GLuint alphaBitDepth;
    GLuint reserved;
    GLuint surface;

    DDColorKey ckDestOverlay;
    DDColorKey ckDestBlt;
    DDColorKey ckSrcOverlay;
    DDColorKey ckSrcBlt;

    DDPixelFormat format;
    DDSCaps caps;

    GLuint textureStage;
} DDSurfaceDesc;

//DDSクラス
class DDSImage
{
protected:
    GLenum format;
    GLuint internalFormat;
    GLuint bpp;
    GLuint numMipmaps;
public:
    GLuint ID;
 GLuint imageSize;
    GLubyte *imageData;
 GLuint width;
    GLuint height;
    DDSImage();
    ~DDSImage();
    void DecompressDDS();
    bool ReadDDS(const char *filename);
    GLuint Load(const char *filename);
};
//コンストラクタ
DDSImage::DDSImage()
{
 imageSize = 0;
 imageData = NULL;
 format = GL_RGB;
 internalFormat = GL_RGB;
 width = 0;
 height = 0;
 bpp = 0;
 ID = 0;
 numMipmaps = 0;
}
//デストラクタ
DDSImage::~DDSImage()
{
 if ( imageData )
 {
  delete [] imageData;
  imageData = NULL;
 }
}
//DDSファイルの読み込み
bool DDSImage::ReadDDS(const char *filename)
{
    FILE *fp;
    char magic[4];
    int mipmapFactor;
    long curr, end;
    DDSurfaceDesc ddsd;
    // ファイルを開く
    fp = fopen(filename, "rb");
    if ( !fp )
    {
        printf("ファイルを開けませんでした\n");
        return false;
    }
    // マジックを読み取り
    fread(&magic, sizeof(char), 4, fp);
    // マジックをチェック
    if ( strncmp(magic, "DDS ", 4 ) != 0 )
    {
        printf("DDSファイルではありません\n");
        fclose(fp);
        return false;
    }
    // ヘッダーを読み取り
    fread(&ddsd, sizeof(ddsd), 1, fp);
    // 幅・高さを格納
    height = ddsd.height;
    width = ddsd.width;
    numMipmaps = ddsd.mipMapLevels;
    // フォーマット判別
    switch ( ddsd.format.fourCC )
    {
    case '1TXD':
        // DXT1
        format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
        internalFormat = 3;
        mipmapFactor = 2;
        break;
    case '3TXD':
        // DXT3
        format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
        internalFormat = 4;
        mipmapFactor = 4;
        break;
    case '5TXD':
        // DXT5
        format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
        internalFormat = 4;
        mipmapFactor = 4;
        break;
    default:
        printf("未対応の形式です\n");
        return false;
    }
    // テクセルデータのサイズを算出
    curr = ftell(fp);
    fseek(fp, 0, SEEK_END);
    end = ftell(fp);
    fseek(fp, curr, SEEK_SET);
    imageSize = end - curr;
    imageData = new GLubyte [imageSize];
    // ピクセルデータの読み込み
    fread(imageData, sizeof(GLubyte), imageSize, fp);
    // ファイルを閉じる
    fclose(fp);
    return true;
}
//S3TC圧縮の解凍作業
void DDSImage::DecompressDDS()
{
    int blockSize;
    int offset = 0;
    GLsizei mWidth = width, mHeight = height, mSize = 0;
    // DXT1
    if ( format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT )
        blockSize = 8;
    // DXT3, DXT5
    else
        blockSize = 16;
    // 解凍
    for ( int i=0; i<(int)numMipmaps; i++ )
    {
        mSize = ( (mWidth+3)/4 ) * ( (mHeight+3)/4 ) * blockSize;
        glCompressedTexImage2D(GL_TEXTURE_2D, i, format, mWidth, mHeight, 0, mSize, imageData + offset );
        if ( mWidth >> 1 )  mWidth = (mWidth >> 1);
        else    mWidth = 1;
        if ( mHeight >> 1 ) mHeight = (mHeight >> 1);
        else    mHeight = 1;
        offset += mSize;
    }
}
//DDSファイルを読み込み,テクスチャを生成する
GLuint DDSImage::Load(const char *filename)
{
    // ファイルの読み込み
    if ( !ReadDDS(filename) )
        return 0;
    // テクスチャを生成
    glGenTextures(1, &ID);
    // テクスチャをバインド
    glBindTexture(GL_TEXTURE_2D, ID);
    // 拡大・縮小する方法の指定
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    // テクスチャ環境の設定
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    // 解凍作業
    DecompressDDS();
    if ( imageData )
    {
        delete [] imageData;
        imageData = NULL;
    }
    glBindTexture(GL_TEXTURE_2D, 0);
    // 生成したテクスチャ番号を返す
    return ID;
}

DDSImage texture;
void display(void)
{
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
 glOrtho(0.0, WIDTH, HEIGHT, 0.0, -1.0, 1.0);

 glEnable(GL_TEXTURE_2D);//テクスチャ有効
 glBindTexture(GL_TEXTURE_2D, texture.ID);
    glEnable(GL_ALPHA_TEST);//アルファテスト開始
    glBegin(GL_POLYGON);
 glTexCoord2f(0.0f, 1.0f); glVertex2d(10 , 230);//左下
 glTexCoord2f(0.0f, 0.0f); glVertex2d(10 ,  10);//左上
 glTexCoord2f(1.0f, 0.0f); glVertex2d( 310 ,  10);//右上
 glTexCoord2f(1.0f, 1.0f); glVertex2d( 310 , 230);//右下
    glEnd();
    glDisable(GL_ALPHA_TEST);//アルファテスト終了
    glDisable(GL_TEXTURE_2D);//テクスチャ無効

 glutSwapBuffers();
}
void idle(void)
{
 glutPostRedisplay();
}
void Init(){
 //GLEWの初期化
 if(glewInit() != GLEW_OK)printf("GLEWの初期化に失敗しました\n");
 glClearColor(0.0, 0.0, 0.0, 1.0);
 glOrtho(0, WIDTH, HEIGHT, 0, -1, 1);
 texture.Load("sample.dds");
}
int main(int argc, char *argv[])
{
 glutInitWindowPosition(100, 100);
 glutInitWindowSize(WIDTH, HEIGHT);
 glutInit(&argc, argv);
 glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
 glutCreateWindow("画像を読み込んで表示");
 glutDisplayFunc(display);
 glutIdleFunc(idle);
 Init();
 glutMainLoop();
 return 0;
}

 

 

 

 

 

 

 

最終更新:2015年01月03日 22:04
添付ファイル