使用GDAL库加载图像(VC ++)

时间:2013-12-02 14:38:20

标签: c++ opengl mfc gdal

当我尝试使用GDAL库加载图像并将其实现(图像)到OpenGL控件时,我遇到了问题。您可以在picture上看到颜色问题。

这是从图像生成纹理的函数:

GLuint COpenGLControl::ReadGDALData(CString filename)
{
BYTE* tempReturn;
GLuint texture;

GDALDataset *poDataset;
GDALAllRegister();
poDataset = (GDALDataset *) GDALOpen((const char *)(CStringA)filename, GA_ReadOnly);

int Height = poDataset->GetRasterXSize(), Width = poDataset->GetRasterYSize();
LONG LineBytes = (Width*8+31)/32*4;
BYTE * pData  = (BYTE *)new char[ LineBytes * Height * 3];

if (poDataset == NULL)
{
    AfxMessageBox("Couldn't open selected file!");
    return NULL;
}

nBands = poDataset->GetRasterCount();

GDALRasterBand **poBand;
poBand = new GDALRasterBand *[nBands];

if (poBand == NULL)
{
    AfxMessageBox("Couldn't open the bands!", MB_ICONWARNING);
    return NULL;
}

for (int i=0; i<nBands; i++)
{
    poBand[i] = poDataset->GetRasterBand(i+1);
    if (poBand[i] == NULL)
    {
        AfxMessageBox("Couldn't open selected bands", MB_ICONWARNING);
        return NULL;
    }
}

int BandChoice = 2;

nXsize = poBand[BandChoice]->GetXSize();
nYsize = poBand[BandChoice]->GetYSize();

if (BandChoice == 1)
{
    poBandBlock_Gray = (BYTE*)CPLMalloc(sizeof(BYTE)*(nXsize*nYsize));
    poBand[BandChoice]->RasterIO(GF_Read, 0, 0, nXsize, nYsize, poBandBlock_Gray, nXsize, nYsize, poBand[BandChoice]->GetRasterDataType(), 0, 0);
}
else
{
    int nXsize_R, nXsize_G, nXsize_B;
    int nYsize_R, nYsize_G, nYsize_B;

    int BandChoiceR = 0;
    int BandChoiceG = 1;
    int BandChoiceB = 2;

    nXsize_R = poBand[BandChoiceR]->GetXSize();
    nXsize_G = poBand[BandChoiceG]->GetXSize();
    nXsize_B = poBand[BandChoiceB]->GetXSize();
    nYsize_R = poBand[BandChoiceR]->GetYSize();
    nYsize_G = poBand[BandChoiceG]->GetYSize();
    nYsize_B = poBand[BandChoiceB]->GetYSize();

    nXsize = nXsize_R;
    nYsize = nYsize_R;

    poBandBlock_R = (BYTE*)CPLMalloc(sizeof(BYTE)*(nXsize_R*nYsize_R));
    poBandBlock_G = (BYTE*)CPLMalloc(sizeof(BYTE)*(nXsize_G*nYsize_G));
    poBandBlock_B = (BYTE*)CPLMalloc(sizeof(BYTE)*(nXsize_B*nYsize_B));

    poBand[BandChoiceR]->RasterIO(GF_Read, 0, 0, nXsize_R, nYsize_R, poBandBlock_R, nXsize_R, nYsize_R, poBand[BandChoiceR]->GetRasterDataType(), 0, 0);
    poBand[BandChoiceG]->RasterIO(GF_Read, 0, 0, nXsize_G, nYsize_G, poBandBlock_G, nXsize_G, nYsize_G, poBand[BandChoiceG]->GetRasterDataType(), 0, 0);
    poBand[BandChoiceB]->RasterIO(GF_Read, 0, 0, nXsize_B, nYsize_B, poBandBlock_B, nXsize_B, nYsize_B, poBand[BandChoiceB]->GetRasterDataType(), 0, 0);

    delete poDataset;
}

if (BandChoice == 1)
{
    for ( int i=0; i < Height; i++)
    {
        for ( int j=0; j < Width; j++)
        {
            pData[(Height-i-1) * LineBytes + j] = poBandBlock_Gray[i*Width + j];
        }
    }

    CPLFree(poBandBlock_Gray);
}
else
{
    int j2 ;
    for ( int i=0; i<Height; i++)
    {
        for ( int j=0, j2=0; j < Width, j2 < 3 * Width; j++, j2+=3)
        {
            pData[(Height-i-1)*LineBytes + j2+2] = poBandBlock_R[i*Width + j];
            pData[(Height-i-1)*LineBytes + j2+1] = poBandBlock_G[i*Width + j];
            pData[(Height-i-1)*LineBytes + j2] = poBandBlock_B[i*Width + j];
        }
    }

    CPLFree(poBandBlock_B);
    CPLFree(poBandBlock_R);
    CPLFree(poBandBlock_G);
}

// allocate a texture name
glGenTextures( 1, &texture );

// select our current texture
glBindTexture( GL_TEXTURE_2D, texture );

// select modulate to mix texture with color for shading
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );

