简体   繁体   English

Open GL - 为什么 ABGR 中的像素值以及如何在 RGBA 中使用它们

[英]Open GL - Why are Pixel values in ABGR and how to use them in RGBA

I have some code for loading textures where I'm using DevIL to load the images and then OpenGL creates a texture from the pixels.我有一些加载纹理的代码,我使用 DevIL 加载图像,然后 OpenGL 从像素创建纹理。 This code works fine and the texture shows up properly and that's all fine.这段代码工作正常,纹理正确显示,这一切都很好。

Besides that I can also make an array from within the program to create the texture or make changes in the texture's pixels directly.除此之外,我还可以在程序中创建一个数组来创建纹理或直接更改纹理的像素。 My problem is here: when handling the pixels their format seems to be ABGR rather than RGBA as I would have liked.我的问题在这里:在处理像素时,它们的格式似乎是 ABGR 而不是我希望的 RGBA。

I stumbled upon this SO question that refers to the format that's passed in the glTexImage2D function:我偶然发现了这个 SO 问题,它指的是 glTexImage2D 函数中传递的格式:

(...) If you have GL_RGBA and GL_UNSIGNED_INT_8_8_8_8, that means that pixels are stored in 32-bit integers, and the colors are in the logical order RGBA in such an integer, eg the red is in the high-order byte and the alpha is in the low-order byte. (...) 如果您有 GL_RGBA 和 GL_UNSIGNED_INT_8_8_8_8,这意味着像素存储在 32 位整数中,并且颜色在这样的整数中按照逻辑顺序 RGBA,例如红色在高位字节中,而alpha 在低位字节中。 But if the machine is little-endian (as with Intel CPUs), it follows that the actual order in memory is ABGR.但是如果机器是 little-endian(如 Intel CPU),那么内存中的实际顺序是 ABGR。 Whereas, GL_RGBA with GL_UNSIGNED_BYTE will store the bytes in RGBA order regardless whether the computer is little-endian or big-endian.而 GL_RGBA 和 GL_UNSIGNED_BYTE 将以 RGBA 顺序存储字节,无论计算机是小端还是大端。 (...) (...)

Indeed I have an Intel CPU.事实上,我有一个英特尔 CPU。 The images are loaded just fine the way things are right now and I actually use the GL_RGBA mode and GL_UNSIGNED_BYTE type.图像以现在的方式加载得很好,我实际上使用 GL_RGBA 模式和 GL_UNSIGNED_BYTE 类型。

GLuint makeTexture( const GLuint* pixels, GLuint width, GLuint height ) {

    GLuint texture = 0;

    glGenTextures( 1, &texture );

    glBindTexture( GL_TEXTURE_2D, texture );

    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels );

    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );

    glBindTexture( GL_TEXTURE_2D, NULL );

    GLenum error = glGetError();
    if ( error != GL_NO_ERROR ) {
        return 0;
    }

    return texture;
}

This function is used in my two methods for loading textures, the method that loads an image from a file and the one that creates a texture from an array.这个函数用在我的两种加载纹理的方法中,一种是从文件加载图像的方法,另一种是从数组创建纹理的方法。

Let's say that I want to create an array of pixels and create a texture,假设我想创建一个像素数组并创建一个纹理,

GLuint pixels[ 128 * 128 ];
for ( int i = 0; i < 128 * 128; ++i ) {
    pixels[ i ] = 0x800000FF;
}
texture.loadImageArray( pixels, 128, 128 );

By padding the pixels with this value I would expect to see a slightly dark red color.通过用这个值填充像素,我希望看到稍微深红色的颜色。

red = 0x80, green = 0x00, blue = 0x00, alpha = 0xFF

But instead I get a transparent red,但相反,我得到一个透明的红色,

alpha = 0x80, blue = 0x00, green = 0x00, red = 0xFF

Rather than using raw unsigned ints I made a structure to help me handling individual channels:我没有使用原始无符号整数,而是创建了一个结构来帮助我处理单个通道:

struct Color4C {
    unsigned char alpha;
    unsigned char blue;
    unsigned char green;
    unsigned char red;
    ...
};

I can easily replace an array of unsigned ints with an array of Color4C and the result is the same.我可以很容易地用 Color4C 数组替换一个无符号整数数组,结果是一样的。 If I invert the order of the channels (red first, alpha last) then I can easily pass 0xRRGGBBAA and make it work.如果我反转通道的顺序(首先是红色,最后是 alpha),那么我可以轻松地传递 0xRRGGBBAA 并使其工作。

The easy solution is to simply handle these values in ABGR format.简单的解决方案是以 ABGR 格式简单地处理这些值。 But I also find it easier to work with RGBA values.但我也发现使用 RGBA 值更容易。 If I want to use hardcoded color values I would prefer to write them like 0xRRGGBBAA and not 0xAABBGGRR.如果我想使用硬编码的颜色值,我更愿意将它们写成 0xRRGGBBAA 而不是 0xAABBGGRR。

But let's say I start using the ABGR format.但是假设我开始使用 ABGR 格式。 If I were to run my code in another machine, would I suddenly see strange colors wherever I changed pixels/channels directly?如果我要在另一台机器上运行我的代码,我会在直接更改像素/通道的地方突然看到奇怪的颜色吗? Is there a better solution?有更好的解决方案吗?

Promoting some helpful comments to an answer:对答案提出一些有用的评论:

0xRR,0xGG,0xBB,0xAA on your (Intel, little-endian) machine is 0xAABBGGRR .您(英特尔,小端)机器上的0xRR,0xGG,0xBB,0xAA0xAABBGGRR You've already found the information saying that GL_UNSIGNED_BYTE preserves the format of binary blocks of data across machines, while GL_UNSIGNED_INT_8_8_8_8 preserves the format of literals like 0xRRGGBBAA .您已经找到信息说 GL_UNSIGNED_BYTE 保留跨机器数据的二进制块格式,而GL_UNSIGNED_INT_8_8_8_8保留像0xRRGGBBAA这样的文字格式。 Because different machines have different correspondence between binary and literals, it is absolutely impossible for you to have both types of portability at once.因为不同的机器对二进制和字面量有不同的对应关系,所以你绝对不可能同时拥有两种类型的可移植性。 – Ben Voigt ——本·沃伊特

[Writing 0xAABBGGRR would actually be RGBA in your machine, but running this code in another machine could show different results] because OpenGL will reinterpret it as UNSIGNED_BYTE . [在您的机器上写入0xAABBGGRR实际上是 RGBA,但在另一台机器上运行此代码可能会显示不同的结果] 因为 OpenGL 会将其重新解释为UNSIGNED_BYTE C++ needs an endianess library, after all.毕竟,C++ 需要一个字节顺序库。 – WorldSEnder – WorldSENDer

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

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