使用AVIStreamGetFrame获取一帧的图像,然后想进行图像处理,比如锐化等后使用DrawDibDraw绘到屏幕,但不知应怎样将绘好的图像放入缓冲中,请各位图像处理高手指教!

解决方案 »

  1.   

    流水你这小子还给我发消息 :(~~~这回丢人啦 哇哈哈哈哈转的 楼主看看,可能你本来就知道了function GetAviFrame(AviFilename : String; Index: Integer; var bmp: TBitmap): boolean;
    说明:
    avifilename: avi文件名
    index: 要取的桢号
    bmp: 存放返回图象, 如果为nil则自动建立一个bitmap. 如果存在则按bmp
            定义的大小存放stretch后的图象.
    返回值: true 成功, false 失败.代码:uses windows, graphics;interfaceconst
      streamtypeAUDIO : longint = $73647561;
      streamtypeVIDEO : longint = $73646976;type
      TAVIStream = record
        fccType    : longint;
        fccHandler : longint;
        dwFlags    : longint;
        dwCaps     : longint;
        wPriority  : word;
        wLanguage  : word;
        dwScale    : longint;
        dwRate     : longint;
        dwStart    : longint;
        dwLength   : longint;
        dwInitialFrames : longint;
        dwSuggestedBufferSize : longint;
        dwQuality    : longint;
        dwSampleSize : longint;
        rcFrame      : TRect;
        dwEditCount  : longint;
        dwFormatChangeCount : longint;
        Name : array [0..64] of char;
      end;  PAVIStream = ^TAVIStream;  PAVIFile = pointer;  TAVIFileInfo = record
        dwMaxBytesPerSec : longint;
        dwFlags          : longint;
        dwCaps           : longint;
        dwStreams        : longint;
        dwSuggestedBufferSize : longint;    dwWidth          : longint;
        dwHeight         : longint;    dwScale          : longint;
        dwRate           : longint;
        dwLength         : longint;    dwEditCount      : longint;    szFileType       : array[0..63] of char;
      end;  PAVIFileInfo = ^TAVIFileInfo;  TAVIStreamInfo = record
        fccType               : longint;
        fccHandler            : longint;
        dwFlags               : longint;
        dwCaps                : longint;
        wPriority             : word;
        wLanguage             : word;
        dwScale               : longint;
        dwRate                : longint;
        dwStart               : longint;
        dwLength              : longint;
        dwInitialFrames       : longint;
        dwSuggestedBufferSize : longint;
        dwQuality             : longint;
        dwSampleSize          : longint;
        rcFrame               : TRect;
        dwEditCount           : longint;
        dwFormatChangeCount   : longint;
        szName  : array[0..63] of char;
      end;  PAVIStreamInfo = ^TAVIStreamInfo;function  AVIFileOpen(avifile : pointer; filename : pchar; mode : integer;
                       CLSID : pointer) : integer; stdcall; external 'avifil32.dll' index 16;function  AVIFileRelease(avifile : pointer) : longint; stdcall; external 'avifil32.dll' index 20;function  AVIFileGetStream(avifile : pointer; avistream : PAVIStream;
                               streamtype : longint; lParam : longint) : integer; stdcall; external 'avifil32.dll' index 11;function  AVIStreamGetFrameOpen(avistream : PAVIStream; bitmapwanted : pointer) : pointer; stdcall; external 'avifil32.dll' index 42;procedure AVIStreamGetFrameClose(pget : pointer); stdcall; external 'avifil32.dll' index 41;function  AVIStreamGetFrame(getframe : pointer; position : longint) : pointer; stdcall; external 'avifil32.dll' index 40;procedure AVIStreamRelease(avistream : PAVIStream); stdcall; external 'avifil32.dll' index 53;function  AVIStreamInfo(pstream : PAVIStream; psi : PAVISTREAMINFO; lsize : longint) : integer; stdcall; external 'avifil32.dll' index 44;function GetAviFrame(AviFilename : String; Index: Integer; var bmp: TBitmap): boolean;implementationfunction GetAviFrame(AviFilename : String; Index: Integer; var bmp: TBitmap): boolean;
    var
      FAviFile : Pointer;
      FVideoStream : Pointer;
      FGetFrame : Pointer;
      info : TAVIStreamInfo;
      FFrameWidth, FFrameHeight : Integer;
      FStartFrame, FStopFrame : Integer;
      image : PBitmapInfoHeader;
      imagestart : Integer;
    begin
      result := false;
      if (AVIFileOpen(@favifile, pchar(AviFileName), 0, nil) <> 0) then
        exit;  if (AVIFileGetStream(favifile, @fvideostream, streamtypeVIDEO, 0) <> 0) then
      begin
          AVIFileRelease(favifile);
          exit;
      end;  AVIStreamInfo(fvideostream, @info, sizeof(info));
      with info do
      begin
          fFrameWidth := rcframe.right - rcframe.left;
          fFrameHeight := rcframe.bottom - rcframe.top;
          fStartFrame := dwStart;
          fStopFrame := dwLength - 1;
      end;  if (index <fstartframe) or (index > fstopframe) then
      begin
          AVIStreamRelease(fvideostream);
          AVIFileRelease(favifile);
          exit;
      end;  fgetframe := AVIStreamGetFrameOpen(fvideostream, nil);
      if (fgetframe = nil)  then
      begin
          AVIStreamRelease(fvideostream);
          AVIFileRelease(favifile);
          exit;
      end;  image := AVIStreamGetFrame(fgetframe, Index);
      if assigned(image) then
      begin
          if not assigned(bmp) then
          begin
            bmp := tbitmap.create;
            bmp.width := fframewidth;
            bmp.height := fframeheight;
          end
          else if bmp.empty then
          begin
             bmp.width := fframewidth;
             bmp.height := fframeheight;
          end;
          imagestart := image^.biSize + image^.biClrUsed * 4;
          StretchDIBits(bmp.canvas.handle, 0, 0, bmp.width, bmp.height,
                           0, 0, fframewidth, fframeheight,
                           pchar(image) + imagestart,
                           TBitmapInfo(image^), 0, SRCCOPY);
          result := true;
      end;  AVIStreamGetFrameClose(fgetframe);
      AVIStreamRelease(fvideostream);
      AVIFileRelease(favifile);
    end;end.
      

  2.   

    可能 回复人: CDSoftwareWj(95927) ( ) 信誉:107  说的就可以了
    呕也没涉及过这方面,抱歉————————————————————————————————————
    宠辱不惊,看庭前花开花落,去留无意;毁誉由人,望天上云卷云舒,聚散任风。
    ————————————————————————————————————
      

  3.   

    不必被这段代码迷惑,楼主看看有没有什么用,这是从一个不知道是哪个国家的网站弄的,好像是俄罗斯,我没看懂它的注释部分var AviFile: PAVIStream;
        p:Pointer;
        p2:^TBitmap;
        RV:dword;
        FName='c:\video.avi';
    begin
    AVIFileInit;
    if not FileExists(FName) then ErrorOut('File not FOUND!!!');
    RV:=AVIStreamOpenFromFile(AviFile,PChar(FName),streamtypeVIDE
    O,0,OF_READ,nil);
    if RV<>0 then ErrorOut('Cannot open file');
    RV:=null;
    p2:=AVIStreamGetFrameOpen(AviFile,nil);
    if p=nil then ErrorOut('Cannot prepare frame');
    p2:=AVIStreamGetFrame(p,10000);
    p3.SaveToFile('c:\video.bmp');
      

  4.   

    兄弟们先谢谢了,这写代码我都懂,可惜不是我要的,其实我已弄出来了兄弟们可以看看,研究一下:
    procedure FrameToBitmap(Bitmap: TBitmap; FrameBuffer: pointer; BitmapInfo: TBitmapInfo);
    procedure BitmapToFrame(Bitmap: TBitmap; Out Memory: Pointer);
    procedure SaveBuffToFile(Image:Pointer; FileName:String);implementationuses DrawDib;Const
        BufferFrame=1;
    Type
        TBufferThread=class(TThread)
        private
            Player:TDCAVIPlayer;
            AviOpen:Pointer;
            List:TList;
            FrameIndex:Integer;
            FrameCount:Integer;
            Bmp:TBitmap;
            Function SaveOneFrame(Index:Integer):Boolean;
            procedure Close(Sender:TObject);
        protected
            procedure Execute; override;    public
            Constructor Create(sPlayer:TDCAVIPlayer; sAviOpen:Pointer; sList:TList);
        end;
    Var
        Lock:TCriticalSection;
    procedure ClearList(List:TList);
    Var
        i:Integer;
    begin
        Lock.Acquire;
        Try
            For i:=List.Count-1 downto 0 do
            begin
                Dispose(List.Items[i]);
                List.Delete(i); 
            end;
        Finally
            Lock.Release;
        end;
    end;procedure AddListItem(Pi:Pointer; List:TList);
    begin
        Lock.Acquire;
        Try
            List.Add(Pi);
        Finally
            Lock.Release;
        end;
    end;Function GetListItem(List:TList):Pointer;
    begin
        Lock.Acquire;
        Try
            if List.Count>0 then
            begin
                Result:=List.Items[0];
                List.Delete(0); 
            end
            else
                Result:=nil;
        Finally
            Lock.Release;
        end;
    end;procedure FrameToBitmap(Bitmap: TBitmap; FrameBuffer: pointer; BitmapInfo: TBitmapInfo);
    begin
      with Bitmap do
      begin
        Width := BitmapInfo.bmiHeader.biWidth;      // New size of Bitmap
        Height := Bitmapinfo.bmiHeader.biHeight;
        setDiBits(canvas.handle, handle, 0, BitmapInfo.bmiHeader.biheight,
                  FrameBuffer, BitmapInfo, DIB_RGB_COLORS);
      end;
    end;procedure BitmapToFrame(Bitmap: TBitmap; Out Memory: Pointer);
    Var
        FrameBuffer:Pointer;
        BitmapInfo:TBitmapInfo;
        p:PChar;
        OldPi:Pointer;
        Result:Integer;
        Hd:THandle;
    begin
      Memory:=nil;
      with Bitmap do
      begin
          FrameBuffer:=AllocMem(Bitmap.Height * Bitmap.Width * 4);
          with BitmapInfo.bmiHeader do
          begin
              biSize := SizeOf(TBITMAPINFOHEADER);
              biWidth := Bitmap.Width;
              biHeight := Bitmap.Height;
              biPlanes := 1;
              biBitCount := 32;
              biCompression := 0;
              biSizeimage := Bitmap.Height * Bitmap.Width * 4;
              biXPelsPerMeter := 1;
              biYPelsPerMeter := 1;
              biClrUsed := 0;
              biClrImportant := 0;
          end;
        Hd:=Bitmap.Handle;
        Result:=GetDiBits(GetDC(0), Hd, 0, Bitmap.Height,
                  FrameBuffer, BitmapInfo, DIB_RGB_COLORS);
        if Result<=0 then
        begin
            Exit;
        end;
        p:=PChar(BitmapInfo.bmiColors);
        Memory:=AllocMem(SizeOf(TBitmapInfoHeader)+BitmapInfo.bmiHeader.biClrUsed*4+BitmapInfo.bmiHeader.biSizeImage);
        OldPi:=Memory;
        Move(BitmapInfo.bmiHeader,PChar(Memory)^,SizeOf(TBitmapInfoHeader));
        Inc(PChar(Memory),SizeOf(TBitmapInfoHeader));
        Move(p^,PChar(Memory)^,BitmapInfo.bmiHeader.biClrUsed*4);
        Inc(PChar(Memory),BitmapInfo.bmiHeader.biClrUsed*4);
        Move(PChar(Framebuffer)^,PChar(Memory)^,BitmapInfo.bmiHeader.biSizeImage);
        Memory:=OldPi;
      end;
    end;procedure SaveBuffToFile(Image:Pointer; FileName:String);
    Var
        ImageStart:Integer;
        p:PChar;
        Bmp:TBitmap;
    begin
        Bmp:=TBitmap.Create;
        Try
            imagestart := TBitmapInfoHeader(image^).biSize + TBitmapInfoHeader(image^).biClrUsed * 4;
            P:=PChar(Image)+ImageStart;
            FrameToBitmap(Bmp,P,TBitmapInfo(Image^));
            Bmp.SaveToFile(FileName);
        Finally
            Bmp.Free; 
        end;
    end;procedure TBufferThread.Close(Sender: TObject);
    begin
        Bmp.Free;
    end;constructor TBufferThread.Create(sPlayer: TDCAVIPlayer; sAviOpen: Pointer; sList:TList);
    Var
        Count,i:Integer;
    begin
        Inherited Create(true);
        Bmp:=TBitmap.Create;
        FrameCount:=0;
        Self.FreeOnTerminate:=true;
        Self.OnTerminate:=Close;
        Player:=sPlayer;
        AviOpen:=sAviOpen;
        List:=sList;
        Count:=Player.fStartFrame+((Player.fStopFrame-Player.fStartFrame) div Player.fdelay)*BufferFrame;
        FrameIndex:=Count+1;
        For i:=Player.fStartFrame to Count do
        begin
            if i<=Player.fStopFrame then
                SaveOneFrame(i)
            else
            begin
                Self.Terminate;
                break;
            end;
        end;    Self.Resume;
    end;procedure TBufferThread.Execute;
    Var
        i:Integer;
    begin
        For i:=FrameIndex to Player.fStopFrame do
        begin
            if Self.Terminated then
                break;
            SaveOneFrame(i);
            Sleep(Player.fdelay);
        end;
    end;function TBufferThread.SaveOneFrame(Index: Integer): Boolean;
    Var
        Image:Pointer;
        ImageStart:Integer;
        p:Pointer;
        Buff:Pointer;
    begin
        Try
            image:=AVIStreamGetFrame(AviOpen, Index);
            imagestart := TBitmapInfoHeader(image^).biSize + TBitmapInfoHeader(image^).biClrUsed * 4;
            P:=PChar(Image)+ImageStart;
            FrameToBitmap(Bmp,P,TBitmapInfo(Image^));
            if Assigned(Player.ComposeProc) then
                Player.ComposeProc(Player,Bmp);        BitmapToFrame(Bmp,Buff);
            AddListItem(Buff,List);
            if Index=100 then
                SaveBuffToFile(Buff,'c:\b.bmp');
        Except
            On E:Exception do
                ShowMessage(E.Message);
        end;
    end;
      

  5.   

    已以可以取出每一帧的图像了么?
    如果要追求效率,建议使用DirectDraw吧,建二个页面对象.在后台处理完一帧直接换页就可以了.但如果不用全屏独占模式的话就不能用双缓冲了..
      

  6.   

    偶对这个不是很明白,希望下面的程序对你有所帮助(AVI抓图并保存图像,源程序程序来自torry,有些问题,我已经改过了,不过还是有些小的错误,楼主自己解决吧)
    记得去delphi-jedi下载vfw.pas;
    uses 
     VfW ;function GrabAVIFrame(avifn: string; iFrameNumber: Integer; ToFileName: TFileName): Boolean;
    var 
      Error: Integer; 
      pFile: IAVIFile;
      AVIStream: IAVIStream;
      gapgf: IGETFRAME;
      lpbi: PBITMAPINFOHEADER;
      bits: PChar;
      hBmp: HBITMAP; 
      AviInfo: TAVIFILEINFO; 
      sError: string; 
      TmpBmp: TBitmap; 
      DC_Handle: HDC;
    begin 
      Result := False; 
      // Initialize the AVIFile library.
      AVIFileInit;  // The AVIFileOpen function opens an AVI file 
      Error := AVIFileOpen(pFile, PChar(avifn), 0, nil); 
      if Error <> 0 then 
      begin 
        AVIFileExit; 
        case Error of
          AVIERR_BADFORMAT: sError := 'The file couldn''t be read'; 
          AVIERR_MEMORY: sError := 'The file could not be opened because of insufficient memory.'; 
          AVIERR_FILEREAD: sError := 'A disk error occurred while reading the file.'; 
          AVIERR_FILEOPEN: sError := 'A disk error occurred while opening the file.'; 
        end; 
        ShowMessage(sError); 
        Exit; 
      end;   // AVIFileInfo obtains information about an AVI file 
      if AVIFileInfo(pFile, AviInfo,SizeOf(AVIINFO)) <> AVIERR_OK then
      begin 
        // Clean up and exit 
        AVIFileRelease(pFile); 
        AVIFileExit; 
        Exit; 
      end;   // Show some information about the AVI 
      Form1.Memo1.Lines.Add('AVI Width : ' + IntToStr(AVIINFO.dwWidth)); 
      Form1.Memo1.Lines.Add('AVI Height : ' + IntToStr(AVIINFO.dwHeight)); 
      Form1.Memo1.Lines.Add('AVI Length : ' + IntToStr(AVIINFO.dwLength));   // Open a Stream from the file 
      Error := AVIFileGetStream(pFile, AVIStream, streamtypeVIDEO, 0); 
      if Error <> AVIERR_OK then 
      begin 
        // Clean up and exit 
        AVIFileRelease(pFile);
        AVIFileExit; 
        Exit; 
      end;   // Prepares to decompress video frames 
      gapgf := AVIStreamGetFrameOpen(AVIStream, nil);
      if gapgf = nil then 
      begin 
        AVIStreamRelease(AVIStream); 
        AVIFileRelease(pFile); 
        AVIFileExit;
        Exit; 
      end;   // Read current Frame 
      // AVIStreamGetFrame Returns the address of a decompressed video frame 
      lpbi := AVIStreamGetFrame(gapgf, iFrameNumber); 
      if lpbi = nil then 
      begin 
        AVIStreamGetFrameClose(gapgf); 
        AVIStreamRelease(AVIStream); 
        AVIFileRelease(pFile);
        AVIFileExit; 
        Exit; 
      end;   // Show number of frames: 
      Form1.Memo1.Lines.Add(Format('Framstart: %d FrameEnd: %d', 
        [AVIStreamStart(AVIStream), AVIStreamEnd(AVIStream)]));   TmpBmp := TBitmap.Create; 
      try 
        TmpBmp.Height := lpbi.biHeight;
        TmpBmp.Width  := lpbi.biWidth; 
        bits := Pointer(Integer(lpbi) + SizeOf(TBITMAPINFOHEADER));     DC_Handle := CreateDC('Display', nil, nil, nil); 
        try 
          hBmp := CreateDIBitmap(DC_Handle, // handle of device context 
            lpbi^, // address of bitmap size and format data 
            CBM_INIT, // initialization flag 
            bits, // address of initialization data 
            PBITMAPINFO(lpbi)^, // address of bitmap color-format data 
            DIB_RGB_COLORS); // color-data usage
        finally 
          DeleteDC(DC_Handle); 
        end;     TmpBmp.Handle := hBmp; 
        AVIStreamGetFrameClose(gapgf); 
        AVIStreamRelease(AVIStream); 
        AVIFileRelease(pfile); 
        AVIFileExit; 
        try 
          TmpBmp.SaveToFile(ToFileName);
          Result := True; 
        except
        end;
      finally
        TmpBmp.Free;
      end;
    end;
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      // Extract Frame 3 from AVI file
      GrabAVIFrame('C:\Clock.avi', 0, 'c:\Clock.bmp');
    end;
      

  7.   

    我不是要抓图,其实是对AVI图像进行运行期图像合成,同时考虑到显示间隔比较短所以使用
    SETTIMEEVENT定时、使用DRAWDIDRAW绘显存。
      

  8.   

    哪还有什么问题啊?DirectDraw的问题?
      

  9.   

    昨天看了几篇相关的文章和MSDN
    DrawDibBegin最后一个参数wFlags  如果为DDF_BUFFER就可以借用屏幕缓冲区
    随后调用DrawDibDraw的时候wFlags可以设置为DDF_UPDATE
    两个函数中的lpbi参数就是指向保存图像的缓冲区呵呵,胡诌:),期待正确答案
    友情up
      

  10.   

    以上的代码有内存泄露问题,但已解决,不过AVI的播放还是不够适时,请大家继续讨论,我使用的是setTimeEvent函数定时.