سؤال

It appears that i am loading the image wrong. The image appears all scrambled. What am i doing wrong here?

int DrawGLScene(GLvoid) // Here's Where We Do All The Drawing
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer
    glLoadIdentity();   // Reset The Current Modelview Matrix

    glEnable(GL_TEXTURE_2D);
    GLuint texture = 0;
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    glBindTexture(GL_TEXTURE_2D, texture);

    FIBITMAP* bitmap = FreeImage_Load(FreeImage_GetFileType("C:/Untitled.bmp", 0), "C:/Untitled.bmp", BMP_DEFAULT);
    FIBITMAP *pImage = FreeImage_ConvertTo32Bits(bitmap);
    int nWidth = FreeImage_GetWidth(pImage);
    int nHeight = FreeImage_GetHeight(pImage);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, nWidth, nHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, (void*)FreeImage_GetBits(pImage));
    FreeImage_Unload(pImage);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glBegin(GL_QUADS);
    glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f);
    glTexCoord2f(0.0f, 1.0f); glVertex2f(-1.0f, 1.0f);
    glTexCoord2f(1.0f, 1.0f); glVertex2f(1.0f, 1.0f);
    glTexCoord2f(1.0f, 0.0f); glVertex2f(1.0f, -1.0f);
    glEnd();

    RECT desktop;
    const HWND hDesktop = GetDesktopWindow();
    GetWindowRect(hDesktop, &desktop);
    long horizontal = desktop.right;
    long vertical = desktop.bottom;

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glDisable(GL_TEXTURE_2D);
    return TRUE;    // Keep Going
}

what i see when the program runs What i see when the program runs what i expect to see when the program runs (bitmap i am loading) What i expect to see

هل كانت مفيدة؟

المحلول

Part of the problem here seems to be a mismatch between the format of the pixel data you're getting from FreeImage and the format expected by glTexImage2D.

FreeImage_ConvertTo32Bits is going to return an image with 32-bit pixel data. I haven't used FreeImage but usually that would mean that each pixel would have 4 8-bit components representing red, green, blue and alpha (opacity). The format of the data you get from the BMP file depends on the file and may or may not have an alpha channel in it. However it seems safe to assume that FreeImage_ConvertTo32Bits will return data with alpha set to 255 if your original image is fully opaque (either because your BMP file format lacked an alpha channel or because you set it to opaque when you created the file).

This is all fine, but the problem comes with the call to glTexImage2D. This function can take pixel data in lots of different formats. The format it uses for interpreting the data is determined by the parameters type and format as decribed here. The value of format in your code is GL_RGB. This says that each pixel has three components describing its red, green and blue components which appear in that order in the pixel data. The value of type (GL_UNSIGNED_BYTE) says each component is a single byte in size. The problem is that the alpha channel is missing, so glTexImage2D reads the pixel data from the wrong place. Also it seems that the order of the colours that FreeImage produces is blue-green-red, as pointed out by Roger Rowland. The fix is simple: set the format to GL_BGRA to tell glTexImage2D about the alpha components and the order of the data:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, nWidth, nHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, (void*)FreeImage_GetBits(pImage));

To see if this problem could explain the weird outputs, think about the big blocks of blue colour in your original image. According to GIMP this is largely blue with a smaller amount of green (R=0, G=162, B=232). So we have something like this:

B G R A B G R A B G R A ...   meaning of bytes from FreeImage_GetBits
1 - 0 1 1 - 0 1 1 - 0 1 ...   "values" of bytes (0 -> 0, - -> 162, 1 -> 232 or 255)
R G B R G B R G B R G B ...   what glTexImage2D thinks the bytes mean

The texture pixel colours here are: orange, light yellow, bright cyan and a purply colour. These repeat because reading 4 pixels consumes 12 bytes which is exactly equal to 3 of the original pixels. This explains the pattern you see running over much of your output image. (Originally I had gone through this using the RGBA order but the GBRA version is a better fit for the image - the difference is especially clear at the start of the rows).

However I must admit I'm not sure what's going on at the beginning and how to relate it to the pink square! So there might be other problems here, but hopefully using GL_BGRA will be a step in the right direction.

نصائح أخرى

You are making a 32 bpp image, so you need to have the correct texture declarations:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, nWidth, nHeight,
    0, GL_BGRA, GL_UNSIGNED_BYTE, (void*)FreeImage_GetBits(pImage));

Also, the FreeImage_GetBits function returns data which is normally aligned so that each row ends on a 4 byte boundary. So, if your image is 32 bpp (as your is), or if your image width is a power of two, it will be ok but otherwise, you will need to set the unpack alignment appropriately.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top