Very nice concept. Thanks for sharing it :-)
[EMAIL PROTECTED] wrote:
> ScreenGrabber is a part of Breeze (also licenced as freeware GNU GPL).
> You can find full source code on my web pages. Now I'm implementing 2
> way feed-back-buffer to accelerate and minimize data traffic.
>
> 1. call method Grab to find minimal changed rectangle (on the screen).
> 2. call GrabAccept.
> 3. in ResultBMP is stored changed bitmapdata.
>
> ScreenGrabber is developed in C++ and Object Pascal. Pascal for graphics
> issues, C++ for robust logic.
>
> Source code:
>
> unit ScreenChangeRecognition;
>
> interface
>
> uses
> Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
> StdCtrls, ExtCtrls,Math;
>
> type
> TPixels = array[0..$FFFFFF] of dword;
> PPixels = ^TPixels;
>
> type
> TChangeResult = record
> result:boolean; //byly detekovany zmeny
> ChangeRect:TRect; //obdelnik ktery se vymenil
> KeyFrame:boolean; //zjisti jestli byl zmenen celyscreen
> end;
>
> type
> TGrabMode = (GM_NORMAL,GM_KEYFRAME,GM_NOTRAYWND);
>
> type
> TChangeRecognition = class
> private
> ScreenDC:HDC;
> bmp:array [0..1] of TBitmap;
> pixels:array [0..1] of PPixels; //pole pixelu pro kazdou bitmapu
> lowbmp:TBitmap; //slouzi pro ulozeni rozdilu
> lowpix:PPixels; //pixely bitmapy pro detekci zmen
> counter:dword; //pocita kolikrat bylo zavolano grab
> fVideoHeight: integer;
> fVideoWidth: integer;
> fVideoX: integer;
> fVideoY: integer;
> fVideoH: integer;
> fVideoW: integer;
> RectSize:integer;
> fGrabMode: TGrabMode;
> procedure setVideoHeight(const Value: integer);
> procedure setVideoWidth(const Value: integer);
> procedure setVideoX(const Value: integer);
> procedure setVideoY(const Value: integer);
> procedure setVideoH(const Value: integer);
> procedure setVideoW(const Value: integer);
> public
> LastResult:TChangeResult;
> ResultBMP:TBitmap; //bitmapa se zmenenou casti
> procedure Grab; //najde zmeny v obrazu
> procedure GrabAccept; //akceptuje zmeny
> function getBitmap:TBitmap;
> function getLowBMP:TBitmap;
> constructor create;
> destructor destroy;
> procedure setVideoRect(ax,ay,aw,ah,destw,desth:integer);
> property VideoX:integer read fVideoX write setVideoX;
> property VideoY:integer read fVideoY write setVideoY;
> property VideoW:integer read fVideoW write setVideoW;
> property VideoH:integer read fVideoH write setVideoH;
> property VideoWidth:integer read fVideoWidth write setVideoWidth;
> property VideoHeight:integer read fVideoHeight write setVideoHeight;
> property GrabMode:TGrabMode read fGrabMode write fGrabMode;
> end;
>
>
> implementation
>
> { TChangeRecognition }
>
> constructor TChangeRecognition.create;
> var a:integer;
> begin
> //zjisti device context obrazovky
> ScreenDC:=getDC(0);
> RectSize:=5;
>
> //nastavi sirku a vysku videa
> fVideoWidth:=screen.width;
> fVideoHeight:=screen.Height;
> fVideoW:=screen.width;
> fVideoH:=screen.height;
>
> fGrabMode:=GM_NORMAL;
>
> //vytvori bitmapy do nichz bude uklada screen
> for a:=0 to high(bmp) do
> begin
> bmp[a]:=TBitmap.create;
> bmp[a].Width:=VideoWidth;
> bmp[a].Height:=VideoHeight;
> bmp[a].PixelFormat:=pf32bit;
> //nacte ukazatel
> pixels[a]:=bmp[a].ScanLine[bmp[a].height-1];
> end;
>
> ResultBMP:=TBitmap.create;
> ResultBMP.PixelFormat:=pf32bit;
>
> //nastavi rozmery lowbitmapy pro detekci rozdilu
> lowbmp:=TBitmap.create;
> //bitmapa musi byt vetsi o 3 pixely nebot se predsazuje pixel
> //dopredu a 2 pixely dozadu
> lowbmp.Width:=trunc(bmp[0].Width/RectSize)+3;
> lowbmp.Height:=trunc(bmp[0].Height/RectSize)+3;
> lowbmp.PixelFormat:=pf32bit;
> //nacte pixely
> lowpix:=lowbmp.ScanLine[lowbmp.height-1];
> end;
>
>
>
>
> destructor TChangeRecognition.destroy;
> begin
>
> end;
>
>
>
> //nastavi vysky videa
> function TChangeRecognition.getBitmap: TBitmap;
> var whichBMP:integer;
> begin
> whichBMP:=(counter mod (high(bmp)+1));
> result:=bmp[whichBMP];
> result:=bmp[0];
> end;
>
>
>
>
> function TChangeRecognition.getLowBMP: TBitmap;
> begin
> result:=lowbmp
> end;
>
>
>
>
> procedure TChangeRecognition.grab;
> var whichBMP:integer; //ktera bitmapa se pouzije
> x,y:integer;
> startx,starty:integer; //startovaci pozice aby bylo mozne detekovat
> zmeny
> position:integer; //pozice v poli pixelu ktera se porovnava
> pix1,pix2:PPixels; //pole pixelu pro porovnani a detekci zmen
> xscale,yscale:single; //koeficienty roztazeni okna
> TrayWnd:hwnd; //okno jehoz zmeny se nezaznamenavaji
> TrayWndRect:TRect;
> begin
> counter:=counter+1;
> //zjisti do ktere bitmapy se bude tisknout tentokrat
> whichBMP:=(counter mod (high(bmp)+1));
> whichBMP:=1;
> //pokud jsou strany obdelniku a,b source a dest stejne tak provede bitblt
> if ((VideoW=VideoWidth) and (VideoH=VideoHeight)) then
> begin
> bitblt(bmp[whichBMP].Canvas.Handle,
> 0,0,bmp[whichBMP].Width,bmp[whichBMP].Height,
> ScreenDC,VideoX,VideoY,srccopy);
> end
> //jinak provede stretchblt
> else
> begin
> SetStretchBltMode(bmp[whichBMP].Canvas.Handle,HALFTONE);
> //zmensi bitmapu
> StretchBlt(bmp[whichBMP].Canvas.Handle,
> 0,0,bmp[whichBMP].Width,bmp[whichBMP].Height,
> ScreenDC,VideoX,VideoY,VideoW,VideoH,srccopy);
> end;
>
> //pokud je snimek klicovym obrazkem tak neni treba vypocitavat
> nejmensi obdelnik
> if GrabMode=GM_KEYFRAME then
> begin
> LastResult.result:=true;
> LastResult.ChangeRect:=rect(0,0,VideoWidth,VideoHeight);
> LastResult.KeyFrame:=true;
> exit;
> end;
>
> //zjisti handle traywnd
> TrayWnd:=FindWindow('Shell_TrayWnd',nil);
> if not(getwindowrect(TrayWnd,TrayWndRect)) then
> TrayWndRect:=rect(0,0,0,0);
>
> //zjisti koeficient roztazeni z puvodni oblasti do nove
> xscale:=(VideoW)/VideoWidth;
> yscale:=(VideoH)/VideoHeight;
>
> //resetuje posledni vysledek
> LastResult.result:=false;
> LastResult.ChangeRect:=rect($FFFF,$FFFF,-1,-1);
> LastResult.KeyFrame:=false;
>
> //premaze lowbmp
> zeromemory(@lowpix[0],lowbmp.width*lowbmp.height*sizeof(dword));
>
> //v pix1 je ulozena aktualni mapa v pix2 stara podle niz se porovnava
> pix1:=pixels[whichBMP];
> pix2:=pixels[abs(whichBMP-1)];
>
> //urci startovni pozice x a y
> startx:=counter mod RectSize;
> starty:=trunc(counter/RectSize) mod RectSize;
>
> //prohleda zmeny v obrazku
> //nastavi y na pocatek
> y:=starty;
> while y<VideoHeight do
> begin
> //nastavi x na pocatek
> x:=startx;
> while x<VideoWidth do
> begin
> //zjisti jestli se na dotycnem miste nenachazi traywnd
> if GrabMode=GM_NOTRAYWND then
> if ptinrect(TrayWndRect,point(trunc(x*xscale),
> trunc((VideoHeight-y)*yscale))) then
> begin
> x:=x+RectSize;
> continue;
> end;
> //v ramci na hodnote counter systematicky prochazi obrazovku
> //pokud je steprect 8 a obraz se scanuje 4 krat za vterinu
> //je stredni doba nalezeni zmeny pixelu 8 vterin
> position:=y*VideoWidth+x;
> if(pix1[position]<>pix2[position]) then
> with LastResult do
> begin
> result:=true;
> //upravi minimalni obdelnik ve kterem doslo ke zmenam
> ChangeRect:=rect(min(ChangeRect.Left,x-RectSize),
> min(ChangeRect.Top,y-RectSize),
> max(ChangeRect.Right,x+RectSize),
> max(ChangeRect.Bottom,y+RectSize));
> //zmeni pixel v lowbmp
> //pozor x je ve skutecnosti x-1 nebot lowbmp je predsazena
> //lowpix[y*lowbmp.Width+x]:=$000000FF;
> //lowpix[y*lowbmp.Width+x+1]:=$000000FF;
> //lowpix[y*lowbmp.Width+x+2]:=$000000FF;
> //lowpix[(y+1)*lowbmp.Width+x+2]:=$000000FF;
> //lowpix[(y+2)*lowbmp.Width+x+2]:=$000000FF;
> end;
> //inkrementuje x
> x:=x+RectSize;
> end;
> //inkrementuje y
> y:=y+RectSize;
> end;
>
>
>
> //vysledny obdelnik je jeste treba upravit
> if LastResult.result then
> with LastResult do
> begin
> {//zameni souradnice tak aby byl pocatek vlevo nahore
>
> ChangeRect:=rect(VideoX+ChangeRect.Left,VideoY+VideoHeight-ChangeRect.Bottom,
>
> VideoX+ChangeRect.Right,VideoY+VideoHeight-ChangeRect.Top);
> //upravi obdelnik aby se vesel do vyrezu obrazku
> ChangeRect:=rect(max(ChangeRect.Left,VideoX),
> max(ChangeRect.Top,VideoY),
> min(ChangeRect.Right,VideoX+VideoWidth),
> min(ChangeRect.Bottom,VideoY+VideoHeight));}
>
> //zameni souradnice tak aby byl pocatek vlevo nahore
> ChangeRect:=rect(ChangeRect.Left,VideoHeight-ChangeRect.Bottom,
> ChangeRect.Right,VideoHeight-ChangeRect.Top);
> //upravi obdelnik aby se vesel do vyrezu obrazku
> ChangeRect:=rect(max(ChangeRect.Left,0),
> max(ChangeRect.Top,0),
> min(ChangeRect.Right,VideoWidth),
> min(ChangeRect.Bottom,VideoHeight));
> end;
> end;
>
>
>
>
> procedure TChangeRecognition.GrabAccept;
> begin
> //pokud je vysledek grab kladny je volana metoda grabaccept
> //ktera detekuje bitmapu jez se zmenila
> if LastResult.result then
> begin
> //zjisti velikost ResultBMP
> ResultBMP.width:=LastResult.ChangeRect.Right-LastResult.ChangeRect.Left;
>
> ResultBMP.Height:=LastResult.ChangeRect.Bottom-LastResult.ChangeRect.Top;
> //zjisti bitmapu vysledku
> bitblt(ResultBMP.Canvas.Handle,0,0,ResultBMP.Width,ResultBMP.Height,
> bmp[1].canvas.handle,
> LastResult.ChangeRect.Left,LastResult.ChangeRect.Top,srccopy);
> //ulozi zmenenou cast do bmp1
> bitblt(bmp[0].Canvas.Handle,
> LastResult.ChangeRect.Left,LastResult.ChangeRect.Top,
> ResultBMP.width,ResultBMP.height,
> ResultBMP.canvas.handle,0,0,srccopy);
> end;
> end;
>
>
>
>
>
> procedure TChangeRecognition.setVideoH(const Value: integer);
> begin
> fVideoH := min(screen.Height,Value);
> end;
>
>
>
>
> procedure TChangeRecognition.setVideoHeight(const Value: integer);
> var a:integer;
> begin
> //nastavi vysku videa
> fVideoHeight := min(screen.Height,max(Value,1));
> //zmeni rozliseni videa
> for a:=0 to high(bmp) do
> begin
> bmp[a].Height:=VideoHeight;
> pixels[a]:=bmp[a].ScanLine[bmp[a].height-1];
> //musi upravit i lowbmp
> lowbmp.Height:=trunc(bmp[0].Height/RectSize)+3;
> lowpix:=lowbmp.ScanLine[lowbmp.height-1];
> end;
> end;
>
>
>
>
> procedure TChangeRecognition.setVideoRect(ax, ay, aw, ah, destw, desth:
> integer);
> begin
> VideoX:=ax;
> VideoY:=ay;
> VideoW:=aw;
> VideoH:=ah;
> VideoWidth:=destw;
> VideoHeight:=desth;
> end;
>
>
>
> procedure TChangeRecognition.setVideoW(const Value: integer);
> begin
> fVideoW := min(screen.Width,Value);
> end;
>
>
>
>
> procedure TChangeRecognition.setVideoWidth(const Value: integer);
> var a:integer;
> begin
> //nastavi sirku videa
> fVideoWidth := min(screen.Width,max(Value,1));
> //zmeni rozliseni videa
> for a:=0 to high(bmp) do
> begin
> bmp[a].Width:=VideoWidth;
> pixels[a]:=bmp[a].ScanLine[bmp[a].height-1];
> //musi upravit i lowbmp
> lowbmp.Width:=trunc(bmp[0].Width/RectSize)+3;
> lowpix:=lowbmp.ScanLine[lowbmp.height-1];
> end;
> end;
>
>
>
>
> procedure TChangeRecognition.setVideoX(const Value: integer);
> begin
> fVideoX := max(Value,0);
> end;
>
>
>
>
> procedure TChangeRecognition.setVideoY(const Value: integer);
> begin
> fVideoY := max(Value,0);
> end;
>
> end.
>
> Interalab napsal(a):
>
>> Is the screengrabber application proprietary?
>>
>> [EMAIL PROTECTED] wrote:
>>
>>
>>> Hi.
>>>
>>> Im so sorry i forgot change "licence" paragraph text. But as you can see
>>> on my web pages http://www.cze.cz/?lang=en, the licence is GNU GPL.
>>>
>>> dabi du napsal(a):
>>>
>>>
>>>
>>>> Hi, very interesting work.
>>>>
>>>> Could you please explain about terms of use, you say
>>>> freeware open source but on your web site it says only
>>>> for noncommercial us. How is it going to be in the
>>>> future in terms of licesing.
>>>>
>>>> --- John Grden <[EMAIL PROTECTED]> wrote:
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>> wow, very impressive video - The screen capture, i"m
>>>>> sure, is going to get
>>>>> alot of people trying it out for sure. That was
>>>>> very cool to see.
>>>>>
>>>>> Nice work!
>>>>>
>>>>> On 4/15/07, [EMAIL PROTECTED] <[EMAIL PROTECTED]> wrote:
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>> **Breeze is freeware open source web application
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>> for chating, providing
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>> and recording web seminars.
>>>>>>
>>>>>> Download (Windows & Linux all in one)
>>>>>> Download from
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>> http://rapidshare.com/files/25850249/Breeze.exe
>>>>> (28118 KB)
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>> or http://mirror1.cze.cz/download/breeze.exe
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>> (28118 KB).
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>> Online video tutorial
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>> http://grafitchat.wz.cz/help.htm,
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>> http://mirror1.cze.cz/download/breezehelp.htm.
>>>>>>
>>>>>>
>>>>>> _______________________________________________
>>>>>> Red5 mailing list
>>>>>> [email protected]
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>> http://osflash.org/mailman/listinfo/red5_osflash.org
>>>>>
>>>>>
>>>>> --
>>>>> [ JPG ]
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>> _______________________________________________
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>> Red5 mailing list
>>>>> [email protected]
>>>>> http://osflash.org/mailman/listinfo/red5_osflash.org
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>> __________________________________________________
>>>> Do You Yahoo!?
>>>> Tired of spam? Yahoo! Mail has the best spam protection around
>>>> http://mail.yahoo.com
>>>>
>>>> _______________________________________________
>>>> Red5 mailing list
>>>> [email protected]
>>>> http://osflash.org/mailman/listinfo/red5_osflash.org
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>> _______________________________________________
>>> Red5 mailing list
>>> [email protected]
>>> http://osflash.org/mailman/listinfo/red5_osflash.org
>>>
>>>
>>>
>> _______________________________________________
>> Red5 mailing list
>> [email protected]
>> http://osflash.org/mailman/listinfo/red5_osflash.org
>>
>>
>>
>> __________ Informace od NOD32 2195 (20070416) __________
>>
>> Tato zprava byla proverena antivirovym systemem NOD32.
>> http://www.nod32.cz
>>
>>
>>
>>
>>
>
>
> _______________________________________________
> Red5 mailing list
> [email protected]
> http://osflash.org/mailman/listinfo/red5_osflash.org
>
_______________________________________________
Red5 mailing list
[email protected]
http://osflash.org/mailman/listinfo/red5_osflash.org