繁体   English   中英

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

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

我有两个选择。 我可以从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;
}

结果是:

在此处输入图像描述

当我从 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;
}

您会看到颜色和上图之间的差异由于C向左移动。 它应该在图像的右侧。 请注意,上面的图像是用GL_RBG显示的,而这个图像是用GL_RGBA显示的。 否则,我无法显示图像。

在此处输入图像描述

题:

根据我加载图像数据的方式,它似乎是不同的数据。 我看过图像的数据。 变量image_data不同。

如果图像由 Resource.rc 文件加载而不是由 STBI 库等文件加载,我如何使用 OpenGL 正确显示图像?

LoadResource不会以任何方式解码、解压缩或解释资源数据。 您在image_data中得到的是指向内存块的指针,该内存块恰好包含pinmap.jpg文件的内容。

有趣的是,您拥有的是 BITMAP 而不是实际的 JPEG 文件。 如果不是,你会得到一堆噪音而不是任何与你的形象相似的东西。 根据我的水晶球告诉我的情况,您使用 Visual Studio 的“添加资源 > 导入...”功能将曾经是 JPEG 的文件导入到资源编辑器中。 完成后,它将文件转换为 BITMAP,覆盖磁盘上的原始文件。 (说真的,微软,你在抽什么烟??)

您观察到的结果可以解释如下:

  • 水平环绕偏移是由于资源开头的 BITMAP 文件和信息标头引起的。
  • 由于 BGR <-> RGB 不匹配,颜色已关闭。

如果要将资源保留为 JPEG,可以通过手动编辑 rc 文件或在 Visual Studio 完成处理后还原文件来添加它。 但是,如果您选择这条路线,则必须解压缩 JPEG(因为 OpenGL 需要纯 RGB 数据而不是 JPEG)。 一种方法是在从image_data获得的LockResource stbi_load_from_memory Stbi 会将 JPEG 解压缩为 RGB(按此顺序)。

如果您想继续使用 BITMAP 资源,那么您只需跳过标题并翻转频道即可。

为了跳过标头,您解析位于image_dataBITMAPFILEHEADER 像素数据的偏移量位于标头中的bfOffBits字段中:

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

为了修复通道顺序,您可以为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