2012-04-20 222 views
0

我已经在下面回答了我的问题。感谢gavinb的帮助。将Uint8转换为无符号字符的RGB值

问题: 我试图复制纹理只是为了学习体验。我使用24位TGA图像,并使用SDL加载它。我已经创建了自己的结构

struct Colour24 
{ 
    unsigned char r; 
    unsigned char g; 
    unsigned char b; 
} 

unsigned char* texture = new unsigned char[width * height * 3]; 

    for (int y = 0; y < height; y++) 
    { 
     for (int x = 0; x < width; x++) 
     { 
      int index = (y * width) + x; 

      Colour24 colour = getColourAt(x, y); 

      newTexture[index] = colour.r; 
      newTexture[index + 1] = colour.g; 
      newTexture[index + 2] = colour.b; 
     } 
    } 

Colour24 getColour(int x, int y) 
{ 
    Uint32 pixel; 
    Uint8 red, green, blue; 
    Colour24 rgb; 

    pixel = getPixel(m_surface, x, y); // using the SDL get pixel function 

    SDL_GetRGB(pixel, m_surface->format, &red, &green, &blue); 

    rgb.r = red; 
    rgb.b = blue; 
    rgb.g = green; 

    return rgb; 
} 

OLD: 我打算发送到一个OpenGL纹理这个和它的工作时,我直接将表面 - >像素。但我想自己创建数据数组。非常感谢帮助!

编辑:对不起,我没有解释得很好。我试图从包含24位TGA图像的SDL_Surface中手动重新创建纹理,然后我将它交给opengl来创建纹理。我已经用surface-> pixels测试了我的opengl代码,它工作正常。我只是试图找出我在哪里加载错误。

+0

究竟是什么问题?编译器错误?不符合你的期望?至少你的代码是不完整的,因为它包含与函数定义相同级别的代码。 – bjhend 2012-04-20 10:40:09

+0

我可以将这个纹理加载到opengl中,但它不正确。我得到了很多红色,绿色和蓝色的交叉孵化发生。 – rocklobster 2012-04-20 10:48:12

回答

1

结束写我自己的TGA加载程序,然后发现我需要乘以每像素字节的高度。仍然不是100%确定为什么(随意评论),但它现在起作用。

代码:

TGAReader* reader = new TGAReader(); 
reader->readSurface("MyTexture.tga"); 

int height = reader->height; 
int width = reader->width; 
int bpp = reader->bpp; 

unsigned char* texture = new unsigned char[width * height * bpp]; 

for (int y = 0; y < height * bpp; y++) 
{ 
    for (int x = 0; x < width; x += 3) 
    { 
     int index = (y * width) + x; 

     Colour24 colour = reader->getColourAt(x, y); 

     newTexture[index] = colour.r; 
     newTexture[index + 1] = colour.g; 
     newTexture[index + 2] = colour.b; 
    } 
} 
// create OpenGL texture 
unsigned int = createTextureFromData(newTexture, width, height, bpp); 

// reading tga data 
Colour24 TGAReader::getColourAt(int x, int y) 
{ 
    Colour24 rgb; 

    rgb.r = m_data[((y * width) + x)]; 
    rgb.g = m_data[((y * width) + x) + 1]; 
    rgb.b = m_data[((y * width) + x) + 2]; 

    return rgb; 
} 
0

Uint8的大小取决于其声明。另一方面,在C++标准中,unsigned char的大小也没有被指定为8位,尽管它在许多平台上都是8位。

最好在您的Colour24中直接使用Uint8以避免转换错误。

+0

谢谢,我现在就试试。 – rocklobster 2012-04-20 10:48:21

+0

编辑:只是检查。 Uint8是uint8_t的typedef,这是一个unsigned char的typedef ... – rocklobster 2012-04-20 10:51:11

2

unsigned char几乎可以肯定相当于uint8_t,除非你使用了一些令人难以置信的深奥的架构。

但是在代码中存在一些问题,尽管目前还不清楚你想要做什么或者问题是什么。

首先,您在调用getColourAt()时转置了x,y坐标。您正在使用我索引的高度和j索引的宽度,所以你应该使用J,I这样的:

Colour24 colour = getColourAt(j, i); 

也许这将是简单的坚持与X,Y命名。

其次,索引到纹理缓冲区是错误的。它应该是:

texture[i*width+j+0] = colour.red; 
texture[i*width+j+1] = colour.green; 
texture[i*width+j+2] = colour.blue; 

,因为你将有width字节i完整行,并在不完全排j字节。

此外,您正在丢失SDL_GetRGB调用中的像素格式,所以这甚至不会编译。

最后,您的getColour()函数将无法正常工作;它总是会返回0,0像素的值,因为您没有通过x,y偏移到图像中。您可以使用与上述相同的技术。只要注意索引,就好像您使用的是带有SDL的UInt32,这意味着RGBA(32位)像素格式,但是您使用的是RGB(24位)。

+0

现在测试一下。为了清晰起见,我还编辑了原始文章。 – rocklobster 2012-04-20 10:54:03

+0

好吧,我已经使用新代码更新了原始帖子。我有不同的结果,但仍然是奇怪的。 – rocklobster 2012-04-20 11:01:46

+1

将y值索引乘以纹理缓冲区时,仍然需要使用宽度而不是高度。另外,由于像素是UInt32,因此您会陷入上述陷阱中,将缓冲区视为32bpp而不是24bpp。查看http://www.libsdl.org/cgi/docwiki.cgi/Introduction_to_SDL_Video#getpixel,了解适用于所有像素格式的完整解决方案。 – gavinb 2012-04-20 11:08:51

相关问题