[英]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.