// when texture area is small, bilinear filter the closest mipmap
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
                 GL_LINEAR_MIPMAP_NEAREST );
// when texture area is large, bilinear filter the first mipmap
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

// if wrap is true, the texture wraps over at the edges (repeat)
//       ... false, the texture ends at the edges (clamp)
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, FALSE );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, FALSE );

// build our texture mipmaps
gluBuild2DMipmaps( GL_TEXTURE_2D, 3, Width, Height, GL_RGB, GL_UNSIGNED_BYTE, pData );

// free buffer
free( pData );

return texture;
}

这是Draw函数:

void COpenGLControl::OnDraw(CDC *pDC)
{
// TODO: Camera controls
wglMakeCurrent(hdc,hrc);

// Set color to use when clearing the background.
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClearDepth(1.0f);

// Turn on backface culling
glFrontFace(GL_CCW);
glCullFace(GL_FRONT_AND_BACK);

// Turn on depth testing
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);

glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear all objects

glEnable( GL_TEXTURE_2D ); // enable texture for 2 dimensions

glPushMatrix();

if (filename.IsEmpty() == false)
{
    imgData = ReadGDALData( filename );
    glBindTexture( GL_TEXTURE_2D, imgData );
    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear all objects

    glLoadIdentity ();
    gluLookAt      (0,0,1,0,0,0,0,1,0);
    glTranslatef   (m_fPosX, m_fPosY, 0.0f);
    glScalef       (m_fZoom,m_fZoom,1.0);

    glBegin( GL_QUADS ); // apply loaded texture to viewport
        glTexCoord2d(0.0,0.0); glVertex2d(-1.0,-1.0);
        glTexCoord2d(1.0,0.0); glVertex2d(+1.0,-1.0);
        glTexCoord2d(1.0,1.0); glVertex2d(+1.0,+1.0);
        glTexCoord2d(0.0,1.0); glVertex2d(-1.0,+1.0);
    glEnd();
}

glPopMatrix();

glDisable( GL_TEXTURE_2D );

glFlush();

// Swap buffers
SwapBuffers(hdc);

wglMakeCurrent(NULL, NULL);
}

1 个答案:

答案 0 :(得分:0)

问题不在于颜色,而是(根据我从样本中可以看出的)数据的打包方式。查看OpenGL缓冲区期望的字节排序/行填充/颜色打包,以及它在GDAL加载器中提供的内容。这里只是一个预感,但看起来你的OpenGL需要你的RGB结构中的第4个(alpha)组件,但你的GDAL代码不提供它。此外,您的GDAL加载程序在32位边界上对齐,检查您的OpenGL纹理调用是否也需要。你是否从一个样本中复制/粘贴GDAL加载器,有人用它来绘制BitBlt()?看起来就是这样。