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

Reply via email to