C + + TGA разбор неверный_цвет / искажение с некоторыми разрешениями

Я хотел бы получить помощь по моей проблеме с анализом формата файлов .tga. у меня есть код, который я использую в течение длительного времени:

            int fileLength = Input.tellg();
vector<char> tempData;
tempData.resize(fileLength);

Input.seekg(0);
Input.read(&tempData[0], fileLength);
Input.close();

// Load information about the tga, aka the header.
// Seek to the width.
w = byteToUnsignedShort(tempData[12], tempData[13]);

// Seek to the height.
h = byteToUnsignedShort(tempData[14], tempData[15]);

// Seek to the depth.
depth = unsigned(tempData[16]);

// Mode = components per pixel.
md = depth / 8;

// Total bytes = h * w * md.
t = h * w * md;

//Delete allocated data, if need to
clear();

//Allocate new storage
data.resize(t);

// Copy image data.
for(unsigned i = 0, s = 18; s < t + 18; s++, i++)
data[i] = unsigned char(tempData[s]);

// Mode 3 = RGB, Mode 4 = RGBA
// TGA stores RGB(A) as BGR(A) so
// we need to swap red and blue.
if(md > 2)
{
char aux;

for(unsigned i = 0; i < t; i+= md)
{
aux = data[i];
data[i] = data[i + 2];
data[i + 2] = aux;
}
}

но он иногда дает сбой для некоторых разрешений изображения (в основном, для нечетных чисел и разрешений, отличных от POT). это приводит к искаженному изображению (с диагональными образцами) или неправильным цветам. в прошлый раз, когда я столкнулся с этим — это было изображение 9×9 24bpp, показывающее странные цвета.

Я нахожусь на окнах (так что это означает, что с прямым порядком байтов), рендеринг с OpenGL (я принимаю во внимание существование альфа-канала, при передаче данных изображения с glTexImage2D). Я сохраняю свои изображения в фотошопе, не устанавливая флаг RLE. этот код всегда читает правильное разрешение изображения и глубину цвета.

пример изображения, вызывающего проблемы:
http://pastie.org/private/p81wbh5sb6coldspln6mw

после загрузки проблемного изображения этот код:

for(unsigned f = 0; f < imageData.w * imageData.h * imageData.depth; f += imageData.depth)
{
if(f % (imageData.w * imageData.depth) == 0)
writeLog << endl;

writeLog << "[" << unsigned(imageData.data[f]) << "," << unsigned(imageData.data[f + 1]) << "," << unsigned(imageData.data[f + 2]) << "]" << flush;
}

выводит это:

[37,40,40][37,40,40][37,40,40][37,40,40][37,40,40][37,40,40][37,40,40][37,40,40][37,40,40]
[37,40,40][173,166,164][93,90,88][93,90,88][93,90,88][93,90,88][93,90,88][88,85,83][37,40,40]
[37,40,40][228,221,219][221,212,209][221,212,209][221,212,209][221,212,209][221,212,209][140,134,132][37,40,40]
[37,40,40][228,221,219][221,212,209][221,212,209][221,212,209][221,212,209][221,212,209][140,134,132][37,40,40]
[37,40,40][228,221,219][221,212,209][221,212,209][221,212,209][221,212,209][221,212,209][140,134,132][37,40,40]
[37,40,40][228,221,219][221,212,209][221,212,209][221,212,209][221,212,209][221,212,209][140,134,132][37,40,40]
[37,40,40][228,221,219][221,212,209][221,212,209][221,212,209][221,212,209][221,212,209][140,134,132][37,40,40]
[37,40,40][237,232,230][235,229,228][235,229,228][235,229,228][235,229,228][235,229,228][223,214,212][37,40,40]
[37,40,40][37,40,40][37,40,40][37,40,40][37,40,40][37,40,40][37,40,40][37,40,40][37,40,40]

так что я думаю, что он читает правильные данные.
это подводит нас к opengl;

glGenTextures(1, &textureObject);
glBindTexture(GL_TEXTURE_2D, textureObject);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

GLenum in_comp_mode, comp_mode;

if(linear) //false for that image
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
else
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

//i don't use 1 or 2 - channel textures, so it's always 24 or 32bpp
if(imageData.depth == 24)
{
in_tex_mode = GL_RGB8;
tex_mode = GL_RGB;
}
else
{
in_tex_mode = GL_RGBA8;
tex_mode = GL_RGBA;
}

glTexImage2D(GL_TEXTURE_2D, 0, in_tex_mode, imageData.w, imageData.h, 0, tex_mode, GL_UNSIGNED_BYTE, &imageData.data[0]);

glBindTexture(GL_TEXTURE_2D, NULL);

Код сжатия текстур опущен, потому что он не активен для этой текстуры.

1

Решение

Вероятно, это проблема заполнения / выравнивания.

Вы загружаете TGA, у которого нет заполнения строк, но передаете его в GL, который по умолчанию ожидает, что строки пикселей будут дополнены кратным 4 байтам.

Возможные исправления для этого:

  • Расскажите GL, как упакована ваша текстура, используя (например) glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  • Измените размеры вашей текстуры, чтобы не было заполнения.
  • Измените загрузку вашей текстуры так, чтобы отступы соответствовали ожиданиям GL
3

Другие решения

большинство форматов изображений сохраняют данные изображения выровненными (обычно 4 байта).
например, разрешение: 1row 1columns
каждая строка имеет один пиксель, поэтому, если используется RGB, каждая строка имеет 3 байта.
и будет увеличен до 4 байтов для выравнивания, потому что процессор так.

английский не мой родной язык, поэтому моя плохая грамматика убьет тебя. просто попытайся понять это.

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector