Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Как ускорить снятие скриншота, Ассемблерная вставка


Страницы:   1 2 3 4 5 6

Вова ©   (2013-08-14 16:21:00) 

Обнаружил я такой вот код.
Питаю надежду, что он будет работать быстрей моего.

http://www.programmersforum.ru/showthread.php?t=35588

asm
   push esi
   push edx

   mov ecx, BufLength           // размер массива (Integer)
   mov esi, PointerBuf1Scr     // указатель на источник (Pointer)
   mov edx, PointerBuf2Scr    // указатель на приемник (Pointer)

 @@mix:
   movq      xmm0, [esi]     // buf1 -> в регистр
   movq      [edx], xmm0     // buf2 <- из регистра

   add esi, 8
   add edx, 8

   loop @@mix

   pop edx
   pop esi

   emms
 end;


Естественно ничего из написаного мне не понятно. Но исходя из контекста у меня возникло ощущение, что это можно использовать для снятия скриншота. Только вот как это должно выглядеть на делфи я не знаю. В общем то в этом и вопрос.


Procedure   TMyObject.getScreen(var tbmp: Tbitmap; tmpCoord: TCoord);
var
 hDC1: HDC;
 R: TRect;
 Canvas: TCanvas;
begin

 if tmpCoord.x2search = 0 then
   tmpCoord.x2search := screen.Width;

 if tmpCoord.y2search = 0 then
   tmpCoord.y2search := screen.Height;

 hDC1 := GetDC(0);
 Canvas := TCanvas.Create();
 Canvas.Lock;
 Canvas.Handle := hDC1;
 R := Rect(tmpCoord.x1search, tmpCoord.y1search, tmpCoord.x2search,
   tmpCoord.y2search);

 tbmp              := Tbitmap.Create;
 tbmp.Canvas.Lock;
 tbmp.Width        := R.Right  - R.Left;
 tbmp.Height       := R.Bottom - R.Top;
 tbmp.PixelFormat  := pf24bit;
 tbmp.Canvas.CopyRect(Rect(0,0,tbmp.Width,tbmp.Height), Canvas, R);

 ReleaseDC(0, hDC1);
 Canvas.Free;
 Canvas.Unlock;

end;


как то так делался у меня скриншот, ну примерно в общем не суть, как это объединить?


Sha   (2013-08-21 17:50:00) [21]

Разумеется, не дает. Но красота - страшная сила!

Замени ленч на каунт в объявлении процедуры - и локальная переменная будет не нужна.


Вова   (2013-08-21 17:48:00) [22]

все же по идее должно быть так....но на боевых данных вчера так не работало....

Procedure TScreenShot.CopyScreenScanLine(var tbmpDest: Tbitmap; Coord: TCoord);
var
 LineLength,SkipLine,i: integer;
 Destination, Start, last: pInteger;
begin
 WaitForSingleObject(MyMutex, INFINITE);
 if (fNumberOfShot = 0) or (tbmpDest.Height < 2) then
   exit;
//y*LineLength+x*PixelSize
   Start := fScreen.ScanLine[(fScreen.Height - 1) - Coord.y1work];
   inc(Start, Coord.x1work);
   Destination := tbmpDest.ScanLine[(tbmpDest.Height - 1)];
   last        := tbmpDest.ScanLine[0];
   LineLength  := tbmpDest.Width;
   SkipLine    := fScreen.Width - tbmpDest.Width;
   //inc(last, tbmpDest.Width);
   LockConvertBmpToRGBColorMapM2(Start, Destination, last,LineLength,SkipLine);
 ReleaseMutex(MyMutex);
end;


Вова   (2013-08-21 17:35:00) [23]

я ничего не пытался даже переворачивать, просто подругому вообще ничего внятного на выходе не получается.

ничо не понял, и это ничего не дает.
function LockConvertBmpToRGBColorMapM2(ppixel: pInteger; ppixelDest: pInteger;
 last: pInteger;Lenght,SkipLine:integer): Boolean;
var
 count:integer;
begin
 count:=Lenght;
 repeat
   repeat
     ppixelDest^ := ppixel^;
     inc(ppixel);
     inc(ppixelDest);
     dec(count);
   until count = 0;
   count:=Lenght;
   inc(ppixel,SkipLine)
 until ppixelDest = last;
end;


Sha   (2013-08-21 17:27:00) [24]

4. опять эти чудеса на виражах с переворотами картинок?
5. остаток строки SkipLine лучше вычислять в вызываемой процедуре.
6. inc(last, tbmpDest.Width); правильнее вычислять дельту между строками, хотя в данном случае это одно и то же.


Sha   (2013-08-21 17:16:00) [25]

некузяво

1. название? а результат? а варнинг?
2. word? integer!
3. inc(i)? dec(count)!


Вова   (2013-08-21 17:00:00) [26]

вот зануды.

ассеблер вырезание 500 на 500 делает за 0.468 миллисекунды
мув за 0.515 миллисекунды
Сканлайн в цикле за 0.562 миллисекудны

а сканлайн без сканлайна в цикле за 0.296

function LockConvertBmpToRGBColorMapM2(ppixel: pInteger; ppixelDest: pInteger;
 last: pInteger;Lenght,SkipLine:word): Boolean;
var
 i:word;
begin
 i:=0;
 repeat
   repeat
     ppixelDest^ := ppixel^;
     inc(ppixel);
     inc(ppixelDest);
     inc(i);
   until i=Lenght;
   i:=0;
   inc(ppixel,SkipLine)
 until ppixelDest = last;
end;

Procedure TScreenShot.CopyScreenScanLine(var tbmpDest: Tbitmap; Coord: TCoord);
var
 LineLength,SkipLine,i: Word;
 Destination, Start, last: pInteger;
begin
 WaitForSingleObject(MyMutex, INFINITE);
 if (fNumberOfShot = 0) or (tbmpDest.Height < 2) then
   exit;
//y*LineLength+x*PixelSize
   Start := fScreen.ScanLine[Coord.y2work];
   inc(Start, Coord.x1work);
   Destination := tbmpDest.ScanLine[(tbmpDest.Height - 1)];
   last        := tbmpDest.ScanLine[0];
   LineLength  := tbmpDest.Width;
   SkipLine    := fScreen.Width - tbmpDest.Width;
   //inc(last, tbmpDest.Width);
   LockConvertBmpToRGBColorMapM2(Start, Destination, last,LineLength,SkipLine);
 ReleaseMutex(MyMutex);
end;


проф. Преображенский   (2013-08-21 15:27:00) [27]

Мне мысли морщат мозг,
От знаний я старею,
Ответьте мне скорее:
А то созрел еще вопрос...


Sha   (2013-08-21 15:17:00) [28]

двойного?


Sha   (2013-08-21 15:17:00) [29]

> а отгадка где?

это тот, кто отгадал, должен сказать?

> сканлайн же на начало строки всегда показывает?

она же на границу слова всегда выровнена ?


Вова   (2013-08-21 15:09:00) [30]

а отгадка где? сканлайн же на начало строки всегда показывает?


Sha   (2013-08-21 14:42:00) [31]

> что за ScanLine(0); и ScanLine(1); это вообще не понятно.

дык то ж загадка, она не обязана быть понятной


Вова   (2013-08-21 14:30:00) [32]

1) адрес старта
2) расстояние от начала строки до точки старта + расстояние от конца копируемого отрезка до конца строки;
3) Длина копируемого отрезка (можно BmpDest.Width)
4) адрес конца вырезаемого прямоугольника. (BmpDest.ScanLine(0))

4 переменных, а что за ScanLine(0); и ScanLine(1); это вообще не понятно.


Sha   (2013-08-21 14:10:00) [33]

А в Вовином случае для перехода к границе квадрата на следующей строке
достаточно увеличить старую границу на d.


Sha   (2013-08-21 14:04:00) [34]

> Но это нужно лишнюю переменную заводить на каждый сканлайн
> и каждый раз её инициализировать.

Зачем? Достаточно одной... т.е. двух переменных:

a:=ScanLine(0);
d:=ScanLine(1)-a;

А дальше вместо ScanLine(n) использовать a+n*d


Sapersky   (2013-08-21 11:57:00) [35]


> Адреса сканлайнов представляют собой арифметическую прогрессию.

Это всё уже обсуждалось:
http://www.delphimaster.ru/cgi-bin/forum.pl?id=1186325580&n=9&from=96
Но это нужно лишнюю переменную заводить на каждый сканлайн и каждый раз её инициализировать.

> Вообще уже пора сайт с картинками сделать, а то нифига невозможно
> понять)

Да, постоянно считать эти перевороты довольно утомительно.
Я в конечном счёте перешёл на не перевёрнутые битмапы (с отрицательной высотой), благо класс-контейнер (TFastDIB) позволяет.


Вова   (2013-08-21 11:52:00) [36]

Хотя частые вызовы Scanline в некоторых случаях здорово всё тормозят.

а что тут есть возможность не вызывать часто сканлайн? когда я пытался просто идти как идется, то получалось, что делался проход по всей строке источника.....если наставить условий, что от сих до сих пишем в принимающий битмап, а остальные места просто пропускаем, то будет быстрее, чем если в цикле сканлайн запускать? хм....кстати да, особенно что если выходишь за отрезок который нужно копировать можно не inc(ppixel,1) делать, а сразу длину всего отрезка. над попробовать будет.


Вова   (2013-08-21 11:42:00) [37]

таки если он в Height-1 то как выходит так, что если я, отнимаю от этого значения координату У верхнего угла целевого прямоугольника и на выходе получаю что прямоугольник вырезается внизу? хотя на деле он вверху ). Таким образом я пошел другим путем, и от 0 взял координату У нижнего угла прямоугольника, и тогда попал в цель. Т.е. когда приращиваешь адрес то идешь от нижнего угла к верхнему.....хотя в данном случае чтобы перейти на следующую строку нужно опять делать сканлайн, так что неочень понятно опять же.

Вообще уже пора сайт с картинками сделать, а то нифига невозможно понять)


Sha   (2013-08-21 09:33:00) [38]

Адреса сканлайнов представляют собой арифметическую прогрессию.
Просто мысль.


Sapersky   (2013-08-21 02:46:00) [39]


> я думал что первый пиксель битмапа в fScreen.Height - 1,
>  оказывается он все же в 0

Таки в Height-1, но TBitmap.GetScanline переворачивает координату, задаёшь 0 - будет Height-1.
Если работать со сканлиниями по одной, не пытаясь скопировать/обработать сразу несколько, то по идее о переворотах можно не думать. Хотя частые вызовы Scanline в некоторых случаях здорово всё тормозят.
На уровне WinAPI есть способ создать нормальный, не перевёрнутый битмап - задать ему отрицательную высоту. Но с TBitmap это не работает, разве что наследника писать.


Вова   (2013-08-21 02:12:00) [40]

скорость поиска теперь доставляет ) пора переходить на микросекунды ) на замеры в микросекундах )


Страницы:   1 2 3 4 5 6

Наверх

Титульная страница Поиск, карта сайта Написать письмо