Модераторы: Snowy, Alexeis, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Непонятки с цветом при работе с пикселями, DDS > BMP и обратно. 
:(
    Опции темы
CynicRus
Дата 11.9.2014, 09:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 248
Регистрация: 31.5.2012

Репутация: 2
Всего: 5



Приветствую уважаемых форумчан. Декодирую 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 - и получаю вообще какую-то хрень. Даже контуров битмапа нету, есть набор цветных пятен. Но правда, для каждого дефолтного битмапа - он свой-) При этом, различие в структурах битмапов:


user posted image - родной битмап, который всегда был битмапом.

user posted image - битмап который получен из DDS.

Собственно вопрос - что я делаю не так? Отчего битмап полученный из DDS перегоняется обратно без проблем, а любой другой - перегоняется в адскую кашу? Ну и главный вопрос, что я не учитываю при перегонке bmp в DDS?

PM MAIL   Вверх
drkot
Дата 12.9.2014, 12:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ищущий
***


Профиль
Группа: Завсегдатай
Сообщений: 1042
Регистрация: 5.5.2006

Репутация: нет
Всего: 8



Цитата(CynicRus @  11.9.2014,  10:35 Найти цитируемый пост)
делаю его 32 битным

по всей видимости это не так

Добавлено через 11 минут и 54 секунды
Думаю имеет смысл использовать TBitmap.ScanLine.
Быстродействие сохранится, и проблем с различными битностями не должно возникнуть


--------------------
Ошибка не становится истиной по причине широкого распространения,
как и Истина не становится Ошибкой из-за того, что никто её не видит.
PM   Вверх
CynicRus
Дата 12.9.2014, 21:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 248
Регистрация: 31.5.2012

Репутация: 2
Всего: 5



Так я и работаю со ScanLine, массив был использован просто для доп проверки. Или ты имеешь ввиду - перевести 24 бита в 32 бита с помощью ScanLine? Пробовал - результат - болт.

PM MAIL   Вверх
drkot
Дата 13.9.2014, 18:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ищущий
***


Профиль
Группа: Завсегдатай
Сообщений: 1042
Регистрация: 5.5.2006

Репутация: нет
Всего: 8



Цитата(CynicRus @  12.9.2014,  22:01 Найти цитируемый пост)
работаю со ScanLine

в представленном коде ее нет, следовательно догадаться о том что она где-то есть ....

Учитывая что Вы работаете с некой ссылкой на массив, то: не факт что она указывает на правильные данные.

Думаю надо начать с того, что сделать однопиксельный файл и проверить его конвертацию.
Как минимум будет просто отследить баг



--------------------
Ошибка не становится истиной по причине широкого распространения,
как и Истина не становится Ошибкой из-за того, что никто её не видит.
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Звук, графика и видео"
Girder
Snowy
Alexeis

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делится вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • По вопросам разработки игр стоит заглянуть сюда

FAQ раздела лежит здесь!


Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Girder, Snowy.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Звук, графика и видео | Следующая тема »


 




[ Время генерации скрипта: 0.0420 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.