Форум: "Начинающим";
Текущий архив: 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