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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Ускорение функции сглаживания 
:(
    Опции темы
SMaks
Дата 31.1.2008, 02:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Здравствуйте!

В общем нужно сгладить линию алгоритмом By, но сделать это с максимальным быстродействием (gdi+ не предлогать). Вот что у меня получилось:

Код

function GetPixelW(Bitmap: TBitmap; X,Y: Integer): TColor;
var
  pixel: PRGBTriple;
begin
  if Bitmap.PixelFormat = pf24bit then
  begin
    DWORD(pixel) := DWORD(Bitmap.ScanLine[Y]) + (X * SizeOf(TRGBTriple));
    Result := RGB(pixel.rgbtRed, pixel.rgbtGreen, pixel.rgbtBlue);
  end
    else Result := 0;
end;

procedure SetPixelW(Bitmap: TBitmap; X,Y: Integer; Color: TColor);
var  pixel: PRGBTriple;
begin
  if Bitmap.PixelFormat = pf24bit then
  begin
    DWORD(pixel) := DWORD(Bitmap.ScanLine[Y]) + (X * SizeOf(TRGBTriple));
    pixel.rgbtRed   := GetRValue(Color);
    pixel.rgbtGreen := GetGValue(Color);
    pixel.rgbtBlue  := GetBValue(Color);
  end;
end;

function MixBytes(FG, BG, TRANS: byte): byte;
 asm
  push bx  // push some regs
  push cx
  push dx
  mov DH,TRANS // remembering Transparency value (or Opacity - as you like)
  mov BL,FG    // filling registers with our values
  mov AL,DH    // BL = ForeGround (FG)
  mov CL,BG    // CL = BackGround (BG)
  xor AH,AH    // Clear High-order parts of regs
  xor BH,BH
  xor CH,CH
  mul BL       // AL=AL*BL
  mov BX,AX    // BX=AX
  xor AH,AH
  mov AL,DH
  xor AL,$FF   // AX=(255-TRANS)
  mul CL       // AL=AL*CL
  add AX,BX    // AX=AX+BX
  shr AX,8     // Fine! Here we have mixed value in AL
  pop dx       // Hm... No rubbish after us, ok?
  pop cx
  pop bx       // Bye, dear Assembler - we go home to Delphi!
end;

function MixColors(FG, BG: TColor; T: byte): TColor;
 var r,g,b:byte;
 begin
   R := MixBytes(FG and 255,BG and 255,T); // extracting and mixing Red
  G := MixBytes((FG shr 8) and 255,(BG shr 8) and 255,T); // the same with green
  B := MixBytes((FG shr 16) and 255,(BG shr 16) and 255,T); // and blue, of course
  Result := r+g*256+b*65536; // finishing with combining all channels together
end;


procedure DrawWuLine(bt: TBitmap; x1, y1, x2, y2: real; clr: TColor);
//-----------------------------------------------------//
  procedure SetPixel(x, y: Integer; Brightness: Double);
  var
    Color: TColor;
  begin
    if round(100*Brightness) = 100 then
      SetPixelW(bt, x, y, clr)
    else
      if not (trunc(100*Brightness) = 0) then
      begin
        Color := GetPixelW(bt, x, y);
        Color := MixColors(clr, Color, trunc(Brightness*255));
        SetPixelW(bt, x, y, Color);
      end;
  end;
//-----------------------------------------------------//
  function MyFrac(X: Double): Double;
  begin
    Result := X-Floor(X);
  end;
//-----------------------------------------------------//
var
  grad: Double;
  xd, yd: Double;
  xgap: Double;
  xend, yend: Double;
  yf: Double;
  brightness1: Double;
  brightness2: Double;
  x: Integer;
  ix1, ix2: Integer;
  iy1, iy2: Integer;
  WasExchange: Boolean;
  TmpReal: Double;
begin
  if (x1 = x2) or (y1 = y2) then
  begin
    bt.Canvas.Pen.Color := clr;
    bt.Canvas.MoveTo(trunc(x1), trunc(y1));
    bt.Canvas.LineTo(trunc(x2), trunc(y2));
    Exit;
  end;

  xd := x2-x1;
  yd := y2-y1;

  if (xd=0) and (yd=0) then Exit;
  
  if Abs(xd) > Abs(yd) then
    WasExchange := False
  else
    begin
      WasExchange := True;
      TmpReal := x1;
      x1 := y1;
      y1 := TmpReal;
      TmpReal := x2;
      x2 := y2;
      y2 := TmpReal;
      TmpReal := xd;
      xd := yd;
      yd := TmpReal;
    end;

  if x1 > x2 then
  begin
    TmpReal := x1;
    x1 := x2;
    x2 := TmpReal;
    TmpReal := y1;
    y1 := y2;
    y2 := TmpReal;
    xd := x2-x1;
    yd := y2-y1;
  end;

  grad := yd / xd;
  xend := Floor(x1 + 0.5);
  yend := y1+grad*(xend - x1);
  xgap := 1-MyFrac(x1 + 0.5);
  ix1 := Floor(x1 + 0.5);
  iy1 := Floor(yend);

  brightness1 := (1-MyFrac(yend))*xgap;
  brightness2 := MyFrac(yend)*xgap;

  if WasExchange then
    begin
      SetPixel(iy1, ix1, Brightness1);
      SetPixel(iy1+1, ix1, Brightness2);
    end
  else
    begin
      SetPixel(ix1, iy1, Brightness1);
      SetPixel(ix1, iy1+1, Brightness2);
    end;

  yf := yend+grad;
  xend := Floor(x2+0.5);
  yend := y2+grad*(xend-x2);
  xgap := 1-MyFrac(x2-0.5);

  ix2 := Floor(x2+0.5);
  iy2 := Floor(yend);

  brightness1 := (1-MyFrac(yend))*xgap;
  brightness2 := MyFrac(yend)*xgap;

  if WasExchange then
    begin
      SetPixel(iy2, ix2, brightness1);
      SetPixel(iy2+1, ix2, brightness2);
    end
  else
    begin
      SetPixel(ix2, iy2, brightness1);
      SetPixel(ix2, iy2+1, brightness2);
    end;

  x := ix1 + 1;
  while x <= ix2-1 do
  begin
    brightness1 := 1-MyFrac(yf);
    brightness2 := MyFrac(yf);

    if WasExchange then
      begin
        SetPixel(Floor(yf), x, brightness1);
        SetPixel(Floor(yf)+1, x, brightness2);
      end
    else
      begin
        SetPixel(x, Floor(yf), brightness1);
        SetPixel(x, Floor(yf)+1, brightness2);
      end;

    yf := yf+grad;
    Inc(x);
  end;
end;


Нужно бы перевести эту функцию на asm и какие есть еще идеи оптимизации?
И еще вопрос, что быстрее: использовать ScanLine для отрисовки обычной линии или MoveTo-LineTo?

Это сообщение отредактировал(а) SMaks - 31.1.2008, 02:03
PM MAIL   Вверх
Alexeis
Дата 31.1.2008, 10:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 55
Всего: 459



Цитата(SMaks @  31.1.2008,  01:02 Найти цитируемый пост)
И еще вопрос, что быстрее: использовать ScanLine для отрисовки обычной линии или MoveTo-LineTo?

  Одна линия быстрее будет через LineTo, а когда их много, то уже через ScanLine, а вообще если нужна реальная скорость, то лучше подумать об OpenGl

Добавлено через 1 минуту и 3 секунды
Про SetPixel можно сразу забыть, это жуткие тормоза.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Звук, графика и видео"
Girder
Snowy
Alexeis

Запрещено:

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

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

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

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


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

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


 




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


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

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