Приветствую уважаемых форумчан. Декодирую DDS изображение:
| Код | procedure DecodeDXT1toBitmap32(encData, decData: PByteArray; w, h: Integer; var trans: Boolean); var x, y, i, j, k, select: Integer; col0, col1: Word; colors: array [0..3] of array [0..3] of Byte; bitmask: Cardinal; temp: PByte; r0, g0, b0, r1, g1, b1: Byte; begin trans := False; if not (Assigned(encData) and Assigned(decData)) then exit; temp := PByte(encData); for y := 0 to (h div 4) - 1 do begin for x := 0 to (w div 4) - 1 do begin col0 := PWord(temp) ^; Inc(temp, 2); col1 := PWord(temp) ^; Inc(temp, 2); bitmask := PCardinal(temp) ^; Inc(temp, 4); DecodeColor(col0, r0, g0, b0); DecodeColor(col1, r1, g1, b1); colors[0][0] := r0 shl 3; colors[0][1] := g0 shl 2; colors[0][2] := b0 shl 3; colors[0][3] := $FF; colors[1][0] := r1 shl 3; colors[1][1] := g1 shl 2; colors[1][2] := b1 shl 3; colors[1][3] := $FF; if col0 > col1 then begin colors[2][0] := (2 * colors[0][0] + colors[1][0] + 1) div 3; colors[2][1] := (2 * colors[0][1] + colors[1][1] + 1) div 3; colors[2][2] := (2 * colors[0][2] + colors[1][2] + 1) div 3; colors[2][3] := $FF; colors[3][0] := (colors[0][0] + 2 * colors[1][0] + 1) div 3; colors[3][1] := (colors[0][1] + 2 * colors[1][1] + 1) div 3; colors[3][2] := (colors[0][2] + 2 * colors[1][2] + 1) div 3; colors[3][3] := $FF; end else begin trans := True; colors[2][0] := (colors[0][0] + colors[1][0]) div 2; colors[2][1] := (colors[0][1] + colors[1][1]) div 2; colors[2][2] := (colors[0][2] + colors[1][2]) div 2; colors[2][3] := $FF; colors[3][0] := (colors[0][0] + 2 * colors[1][0] + 1) div 3; colors[3][1] := (colors[0][1] + 2 * colors[1][1] + 1) div 3; colors[3][2] := (colors[0][2] + 2 * colors[1][2] + 1) div 3; colors[3][3] := 0; end; k := 0; for j := 0 to 3 do begin for i := 0 to 3 do begin select := (bitmask and (3 shl (k * 2))) shr (k * 2); if ((4 * x + i) < w) and ((4 * y + j) < h) then PCardinal(@ decData[((4 * y + j) * w + (4 * x + i)) * 4]) ^ := Cardinal(colors[select]); Inc(k); end; end; end; end; end;
|
сохраняю полученный массив в битмап - картинка открывается, глубина цвета 32 бита. Всё замечательно. Затем беру этот битмап, перегоняю в DDS:
| Код | procedure EncodeBitmap32toDXT1(Src, Enc: PByteArray; w, h: integer); var col0, col1, cw: word; bitmask: Cardinal; cl: array [0..3] of crgba; temp: pbyte; x, y, i, j, k, n: integer; ma, mi, l: integer; c1, c2, c: crgba; tr: boolean;
function coldst(c1, c2: crgba): integer; begin result := sqr(c1[0] - c2[0]) + sqr(c1[1] - c2[1]) + sqr(c1[2] - c2[2]) + sqr(c1[3] - c2[3]); end;
begin fillchar(enc ^, w * h div 2, 0); temp := pbyte(enc); for y := 0 to (h div 4) - 1 do for x := 0 to (w div 4) - 1 do begin tr := false; c1 := pcrgba(@ src[((4 * y + 3) * w + (4 * x + 3)) * 4]) ^; c2 := pcrgba(@ src[((4 * y + 0) * w + (4 * x + 0)) * 4]) ^; mi := maxint; ma := 0; for j := 0 to 3 do for i := 0 to 3 do if ((4 * x + i) < w) and ((4 * y + j) < h) then begin c := pcrgba(@ src[((4 * y + j) * w + (4 * x + i)) * 4]) ^; l := EncodeColor(c[2], c[1], c[0]); if l > ma then begin c1 := c; ma := l; end; if l < mi then begin c2 := c; mi := l; end; if c[3] = 0 then tr := true; end; col0 := EncodeColor(c1[2], c1[1], c1[0]); col1 := EncodeColor(c2[2], c2[1], c2[0]); if tr then begin c := c1; c1 := c2; c2 := c; cw := col0; col0 := col1; col1 := cw; end; cl[0][0] := c1[0]; cl[0][1] := c1[1]; cl[0][2] := c1[2]; cl[0][3] := $FF; cl[1][0] := c2[0]; cl[1][1] := c2[1]; cl[1][2] := c2[2]; cl[1][3] := $FF; if not tr then begin cl[2][0] := (2 * cl[0][0] + cl[1][0] + 1) div 3; cl[2][1] := (2 * cl[0][1] + cl[1][1] + 1) div 3; cl[2][2] := (2 * cl[0][2] + cl[1][2] + 1) div 3; cl[2][3] := $FF; cl[3][0] := (cl[0][0] + 2 * cl[1][0] + 1) div 3; cl[3][1] := (cl[0][1] + 2 * cl[1][1] + 1) div 3; cl[3][2] := (cl[0][2] + 2 * cl[1][2] + 1) div 3; cl[3][3] := $FF; end else begin cl[2][0] := (cl[0][0] + 2 * cl[1][0] + 1) div 3; cl[2][1] := (cl[0][1] + 2 * cl[1][1] + 1) div 3; cl[2][2] := (cl[0][2] + 2 * cl[1][2] + 1) div 3; cl[2][3] := $FF; cl[3][0] := (2 * cl[0][0] + cl[1][0] + 1) div 3; cl[3][1] := (2 * cl[0][1] + cl[1][1] + 1) div 3; cl[3][2] := (2 * cl[0][2] + cl[1][2] + 1) div 3; cl[3][3] := $00; end; k := 0; bitmask := 0; for j := 0 to 3 do for i := 0 to 3 do if ((4 * x + i) < w) and ((4 * y + j) < h) then begin c := pcrgba(@ src[((4 * y + j) * w + (4 * x + i)) * 4]) ^; n := 0; mi := maxint; l := coldst(c, cl[0]); if l < mi then begin mi := l; n := 0; end; l := coldst(c, cl[1]); if l < mi then begin mi := l; n := 1; end; l := coldst(c, cl[2]); if l < mi then begin mi := l; n := 2; end; l := coldst(c, cl[3]); if l < mi then n := 3; bitmask := bitmask + Cardinal(n shl k); k := k + 2 end; pword(temp) ^ := col0; Inc(temp, 2); pword(temp) ^ := col1; Inc(temp, 2); PCardinal(temp) ^ := bitmask; Inc(temp, 4); end; end;
|
и получаю исходный DDS файл. Алгоритм работает, все хорошо. Затем беру обычный битмап, загружаю, делаю его 32 битным, сохраняю в DDS - и получаю вообще какую-то хрень. Даже контуров битмапа нету, есть набор цветных пятен. Но правда, для каждого дефолтного битмапа - он свой-) При этом, различие в структурах битмапов:
http://shot.qip.ru/00jrEX-5veBVkbL8/ - родной битмап, который всегда был битмапом.
http://shot.qip.ru/00jrEX-6veBVkbL9/ - битмап который получен из DDS.
Собственно вопрос - что я делаю не так? Отчего битмап полученный из DDS перегоняется обратно без проблем, а любой другой - перегоняется в адскую кашу? Ну и главный вопрос, что я не учитываю при перегонке bmp в DDS?
|