Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2014.06.29;
Скачать: CL | DM;

Вниз

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

 
Sapersky   (2013-08-17 00:48) [40]

Move(Source^, Destination^, 1000);
Я предлагал брать окно и потом остальное вокруг этого окна с десктопа.


 
Вова   (2013-08-17 00:54) [41]

эм...эт как? окно по хендлу Апи функцией? вот это мне низя. А уж как воокруг еще взять, не скриншотом я и не знаю )


 
Вова   (2013-08-17 01:02) [42]

ндааа

Source      := fScreen.ScanLine[0];
 Destination := tbmpDest.ScanLine[0];
 Move(Source^, Destination^, 1500);

такое ощущение, что он копирует только первую строку, а на 1500 уже вылетает по ошибке....точно хз на скольки, но суть в том что что то не то...


 
Sapersky   (2013-08-17 01:18) [43]

Ну тогда ScanLine[fScreen.Height-1].

Окно - например через GetForegroundWindow, потом GetDC/BitBlt. Непонятно, какой в этом криминал и почему "низя".
Вокруг окна - обычным скриншотом через GetDC(0), в надежде, что площадь будет небольшая и сработает быстро. Точнее, 4-мя скриншотами (сверху, снизу, слева, справа).


 
Sapersky   (2013-08-17 01:43) [44]

Или подождать, когда у большинства будет Win8 - MS как раз родил специальный API для доступа к десктопу:
http://msdn.microsoft.com/en-us/library/windows/desktop/hh404487(v=vs.85).aspx
Лет 5?


 
antonn_tmp   (2013-08-17 10:04) [45]

А если окна слоеные и пересекаются, с полупрозрачностями, как сфотографируется окно?


 
Вова   (2013-08-17 11:03) [46]


> Ну тогда ScanLine[fScreen.Height-1].


это спасает, но не сильно. Этой функцией нельзя скопировать кусок памяти источника. Она просто фигачит первую строку скрина, и заполняет ей целевой бмп. Т.е. когда она доходит до конца строки целевого бмп, она переходит на следующую строку его при записи, а вот при чтении скрина нет, она также продолжает идти по той же строке источника.


 
Туповатый   (2013-08-17 13:23) [47]

Задача не озвучена, но чувствуется, что пытаются гвозди микроскопом забивать. НИМХО


 
Вова   (2013-08-17 14:09) [48]


Procedure  TScreenShot.CopyScreen(var tbmpDest:TBitmap; Coord:TCoord);
var
 Source,Destination:Pointer;
 i:word;
begin
 for I := 0 to tbmpDest.Height-1 do
 begin
   Source      := fScreen.ScanLine[fScreen.Height-1-i];
   Destination := tbmpDest.ScanLine[tbmpDest.Height-1-i];
   Move(Source^, Destination^, tbmpDest.Width*4);
 end;
end;


если так, то полный скрин 3.5 миллисекунд копируется


 
Вова   (2013-08-17 14:15) [49]

for i := 0 to tbmpDest.Height - 1 do
 begin
   Source := fScreen.ScanLine[fScreen.Height - 1 - i];
   Destination := tbmpDest.ScanLine[tbmpDest.Height - 1 - i];
   CopySSE(Source, Destination, tbmpDest.Width*4)
 end;

а так 2.44


 
Вова   (2013-08-17 14:35) [50]


procedure CopySSE(Src, Dst : Pointer; Cnt : Integer);
asm
  shr ecx, 5
@@mix:
  movapd xmm0, [eax]
  movapd xmm1, [eax+16]
  movapd [edx], xmm0
  movapd [edx+16], xmm1
  add eax, 32
  add edx, 32
  dec ecx
  jnz @@mix
end;

Procedure TScreenShot.CopyScreen(var tbmpDest: Tbitmap; Coord: TCoord);
var
 Source, Destination: Pointer;
 i: Word;
begin
 // WaitForSingleObject(MyMutex, INFINITE);
 for i := 0 to tbmpDest.Height - 1 do
 begin
   Source := fScreen.ScanLine[(fScreen.Height - 1 -Coord.y1work- i)-Coord.x1work*4];
   Destination := tbmpDest.ScanLine[tbmpDest.Height - 1 - i];
   //Move(Source^, Destination^, tbmpDest.Width*4);
   CopySSE(Source, Destination, tbmpDest.Width*4)
 end;
 // ReleaseMutex(MyMutex);

end;


в таком варианте в конце картинки не хватает пикселя в конце строки, если кусок длинной 500, но если 504 то хватает... как то я не понял фишку )


 
Вова   (2013-08-17 14:42) [51]

кратно 8 должно быть?


 
Вова   (2013-08-17 16:05) [52]

че то я там с вырезанием  квадрата накосячил )

function LockConvertBmpToRGBColorMapM(ppixel: pInteger;ppixelDest: pInteger;last:pInteger): Boolean;
begin
 repeat
     ppixelDest^:=ppixel^;
     inc(ppixel,1);
     inc(ppixelDest,1);
 until ppixel=last;
 Result := true;
end;

Procedure TScreenShot.CopyScreen(var tbmpDest: Tbitmap; Coord: TCoord);
var
 i: Word;
 Destination,Start,Last: pInteger;
begin

   Start:= fScreen.ScanLine[(fScreen.Height - 1)];
   Last := fScreen.ScanLine[0];
   Destination := tbmpDest.ScanLine[tbmpDest.Height - 1];

   LockConvertBmpToRGBColorMapM(Start,Destination,last);

end;


а так 2.9 (

ассемблер всех обогнал ) только картинка должна быть размером кратно 4


 
Вова   (2013-08-17 16:57) [53]

Вообщем дальнейшие тесты показали, что если копировать небольшие картинки (кусок 500 на 500 разница на 0.1 милисекунды), то заморачиться смысла нет. Тем более, что на ассемблере еще нужно прикручивать выравнивание, а оно тоже чего нибудь отожрет.

И возник вопрос: Как правильно написать, чтобы по x сдвинуть копируемый участок? как я сейчас сделал получается какая то фигня, слева вроде все нормально, но справа рисуется левая часть (которая в копируемый диапазон вроде как не попала) картинки источника.

Procedure TScreenShot.CopyScreenSSE(var tbmpDest: Tbitmap; Coord: TCoord);
var
 Source, Destination: pInteger;
 i: Word;
begin

 //WaitForSingleObject(MyMutex, INFINITE);
 for i := 0 to tbmpDest.Height - 1 do
 begin
   //i:=0;
   Source := fScreen.ScanLine[(fScreen.Height - 1 -Coord.y1work- i)];
   inc(Source,Coord.x1work);
   Destination := tbmpDest.ScanLine[tbmpDest.Height - 1 - i];
   //Move(Source^, Destination^, tbmpDest.Width*4);
   CopySSE(Source, Destination, tbmpDest.Width*4);
 end;
 //ReleaseMutex(MyMutex);

end;


 
Вова   (2013-08-17 17:16) [54]

упс......
> И возник вопрос: Как правильно написать, чтобы по x сдвинуть
> копируемый участок? как я сейчас сделал получается какая
> то фигня, слева вроде все нормально, но справа рисуется
> левая часть (которая в копируемый диапазон вроде как не
> попала) картинки источника.


это я исправил еще в том же посте где и спросил ))

function LockConvertBmpToRGBColorMapM(ppixel: pInteger;ppixelDest: pInteger;last:pInteger): Boolean;
begin
 repeat
     ppixelDest^:=ppixel^;
     inc(ppixel);
     inc(ppixelDest);
 until ppixelDest=last;
end;

Procedure TScreenShot.CopyScreenScanLine(var tbmpDest: Tbitmap; Coord: TCoord);
var
 //Source, Destination: Pointer;
 i: Word;
 Destination,Start,Last: pInteger;
begin
for i := 0 to tbmpDest.Height - 1 do
 begin
   //i:=0;
   Start := fScreen.ScanLine[(fScreen.Height - 1 -Coord.y1work- i)];
   inc(Start,Coord.x1work);
   Destination := tbmpDest.ScanLine[tbmpDest.Height - 1 - i];
   Last := Destination;
   inc(Last,tbmpDest.Width);
   LockConvertBmpToRGBColorMapM(Start,Destination,Last);
 end;
end;


ну и в заключении решил дать шанс просто сканлайну, работает немножко медленней чем Move. на картинке размером 500 на 500 пикселей все 3 варианта в пределах одной десятой миллисекунды различаются ))

где же Sha?))


 
Вова   (2013-08-17 18:14) [55]

единственное, что хорошо в сканлайне, это то что я понимаю как его с фильтром объединить ) Move вообще никак, а ассемблер надо знать как )


 
ProgRAMmer Dimonych ©   (2013-08-18 15:20) [56]

Может, пора заняться функционалом, а не оптимизацией быстрого?


 
Вова   (2013-08-18 17:16) [57]

функционал уже есть. Вчера перевел все что мог на 32 битный битмап (но не на сканлайн)....до сих пор баги исправляю (


 
Вова   (2013-08-21 00:34) [58]

где в последней процедуре ошибка? ( какой то неправильный он мне квадрат вырезает (


 
Sha ©   (2013-08-21 01:42) [59]

Попробуй обработать отрезок каждой строки, пересекающей твой квадрат.
Сразу поймешь в чем дело.


 
Вова   (2013-08-21 01:49) [60]

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

Start := fScreen.ScanLine[(fScreen.Height - 1 -Coord.y1work- i)];


тут что то не так, но что я понять не могу......

по x примерно совпадает...

причем если Coord.y1work = 0 то проблем нет....


 
Вова   (2013-08-21 02:04) [61]

Start := fScreen.ScanLine[(Coord.y2work - i)];

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


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

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


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


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

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


 
Sha ©   (2013-08-21 09:33) [64]

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


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

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

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


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

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

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


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


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

Это всё уже обсуждалось:
http://delphimaster.net/view/9-1186325580/
Но это нужно лишнюю переменную заводить на каждый сканлайн и каждый раз её инициализировать.

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

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


 
Sha ©   (2013-08-21 14:04) [68]

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

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

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

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


 
Sha ©   (2013-08-21 14:10) [69]

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


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

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

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


 
Sha ©   (2013-08-21 14:42) [71]

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

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


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

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


 
Sha ©   (2013-08-21 15:17) [73]

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

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

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

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


 
Sha ©   (2013-08-21 15:17) [74]

двойного?


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

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


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

вот зануды.

ассеблер вырезание 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;


 
Sha ©   (2013-08-21 17:16) [77]

некузяво

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


 
Sha ©   (2013-08-21 17:27) [78]

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


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

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

ничо не понял, и это ничего не дает.
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;


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

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

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;



Страницы: 1 2 3 вся ветка

Текущий архив: 2014.06.29;
Скачать: CL | DM;

Наверх




Память: 0.64 MB
Время: 0.009 c
2-1377746622
FIL-23
2013-08-29 07:23
2014.06.29
chart имя легенды на графике


15-1386952352
Kipan
2013-12-13 20:32
2014.06.29
GDI


15-1386793811
Юрий
2013-12-12 00:30
2014.06.29
С днем рождения ! 12 декабря 2013 четверг


15-1387103920
Cobalt
2013-12-15 14:38
2014.06.29
copy-on-write 8-bit строки


15-1386966602
Юрий
2013-12-14 00:30
2014.06.29
С днем рождения ! 14 декабря 2013 суббота