Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Мультимедиа в Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 02.11.2015, 00:13   #1
IvaniuS
Форумчанин
 
Аватар для IvaniuS
 
Регистрация: 16.04.2007
Сообщений: 225
По умолчанию Распаковка DDS DXT1 в BMP

Доброго времени суток, собственно задача ясна - распаковать и перезаписать из DDS DXT1 в BMP, документации достаточно, а вот готовых алгоритмов без использования видео ресурсов (OGL) мало.
Вот что получилось накопать + переписать
Собственно вот где проблема:
Код:
//Распаковка DXT1 текстуры в BMP
procedure DecodeDXT (const Texture:TGETexture; var Buf:TMemoryStream; ctype:byte);
var
    i,j,k,n : integer;
        pix : byte;
      Color : array [0..3] of TRGB;
begin
  Buf.SetSize(BMP_FILE_SIZE);
  Buf.Position:=0;
  Buf.Write(BMP_HEAD, Length(BMP_HEAD));                                        //пишем заголовок BMP
  for i := 0 to length(Texture.DXT1)-1 do
  for j := 0 to length(Texture.DXT1[0])-1 do
  begin
    GetColors(Texture.DXT1[i,j].Color0, Texture.DXT1[i,j].Color1, Color);       //определяем опорные цвета для блока
    pix:=0;
    for k := 0 to 3 do
    for n := 0 to 3 do
    begin
      case ctype of
        0:begin  
          if j>=12 then Buf.Position:=54+((4*i+k)*256+4*(j-12)+n)*3 else
          if i>=1 then Buf.Position:=54+((4*(i-1)+k)*256+4*(j+52)+n)*3
          else Buf.Position:=54+((4*(i+63)+k)*256+4*(j)+n)*3;
        end;
        else Buf.Position:=54+((4*i+k)*256+4*j+n)*3;
      end;
     Buf.Write(Color[GetColorID(Texture.DXT1[i,j].BitMask, pix)], 3);           //для каждого пикселя из блока, записываем его реальный цвет
     inc(pix);
    end;
  end;
end;
Под нулем - это то что я переписал, на сколько смог, к сожалению я не понимаю как хранится BitMap в памяти и формула немного ошибочна.
Ошибка заключается в том что примерно 1\8 переносится с конца файла, в его начало т.е. изображение искажено.
Если кто сталкивался с подобным или есть где-то уже компонент\код и я зря все это пишу - прошу тыкнуть носом. Спасибо.
IvaniuS вне форума Ответить с цитированием
Старый 16.12.2015, 14:44   #2
xrob
Форумчанин
 
Регистрация: 18.10.2010
Сообщений: 419
По умолчанию

IvaniuS, не могли бы вы более конкретно описать суть проблемы?
Что значит 1/8 (какой исходный размер текстуры?)
Что в вашем понимании "конец файла" и "начало файла"?
Каким образом искажено изображение? (скрин результата)
xrob вне форума Ответить с цитированием
Старый 16.12.2015, 18:34   #3
IvaniuS
Форумчанин
 
Аватар для IvaniuS
 
Регистрация: 16.04.2007
Сообщений: 225
По умолчанию

Спасибо за ответ. Нашел хороший исходник на С++, но к сожалению с его перевести пока не удалось.
Примеры:
Оригинал
При при ctype<>0
Это "улучшеный мною алгоритм при ctype=0"

Код С, во вложении весь код:
Код:
void DDS_DecodeCompressedImage( byte* dest, byte* src, const int width, const int height, const int format )
{
    int sx = ( width  < 4 ) ? width  : 4;
    int sy = ( height < 4 ) ? height : 4;
 
    int nChannels = fEngine::image::GetChannelCount( (_Texture_Format)format );
    for ( int y = 0; y < height; y += 4 )
    {
        for ( int x = 0; x < width; x += 4 )
        {
            byte *dst = dest + ( y * width + x ) * nChannels;
            DDS_DecodeColorBlock( dst, sx, sy, nChannels, width * nChannels, format, src );
            src += 8;
        }   
    }
}
// Decodes a DXT color block
void DDS_DecodeColorBlock( byte* dest, const int w, const int h, const int xOff, const int yOff, const int format, byte* src )
{
    byte colors[4][3];
 
    word c0 = *(word*)src;
    word c1 = *(word*)(src + 2);
 
    // Extract the two stored colors
    colors[0][0] = ((c0 >> 11) & 0x1F) << 3;
    colors[0][1] = ((c0 >>  5) & 0x3F) << 2;
    colors[0][2] =  (c0        & 0x1F) << 3;
   
    colors[1][0] = ((c1 >> 11) & 0x1F) << 3;
    colors[1][1] = ((c1 >>  5) & 0x3F) << 2;
    colors[1][2] =  (c1        & 0x1F) << 3;
 
    register int i, x, y;
 
    // Compute the other two colors
    if ( c0 > c1 )
    {
        for ( i = 0; i < 3; i++ )
        {
            colors[2][i] = ( 2 * colors[0][i] +     colors[1][i] + 1 ) / 3;
            colors[3][i] = (     colors[0][i] + 2 * colors[1][i] + 1 ) / 3;
        }
    }
    else
    {
        for ( i = 0; i < 3; i++ )
        {
            colors[2][i] = ( colors[0][i] + colors[1][i] + 1 ) >> 1;
            colors[3][i] = 0;
        }
    }
 
    src += 4;
    for ( y = 0; y < h; y++ )
    {
        byte* dst     = dest + yOff * y;
        dword indexes = src[ y ];
        for ( x = 0; x < w; x++ )
        {
            dword index = indexes & 0x3;
            dst[0]      = colors[index][0];
            dst[1]      = colors[index][1];
            dst[2]      = colors[index][2];
            indexes   >>= 2;
 
            dst += xOff;
        }
    }
}
Вот то что перевел, оно работает идеально:
Код:
//Определение опорных цветов
procedure GetColors (Color0,Color1:word; var Colors24bit: array of TRGB);
  function RGB565_To_RGB888(Input:Word):TRGB; inline;
  begin
   result.R :=((Input shr 11) and $1F) shl 3;
   result.G :=((Input shr 5 ) and $3F) shl 2;
   result.B := (Input         and $1F) shl 3;
  end;


begin
   Colors24bit[0]:= RGB565_To_RGB888(Color0);
   Colors24bit[1]:= RGB565_To_RGB888(Color1);
   if Color0 > Color1 then begin
     Colors24bit[2].R:= (2*Colors24bit[0].R+Colors24bit[1].R+1) div 3;
     Colors24bit[2].G:= (2*Colors24bit[0].G+Colors24bit[1].G+1) div 3;
     Colors24bit[2].B:= (2*Colors24bit[0].B+Colors24bit[1].B+1) div 3;

     Colors24bit[3].R:= (Colors24bit[0].R+2*Colors24bit[1].R+1) div 3;
     Colors24bit[3].G:= (Colors24bit[0].G+2*Colors24bit[1].G+1) div 3;
     Colors24bit[3].B:= (Colors24bit[0].B+2*Colors24bit[1].B+1) div 3;
   end else begin
     Colors24bit[2].R:= (Colors24bit[0].R+Colors24bit[1].R+1) shr 1;
     Colors24bit[2].G:= (Colors24bit[0].G+Colors24bit[1].G+1) shr 1;
     Colors24bit[2].B:= (Colors24bit[0].B+Colors24bit[1].B+1) shr 1;
     Colors24bit[3].R := 0;
     Colors24bit[3].G := 0;
     Colors24bit[3].B := 0;
   end;
end;
Вложения
Тип файла: zip DDSDECODE.zip (4.9 Кб, 27 просмотров)

Последний раз редактировалось IvaniuS; 16.12.2015 в 18:39.
IvaniuS вне форума Ответить с цитированием
Старый 10.01.2016, 01:00   #4
IvaniuS
Форумчанин
 
Аватар для IvaniuS
 
Регистрация: 16.04.2007
Сообщений: 225
По умолчанию

Как оказалось алгоритм вообще не универсальный)
Сейчас подсунув ему изображение 128*64, а не 256*64 изображение, на выходе получил пропуски как в черезстрочкной развертке в результате.
На делфи нету ничего подобного для конвертирования или считывания dds DXT1 файлов(
Оказывается все на много проще, подключаешь кусочки от GLScene (я еще 2009 с ней работал) и все отлично работает никаких проблем.

Последний раз редактировалось IvaniuS; 10.01.2016 в 02:50.
IvaniuS вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
load dds to BitMap Coldater C# (си шарп) 0 24.12.2013 16:23
Как получить размер dds-файла? RibGeDx Общие вопросы Delphi 8 16.03.2013 20:56
ImageMagick и формат DDS J-Max PHP 1 26.08.2012 14:01
Как открыть dds-изображения HellMercenariess Мультимедиа в Delphi 1 24.07.2012 12:44
Как отобразить в окне DDS изображение crymchanin Общие вопросы C/C++ 0 15.02.2012 17:53