DDS файл
Автор
Dr. No
, Mar 15 2013 15:58
Сообщений в теме: 3
#1
Отправлено 15 March 2013 - 15:58
Всем привет. Появился такой вопрос... нужно получить полный размер dds, если в доступе есть только заголовок. Например, у нас есть архив с игры без сжатия. Нам нужно вытащить все dds'ки, которые там есть. Причем там могут быть разные dds (DXT1/3/5, ATI1, RAW и пр...) Ищем заголовок dds, получаем о нем всю инфу.. а дальше как? Как получить размер dds, чтобы можно было его проскочить и искать дальше, предварительно куда то его записав?
P.S. риперы и пр. софт не предлагать - нужна именно программная реализация( c++ or delphi).
P.S. риперы и пр. софт не предлагать - нужна именно программная реализация( c++ or delphi).
#2
Отправлено 15 March 2013 - 18:17
Вообще-то, в MSDN есть описание формата, где даже объясняется как размер файла посчитать.
В заголовке .DDS, увы, нет его размера, как это сделано у .BMP.
В заголовке .DDS, увы, нет его размера, как это сделано у .BMP.
#3
Отправлено 15 March 2013 - 19:46
-=CHE@TER=-
Видел я описания формата. Да и я вообще весь инет перерыл, нигде нет подобного ) Я понимаю, что в заголовке нет размера dds, но проги типа Nova Extractor, MultiExtractor (в HyperRipper фиговый поиск dds'ок, детектить не все форматы dds) как то же получают размер. Насколько я понял, там нужно width * количество цветов .. и еще что то. Вот я понятия не имею, что дальше...
Хм.. в общем, попытался что то реализовать на дельфях ) Вот что получилось:
вроде получает правильный размер dds'ки. Но в чем прикол, когда я подкладываю ему другую dds (DXT1 к примеру), размер считается не правильно. Как быть?
Видел я описания формата. Да и я вообще весь инет перерыл, нигде нет подобного ) Я понимаю, что в заголовке нет размера dds, но проги типа Nova Extractor, MultiExtractor (в HyperRipper фиговый поиск dds'ок, детектить не все форматы dds) как то же получают размер. Насколько я понял, там нужно width * количество цветов .. и еще что то. Вот я понятия не имею, что дальше...
Хм.. в общем, попытался что то реализовать на дельфях ) Вот что получилось:
program dds; uses Windows, SysUtils, FastCode, DDSCommon, Math; {$APPTYPE CONSOLE} var hFile, Readed: THandle; DDSH: DDSHeader; CurH, MinSize: Longword; x: Integer; Size: Int64; begin hFile:= CreateFile(PAnsiChar('1.dds'), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0); ReadFile(hFile, DDSH, SizeOf(DDSH), Readed, nil); Size:= SizeOf(DDSHeader)+DDSH.SurfaceDesc.dwPitchOrLinearSize; CurH := DDSH.SurfaceDesc.dwPitchOrLinearSize; for x := 1 to DDSH.SurfaceDesc.dwMipMapCount-1 do begin CurH := CurH div 4; Inc(Size, Max(0 {minsize}, CurH)); end; Writeln(Size); CloseHandle(hFile); end.
вроде получает правильный размер dds'ки. Но в чем прикол, когда я подкладываю ему другую dds (DXT1 к примеру), размер считается не правильно. Как быть?
#4
Отправлено 17 March 2013 - 22:00
Внимательно статью перечитай (выделение жирным - моё):
Там прямым текстом написано, что на это поле полагаться нельзя и нужно вручную высчитывать в зависимости от цветового пространства и метода сжатия размер (что в списке и указано - для какого типа как считать).The D3DX library (for example, D3DX11.lib) and other similar libraries unreliably or inconsistently provide the pitch value in the dwPitchOrLinearSize member of the DDS_HEADER structure. Therefore, when you read and write to DDS files, we recommend that you compute the pitch in one of the following ways for the indicated formats:
- For block-compressed formats, compute the pitch as:
max( 1, ((width+3)/4) ) * block-size
The block-size is 8 bytes for DXT1, BC1, and BC4 formats, and 16 bytes for other block-compressed formats.
- For R8G8_B8G8, G8R8_G8B8, legacy UYVY-packed, and legacy YUY2-packed formats, compute the pitch as:
((width+1) >> 1) * 4
- For other formats, compute the pitch as:
( width * bits-per-pixel + 7 ) / 8
You divide by 8 for byte alignment.
Note The pitch value that you calculate does not always equal the pitch that the runtime supplies, which is DWORD-aligned in some situations and byte-aligned in other situations. Therefore, we recommend that you copy a scan line at a time rather than try to copy the whole image in one copy.