![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как ускорить снятие скриншота, Ассемблерная вставка
Вова © (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;
как то так делался у меня скриншот, ну примерно в общем не суть, как это объединить?
ProgRAMmer Dimonych (2013-09-02 21:19:00) [1]> И также меня вдруг осенило как работать с перевернутым массивом
> так как будто он не перевернут. И то что Ша тут партизанит,
> не думаю, что это чему то меня учит, просто я потратил
> кучу времени чтобы понять то что мог понять с одного поста
> ответа тут )
А вот это и есть самый лучший способ действительно разобраться в вопросе: дойти самому, а не получить готовое на блюдечке :)
Вова (2013-09-02 01:42:00) [2]хотя в начале Ша конечно меня нереально продвинул ) сам бы я до такого не дошел. Спал бы спокойно )) Сейчас скорость программы даже создает определенные трудности, она работает так быстро, что приходится паузы ставить, что бы инфа успевала обновляться ) но зато есть задел на бОльшие объемы данных. Хотя второй фильтр все еще медленней 170 милисекунд, но уже его в 2 раза убыстрил )
Вова (2013-09-02 01:35:00) [3]
> Вовы ВНЕЗАПНО на конец...
а все потому, что нет ни одной понятной картинки
опщем, да нужно было просто inc от scanline[0] в конец строки сделать. И также меня вдруг осенило как работать с перевернутым массивом так как будто он не перевернут. И то что Ша тут партизанит, не думаю, что это чему то меня учит, просто я потратил кучу времени чтобы понять то что мог понять с одного поста ответа тут ) удивительное отношение на форуме, я уже тут полгода со всем этим сношаюсь, а ко мне относятся так как будто я студент пришел кусовую нахаляву списать )
Вообщем вроде все починил, 3.3 миллисекунды на 1920 на 1080 шарашит, но че то на win7 работает, а на XP нет...нада будет смотреть опять (
Sapersky (2013-08-30 14:05:00) [4]Ну а что ты хотел - во всех хелпах написано, что на начало, все используют, у всех работает, а тут у Вовы ВНЕЗАПНО на конец...
procedure CopyPart32(Src, Dst : TBitmap; OffsX, OffsY : Integer;
Inverted : Boolean = True);
Var y : Integer;
ps, pd : PDWord;
begin
If Inverted then begin
ps := Src.ScanLine[0]; // последняя строка
Dec(ps, Src.Width * (OffsY + Dst.Height));
// битмап перевёрнут, отступаем СНИЗУ на OffsY + Height
end else begin
ps := Src.ScanLine[Src.Height-1]; // первая строка
Inc(ps, Src.Width * OffsY);
end;
Inc(ps, OffsX);
pd := Dst.ScanLine[Dst.Height-1]; // первая строка
For y:=0 to Dst.Height-1 do begin
Move(ps^, pd^, Dst.Width * 4);
Inc(ps, Src.Width); Inc(pd, Dst.Width);
end;
end;
Inverted = True - битмапы перевёрнуты, режим по умолчанию.
Inverted = False - битмапы с отрицательной высотой, не перевёрнутые. Это таки работает, но до сканлайна не доходит, что битмап "нормальный", поэтому нужно брать начало (Src.ScanLine[Src.Height-1]) и дальше считать все смещения самостоятельно.
Вова (2013-08-30 13:58:00) [5]тваюмашу, неугадал (
Вова (2013-08-30 13:30:00) [6]и таким образом получается, что битмап в памяти не перевернут вообще. Перевернут обход по пикселям. Т.е. если идти по возрастанию, то обход нужно начинать в правом нижнем углу.
Вова (2013-08-30 13:20:00) [7]правильный ответ: Потому что в результате того, что у того кто разрабатывал всю эту архитектуру были не все дома, то tbmpDest.ScanLine[0]; указывает не на конец битмапа, а на конец последней строки(который находится в крайней правой точке картинки), как и любой сканлайн указывает на конец строки битмапа , переданной в параметре, в памяти.
Sha (2013-08-30 10:02:00) [8]Для того, чтобы скопировать в цикле элементы
с индесами от N-1 до 0, необходимо выйти из цикла
либо после копирования элемента, имеющего нулевой индекс,
либо перед копированием элемента, имеющего отрицательный индекс.
Вова (2013-08-30 01:35:00) [9]логично, но вопрос как раз в том, почему.
Sha (2013-08-29 09:42:00) [10]потому что строка, для которой ppixelDest=last, не копируется
Вова (2013-08-29 01:06:00) [11]тысяча чертей, почему у меня верхняя строка целевого битмапа пустая? я уже все глаза сломал не могу понять (
function CopyRect(ppixel,ppixelDest,last: pInt64;
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;
function CalcLenght(EndS, StartS: integer): integer;
begin
result := EndS - StartS;
end;
Procedure TScreenShot.CopyScreenScanLine(var tbmpDest: Tbitmap; Coord: TCoord);
var
LineLength, SkipLine, i: integer;
Destination, Start, last: pInt64;
begin
tbmpDest.Width := Coord.x2work - Coord.x1work + 1;
tbmpDest.Height := Coord.y2work - Coord.y1work + 1;
if Coord.x2work = 0 then
begin
tbmpDest.Width := screen.Width;
Coord.x2work := screen.Width - 1
end;
if Coord.y2work = 0 then
begin
tbmpDest.Height := screen.Height;
Coord.y2work := screen.Height - 1;
end;
if (tbmpDest.Width div 2) <> (tbmpDest.Width / 2) then
// строка битмапа должна быть четной
if tbmpDest.Width = screen.Width then
tbmpDest.Width := tbmpDest.Width - 1
else
tbmpDest.Width := tbmpDest.Width + 1;
WaitForSingleObject(MyMutex, INFINITE);
if (fNumberOfShot = 0) or (tbmpDest.Height < 2) then
exit;
Start := fScreen.ScanLine[Coord.y2work];
inc(Start, Coord.x1work div 2);
Destination := tbmpDest.ScanLine[(tbmpDest.Height - 1)];
last := tbmpDest.ScanLine[0];
LineLength := tbmpDest.Width div 2;
SkipLine := CalcLenght(fScreen.Width, tbmpDest.Width) div 2;
CopyRect(Start, Destination, last, LineLength, SkipLine);
ReleaseMutex(MyMutex);
end;
Sha (2013-08-22 15:36:00) [12]теорию сам погугли, а пример могу дать:
http://guildalfa.ru/alsha/node/22
Вова (2013-08-22 15:21:00) [13]
> разверни цикл, Люк
это я так и не понял как делается (
Sha (2013-08-22 14:42:00) [14]разверни цикл, Люк
Вова (2013-08-22 14:23:00) [15]вооот, а если вместо PInteger сделать pInt64, то скорость вырастет еще на треть. ток надо чтобы битмап имел четное количество пикселей.
Вова (2013-08-22 07:38:00) [16]да но последний scanline быстрее SSE )
Sapersky (2013-08-22 00:15:00) [17]Проверил - обычный BitBlt быстрее копирования через Move и совсем немного уступает варианту с SSE (зато без ограничений по выравниванию и размеру).
Sha (2013-08-21 22:29:00) [18]> мне же ее нужно в цикле восстанавливать к прежнему значению
Ах, да, конечно. Это я съел что-нибудь.
> где логика......
Действительно. Потерял, наверное.
Вова (2013-08-21 21:49:00) [19]
Start := fScreen.ScanLine[Coord.y2work];
inc(Start, Coord.x1work);
короче работает тока так.... а так не работает....Start := fScreen.ScanLine[(fScreen.Height - 1) - Coord.y1work];где логика......
Вова (2013-08-21 17:57:00) [20]как так не нужна, мне же ее нужно в цикле восстанавливать к прежнему значению, если я его затру, к чему же я его буду восстанавливать?