简体   繁体   English

如果图像由 Resource.rc 文件加载,则可以使用 OpenGL 正确显示图像

[英]Properly display images with OpenGL if the image is loaded by Resource.rc file

I have two choices.我有两个选择。 I can read my image pinmap.jpg from Resource.rc or read the image from STBI_Image library.我可以从Resource.rc读取我的图像pinmap.jpg或从STBI_Image库读取图像。

// Simple helper function to load an image into a OpenGL texture with common settings
inline bool ReadImageFromResource(GLuint* out_texture, int width, int height) {
    // Locate the resource in the application's executable.
    HRSRC imageResHandle = FindResource(
        NULL,             // This component.
        MAKEINTRESOURCE(IDR_IMAGE1),   // Resource name.
        L"Image");        // Resource type.
    HRESULT hr = (imageResHandle ? S_OK : E_FAIL);

    // Load the resource to the HGLOBAL.
    HGLOBAL imageResDataHandle = NULL;
    if (SUCCEEDED(hr)) {
        imageResDataHandle = LoadResource(NULL, imageResHandle);
        hr = (imageResDataHandle ? S_OK : E_FAIL);
    }

    // Lock the resource to retrieve memory pointer.
    LPVOID image_data = NULL;
    if (SUCCEEDED(hr)) {
        image_data = LockResource(imageResDataHandle);
        UnlockResource(imageResDataHandle);
        hr = (image_data ? S_OK : E_FAIL);
    }

    if (image_data == NULL)
        return false;

    // Create a OpenGL texture identifier
    GLuint image_texture;
    glGenTextures(1, &image_texture);
    glBindTexture(GL_TEXTURE_2D, image_texture);

    // Setup filtering parameters for display
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // This is required on WebGL for non power-of-two textures
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // Same

    // Upload pixels into texture
#if defined(GL_UNPACK_ROW_LENGTH) && !defined(__EMSCRIPTEN__)
    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
#endif
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image_data);
    *out_texture = image_texture;
    return true;
}

The results is:结果是:

在此处输入图像描述

When I read the image from STBI-library, then the image looks like this:当我从 STBI 库中读取图像时,图像如下所示:

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

// Simple helper function to load an image into a OpenGL texture with common settings
inline bool ReadImageFromSTBI(const char* filename, GLuint* out_texture, int* out_width, int* out_height)
{
    // Load from file
    int image_width = 0;
    int image_height = 0;
    unsigned char* image_data = stbi_load(filename, &image_width, &image_height, NULL, 4);
    if (image_data == NULL)
        return false;

    // Create a OpenGL texture identifier
    GLuint image_texture;
    glGenTextures(1, &image_texture);
    glBindTexture(GL_TEXTURE_2D, image_texture);

    // Setup filtering parameters for display
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // This is required on WebGL for non power-of-two textures
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // Same

    // Upload pixels into texture
#if defined(GL_UNPACK_ROW_LENGTH) && !defined(__EMSCRIPTEN__)
    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
#endif
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image_width, image_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data);
    stbi_image_free(image_data);

    *out_texture = image_texture;
    *out_width = image_width;
    *out_height = image_height;

    return true;
}

You see the difference between the color and the image above is shifted due to the C to the left.您会看到颜色和上图之间的差异由于C向左移动。 It should be at the right side of the image.它应该在图像的右侧。 Notice that the image above is displayed with GL_RBG and this image is displayed with GL_RGBA .请注意,上面的图像是用GL_RBG显示的,而这个图像是用GL_RGBA显示的。 Else, I cannot display the image.否则,我无法显示图像。

在此处输入图像描述

Question:题:

It seems to be different data depending on how I load the data of the image.根据我加载图像数据的方式,它似乎是不同的数据。 I have looked at the data of the image.我看过图像的数据。 The variable image_data differes.变量image_data不同。

How do I properly display images with OpenGL if the image is loaded by Resource.rc file and not loaded by file such as STBI-library?如果图像由 Resource.rc 文件加载而不是由 STBI 库等文件加载,我如何使用 OpenGL 正确显示图像?

LoadResource does not decode, decompress, or interpret the resource data in any way. LoadResource不会以任何方式解码、解压缩或解释资源数据。 What you get in your image_data is a pointer to a memory block that contains exactly the contents of your pinmap.jpg file.您在image_data中得到的是指向内存块的指针,该内存块恰好包含pinmap.jpg文件的内容。

Interestingly, what you have is a BITMAP rather than an actual JPEG file.有趣的是,您拥有的是 BITMAP 而不是实际的 JPEG 文件。 If it wasn't, you'd get a bunch of noise instead of anything resembling your image.如果不是,你会得到一堆噪音而不是任何与你的形象相似的东西。 From what my crystal ball tells me, you imported that once has been JPEG into the resource editor with the "Add Resource > Import..." function of Visual Studio.根据我的水晶球告诉我的情况,您使用 Visual Studio 的“添加资源 > 导入...”功能将曾经是 JPEG 的文件导入到资源编辑器中。 When done that way, it converts the file to a BITMAP, overwriting the original on disk.完成后,它将文件转换为 BITMAP,覆盖磁盘上的原始文件。 (Seriously, Microsoft, what were you smoking??) (说真的,微软,你在抽什么烟??)

The results you observe thus can be explained as follows:您观察到的结果可以解释如下:

  • The horizontal wrap-around offset is due to the BITMAP file and info headers at the beginning of the resource.水平环绕偏移是由于资源开头的 BITMAP 文件和信息标头引起的。
  • The colors are off because of the BGR <-> RGB mismatch.由于 BGR <-> RGB 不匹配,颜色已关闭。

If you want to keep the resource as JPEG, you can add it by manually editing the rc file, or by reverting the file after Visual Studio is done with messing it up.如果要将资源保留为 JPEG,可以通过手动编辑 rc 文件或在 Visual Studio 完成处理后还原文件来添加它。 However, if you choose this route, you must decompress the JPEG (because OpenGL expects plain RGB data rather than JPEG).但是,如果您选择这条路线,则必须解压缩 JPEG(因为 OpenGL 需要纯 RGB 数据而不是 JPEG)。 One way would be to call stbi_load_from_memory on that image_data you got from LockResource .一种方法是在从image_data获得的LockResource stbi_load_from_memory Stbi will decompress the JPEG into RGB (in that order). Stbi 会将 JPEG 解压缩为 RGB(按此顺序)。

If you want to keep working with the BITMAP resource, then all you need is to skip the headers and flip the channels.如果您想继续使用 BITMAP 资源,那么您只需跳过标题并翻转频道即可。

For skipping the headers you parse the BITMAPFILEHEADER that's located at image_data .为了跳过标头,您解析位于image_dataBITMAPFILEHEADER The offset to the pixel data is in the bfOffBits field in the header:像素数据的偏移量位于标头中的bfOffBits字段中:

actual_image_data = (char*)image_data + ((BITMAPFILEHEADER*)image_data)->bfOffBits;

For fixing the channel order you can pass GL_BGR for the format parameter ( not the internalformat !!) of glTexImage2D :为了修复通道顺序,您可以为glTexImage2Dformat参数(不是internalformat格式!!)传递GL_BGR

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, actual_image_data);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM