Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2014.06.29;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.64 MB
Время: 0.006 c
15-1386687468
МАКсим007
2013-12-10 18:57
2014.06.29
авторское право


2-1377689079
DZM
2013-08-28 15:24
2014.06.29
Модальное окно оказывается позади


2-1377191147
Дмитрий
2013-08-22 21:05
2014.06.29
обновление по дате изменения файла


6-1273138904
nordek
2010-05-06 13:41
2014.06.29
Приложение сервер-клиент, как связать в интеренете.


2-1377509988
Viktor
2013-08-26 13:39
2014.06.29
ssShift + vk_numpad1





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский