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;


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


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]

как так не нужна, мне же ее нужно в цикле восстанавливать к прежнему значению, если я его затру, к чему же я его буду восстанавливать?


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

Наверх

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