簡體   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