2012-04-20 2 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 текстуры и он работает, когда я непосредственно отправить поверхностно> пикселей. Но я хотел бы создать массив данных самостоятельно. Помощь очень ценится!

EDIT: Извините, я не очень хорошо себя объяснил. Я пытаюсь вручную воссоздать текстуру с SDL_Surface, который содержит 24-битное изображение TGA, и я дам ему opengl для создания текстуры. Я тестировал код opengl с поверхностными пикселями, и он отлично работает. Я просто пытаюсь решить, где я ошибся, загрузив его.

+0

Что проблема именно?Ошибка компилятора? Не делает то, что вы ожидаете? По крайней мере, ваш код является неполным, так как он содержит код на одном уровне определения функции. – bjhend

+0

Я могу загрузить эту текстуру в opengl, но это неверно. Я получаю много красных, зеленых и синих перекрестных штрихов. – rocklobster

ответ

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 зависит от его декларации. С другой стороны, размер unsigned char также не указан ровно в 8 бит в стандарте C++, хотя он 8 бит на многих платформах.

Лучше использовать Uint8 непосредственно в вашем Colour24, чтобы избежать ошибок при преобразовании.

+0

Спасибо, я попробую это прямо сейчас. – rocklobster

+0

EDIT: только что проверено. Uint8 является typedef из uint8_t, и это typedef unsigned char ... – rocklobster

2

unsigned char почти наверняка эквивалентен uint8_t, если вы не используете какую-то невероятно эзотерическую архитектуру.

Но в коде есть несколько проблем, хотя неясно, что именно вы пытаетесь сделать или в чем проблема.

Во-первых, вы перенести координаты x, y при вызове getColourAt(). Вы используете I индексировать высоту и J индексировать ширину, так что вы должны использовать J, I, таким образом:

Colour24 colour = getColourAt(j, i); 

Возможно, было бы проще придерживаться х, у наименования.

Во-вторых, индексирование в буфер текстуры неверно. Оно должно быть:

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

, так как вы будете иметь i полные ряды width байтов и j байт на неполной строке.

Кроме того, вам не хватает формата пикселя в вызове SDL_GetRGB, поэтому это даже не компилируется.

И, наконец, ваша функция getColour() будет работать неправильно; он всегда будет возвращать значение пикселя в 0,0, поскольку вы не смещаете изображение на x, y. Для этого вы можете использовать тот же метод, что и выше. Просто будьте осторожны с индексированием, как если бы вы использовали UInt32 с SDL, который подразумевал бы формат RGBA (32-разрядный) пикселей, но вы используете RGB (24-бит).

+0

Тестирование этого сейчас. Я также редактировал свое оригинальное сообщение для ясности. – rocklobster

+0

Хорошо, я обновил свое оригинальное сообщение с новым кодом, который я использую. У меня разные результаты, но все же странные. – rocklobster

+1

Вам необходимо использовать ширину, а не высоту, при умножении на индексирование значения y в буфер текстуры. Кроме того, поскольку пиксель является UInt32, вы попадаете в ловушку, упомянутую выше, где вы обрабатываете буфер как 32bpp, а не 24bpp. Посмотрите http://www.libsdl.org/cgi/docwiki.cgi/Introduction_to_SDL_Video#getpixel для полного решения, которое должно работать со всеми форматами пикселей. – gavinb

Смежные вопросы