PDA

Просмотр полной версии : DXT декомпрессия


Sid
24.03.2012, 13:48
В общем решил начать изучать OpenGL, но все понемногу. Решил разобраться как устроен modelviewer. Естественно, использую Qt4 и его модуль, но вопрос сейчас не по 3D графике :)

Не могу прочитать BLP %)
Точней могу, но не понимаю как правильно оперировать с данными.

Использую squish библиотеку для декомпрессии изображения, но наверное делаю что-то не так. Никак не получается вывести картинку - вместо нее набор цветопикселей :)

Вот код (может кому-то он ничего не скажет, но суть, я думаю, поймете)

QPixmap Texture::getImage()
{
int mipmax = m_header.hasMips ? 16 : 1;

QDataStream stream(m_buffer);
stream.setByteOrder(QDataStream::LittleEndian);

QVector<quint8> data;
quint8 d = 0;

for (quint8 i = 0; i < mipmax; i++)
{
stream.skipRawData(m_header.offsets[i]);
for (quint32 j = 0; j < m_header.lengths[i]; j++)
{
stream >> d;
data << d;
}
}

QVector<quint8> v;
v.resize(m_header.width * m_header.height * 16 * 4);
squish::DecompressImage(&v[0], m_header.width, m_header.height, data.data(), m_header.encoding);

QImage img(v.data(), m_header.width, m_header.height, QImage::Format::Format_ARGB32);

return QPixmap::fromImage(img);
}

Смотрел как в modelviewer считывается BLP, но там декомпрессия через opengl происходит, и этих методов нет в модуле Qt. Поэтому использовал библиотеку. Вопрос - правилен этот код хоть на пару процентов?))

PS WMV 0.4 http://wowmv.svn.sourceforge.net/viewvc/wowmv/src/
WMV Latest http://code.google.com/p/wowmodelviewer/source/browse/
SQUISH http://code.google.com/p/libsquish/

zergtmn
24.03.2012, 18:47
А зачем его разжимать? DXT это "железный" формат.

Sid
24.03.2012, 18:50
Compression: 1 for uncompressed, 2 for DXTC, 3 (cataclysm) for plain A8R8G8B8 textures (see remarks)

Вроде как надо разжимать)у меня 2.

Evgeniy
25.03.2012, 00:26
http://www.ownedcore.com/forums/world-of-warcraft/world-of-warcraft-bots-programs/wow-memory-editing/289905-drawing-maps-blp-images.html

Sid
25.03.2012, 09:02
Вот уже что-то)

QPixmap Texture::getImage()
{
QDataStream stream(m_buffer);
stream.setByteOrder(QDataStream::LittleEndian);

QVector<quint8> data;
quint8 d = 0;

stream.skipRawData(m_header.offsets[0]);
for (quint32 j = 0; j < m_header.lengths[0]; j++)
{
stream >> d;
data << d;
}

squish::u8* uncompressed;
if (m_header.encoding == 2)
{
int dxtver;
switch (m_header.alphaEncoding)
{
case 0: dxtver = squish::kDxt1; break;
case 1: dxtver = squish::kDxt3; break;
case 7: dxtver = squish::kDxt5; break;
//default: std::cout << "DXT version not recognized.\n"; return false; break;
}
uncompressed = new squish::u8[m_header.width * m_header.height * 4];
squish::DecompressImage(uncompressed, m_header.width, m_header.height, data.data(), dxtver);
}
else
uncompressed = data.data();

QVector<QRgb> colors;
for (quint32 i = 0; i < 256; i++)
{
colors.append(qRgba(m_header.colors[i].r,
m_header.colors[i].g,
m_header.colors[i].b,
m_header.colors[i].a));
}

QImage img(uncompressed, m_header.width, m_header.height, QImage::Format::Format_Indexed8);

return QPixmap::fromImage(img);
}

Правда цветовая палитра не накладывается...
http://my.jetscreenshot.com/4271/20120325-hutr-66kb.jpg

Делал setColorTable и заполнял ее из ARGB[256] куска после данных, тогда картинка вообще белая -_-

Evgeniy
25.03.2012, 09:27
палитра находится сразу за mipmapSize блоками

Sid
25.03.2012, 09:44
Ну я с нее и заполнял.

zergtmn
25.03.2012, 11:18
Первый намек видимо был не понят.

http://www.opengl.org/registry/specs/EXT/texture_compression_s3tc.txt
glCompressedTexImage2D
GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
GL_COMPRESSED_RGBA_S3TC_DXT5_EXT

Sid
25.03.2012, 12:00
Уже разобрался, я так понял что в дате указан номер цвета из палитры. Прогоняю 256х256 цикл, но не получаю нужного)) Код взял из модельвивера. Получается такая фигня.

http://my.jetscreenshot.com/4271/20120325-gyd8-106kb

QPixmap Texture::getImage()
{
QDataStream stream(m_buffer);
stream.setByteOrder(QDataStream::LittleEndian);

QVector<quint8> data;
quint8 d = 0;

stream.skipRawData(m_header.offsets[0]);
for (quint32 j = 0; j < m_header.lengths[0]; j++)
{
stream >> d;
data << d;
}

squish::u8* uncompressed;
if (m_header.encoding == 2)
{
int dxtver;
switch (m_header.alphaEncoding)
{
case 0: dxtver = squish::kDxt1; break;
case 1: dxtver = squish::kDxt3; break;
case 7: dxtver = squish::kDxt5; break;
//default: std::cout << "DXT version not recognized.\n"; return false; break;
}
uncompressed = new squish::u8[m_header.width * m_header.height * 4];
squish::DecompressImage(uncompressed, m_header.width, m_header.height, data.data(), dxtver);
}
else
uncompressed = data.data();

// Заполнение цветов
quint32* p = new quint32[m_header.width * m_header.height];
quint8* c = uncompressed;

for (quint32 y = 0; y < m_header.height; y++)
{
for (quint32 x = 0; x < m_header.width; x++)
{
//ARGBColor8 k = m_header.colors[*c++];

quint32 k = m_header.colors[*c++];

k = ((k&0x00FF0000)>>16) | ((k&0x0000FF00)) | ((k& 0x000000FF)<<16);
k |= 255 << 24;
*p++ = k;//qRgba(k.r, k.g, k.b, 255);
}
}

uncompressed = reinterpret_cast<quint8*>(p);
QImage img(uncompressed, m_header.width, m_header.height, QImage::Format::Format_ARGB32);

return QPixmap::fromImage(img);
}
PS если убрать все эти манипуляции с uint32 и сделать мой вариант через стурктуру и преобразовение в rgba от qt то тоже самое.

for (quint32 x = 0; x < m_header.width; x++)
{
ARGBColor8 k = m_header.colors[*c++];
*p++ = qRgba(k.r, k.g, k.b, 255);
}

Sid
25.03.2012, 12:30
Тема превратилась в "как прочитать BLP" :)

Sid
25.03.2012, 13:24
Все! Я это сделал) Осенило что картинка была белой после того как я устанавливал палитру, значит альфа была нулевая. Установил палитру так же, только альфу в ней сделал 255 и все четко :)

http://my.jetscreenshot.com/4271/20120325-jjrz-70kb