[英]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,覆盖磁盘上的原始文件。 (说真的,微软,你在抽什么烟??)
您观察到的结果可以解释如下:
如果要将资源保留为 JPEG,可以通过手动编辑 rc 文件或在 Visual Studio 完成处理后还原文件来添加它。 但是,如果您选择这条路线,则必须解压缩 JPEG(因为 OpenGL 需要纯 RGB 数据而不是 JPEG)。 一种方法是在从image_data
获得的LockResource
stbi_load_from_memory
Stbi 会将 JPEG 解压缩为 RGB(按此顺序)。
如果您想继续使用 BITMAP 资源,那么您只需跳过标题并翻转频道即可。
为了跳过标头,您解析位于image_data
的BITMAPFILEHEADER
。 像素数据的偏移量位于标头中的bfOffBits
字段中:
actual_image_data = (char*)image_data + ((BITMAPFILEHEADER*)image_data)->bfOffBits;
为了修复通道顺序,您可以为glTexImage2D
的format
参数(不是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.