⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mainframe.cpp

📁 BCAM 1394 Driver
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//-----------------------------------------------------------------------------
//  (c) 2002 by Basler Vision Technologies
//  Section:  Vision Components
//  Project:  BCAM
//  $Header: MainFrame.cpp, 7, 26.09.2002 18:37:40, Nebelung, H.$
//-----------------------------------------------------------------------------
/**
  \file     MainFrame.cpp
  \brief    Implementation of the CMainFrame class.
*/

#include "stdafx.h"

#include <float.h>
#include <math.h>
#include <vfw.h>
#include "resource.h"
#include "MainFrame.h"
#include <BvcDib.h>

//! The frame rate as stored in the AVI file = RATE / SCALE
const int RATE = 30;

//! The frame rate as stored in the AVI file = RATE / SCALE
const int SCALE = 1;

//! Number of Delta frames per key frame
/*! Delta frames contain only differences to the previous frames.
Key frames are stored fully and serve as re-synchronization point
Storing delta frames shrinks the file size and costs computing power
In addition single-stepping backwards does take pretty long.

  If #DELTA_FRAMES_PER_KEY_FRAME == 0 alle frames are stored
  as key frames. 
*/
const int DELTA_FRAMES_PER_KEY_FRAME = 0;

//! Number of frames which will be stored at maximum
const unsigned long MAX_NUM_FRAMES = 200;

//! Stores an additional text stream including a time stamp 
const bool STORE_TEXT_STREAM = true;

//! Number of characters in the comment attached to each frame
const int TEXT_SIZE = 25;

//! Hight of the comment as shown in the AVI file
const int TEXT_HEIGHT = 20;

//! Topple image before saving so they are bottom up instead of top down. 
/*! Most compression implementations and also some AVI viewers cannot deal with 
top down images. On the other hand doe toppeling make things slower
*/
const bool TOPPLE_IMAGE = true;

//! Show a list box and let the user choose a compression format
/*! This option is available only if #TOPPLE_IMAGE == true
*/
const bool COMPRESS_IMAGE = true;

//! Pre-allocates the avi file
/*! Since the compression factor is unknown this daoe not make sense
together with #COMPRESS_IMAGE == true
*/
const bool PRE_ALLOCATE_FILE = false;


/*!
Creates the window and initializes all GUI objects.
*/
LRESULT CMainFrame::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
  try
  {
    // create command bar window
    HWND hWndCmdBar = m_CmdBar.Create(m_hWnd, rcDefault, NULL, ATL_SIMPLE_CMDBAR_PANE_STYLE);
    // attach menu
    m_CmdBar.AttachMenu(GetMenu());
    // load command bar images
    m_CmdBar.LoadImages(IDR_MAINFRAME);
    // remove old menu
    SetMenu(NULL);
    
    HWND hWndToolBar = CreateSimpleToolBarCtrl(m_hWnd, IDR_MAINFRAME, FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE);
    
    CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);
    AddSimpleReBarBand(hWndCmdBar);
    AddSimpleReBarBand(hWndToolBar, NULL, TRUE);
    
    // Create Status Bar
    CreateSimpleStatusBar("");
    m_StatusBar.SubclassWindow(m_hWndStatusBar);
    int arrParts[] =
    {
      ID_STATUS_PANE,
        ID_DEFAULT_PANE,
        ID_FRAME_COUNTER_PANE,
        ID_FPS_PANE
    };
    m_StatusBar.SetPanes(arrParts, sizeof(arrParts) / sizeof(int), false);
    CString StatusPaneText;
    StatusPaneText.LoadString(ID_STATUS_PANE);
    m_StatusBar.SetPaneText(ID_STATUS_PANE, (LPCSTR)StatusPaneText);
    
    // create view window
    m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, WS_EX_CLIENTEDGE);
    m_view.ReleaseBitmap();
    
    UIAddToolBar(hWndToolBar);
    UISetCheck(ID_VIEW_TOOLBAR, 1);
    UISetCheck(ID_VIEW_STATUS_BAR, 1);
    
    // register object for message filtering and idle updates
    CMessageLoop* pLoop = _Module.GetMessageLoop();
    ATLASSERT(pLoop != NULL);
    pLoop->AddMessageFilter(this);
    pLoop->AddIdleHandler(this);
    
  }
  CATCH_MSGBOX( "CMainFrame::OnCreate" )  
    
    return 0;
}


/*!
Called it the user wants to start a live grab. 
Opens the driver, initilizes the camera and enqueues #NUM_BUFFERS grab commands.
When the grab commands are finished they turn up in the #GrabThreadProc.
*/
LRESULT CMainFrame::OnGrabLive(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
  
  try
  {
    // Check for a camera
    if(CBcam::DeviceNames().size() == 0)
    {
      MessageBox("No camera present", _T("Error"), MB_OK | MB_ICONEXCLAMATION);
      return 0;
    }
    
    // ask the user for a filename
    CFileDialog dlg(FALSE, _T("avi"), m_AviFilename, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, _T("AVI Files (*.avi)\0*.avi\0All Files (*.*)\0*.*\0"), m_hWnd);
    if(dlg.DoModal() == IDOK)
    {
      m_AviFilename = dlg.m_szFileName;
    }
    
    // Show the filename in the caption framecounter
    CString Buffer;
    Buffer.Format("StoreAVI - %s", m_AviFilename);
    SetWindowText(Buffer);
    
    // Get the devicename of the first camera
    CString DeviceName = *(CBcam::DeviceNames().begin());
    ATLTRACE(_T("Devicename = %s\n"), DeviceName);
    
    // Open the driver
    m_Bcam.Open( DeviceName );
    
    // Parameter set for the fastest monochrome format (valid assumption anly for Basler cameras)
    const DCSVideoFormat VideoFormat = DCS_Format7;
    const DCSVideoMode VideoMode     = DCS_Mode0;
    const DCSColorCode ColorCode     = DCSColor_Mono8;
    m_Bcam.SetVideoMode(VideoFormat, VideoMode);
    m_Bcam.FormatSeven[VideoMode].ColorCoding = ColorCode;
    
    // Check if the camera sends Bayer8 data instead of Mono8
    m_IsBayerImage = false;
    // Is it a Basler camera? - Check the vendor_id
    CString NodeID = m_Bcam.Info.NodeId();
    if(NodeID.Find("0x003053") == 0)
    {
      // Is it a color camera? - check for the letter 'c' in the modelname
      CString ModelName = m_Bcam.Info.ModelName();
      if(ModelName.Find("c") >= 0)
        m_IsBayerImage = true;
    }
    
    // Set Area Of Interest to maximum
    CSize ImageSize = m_Bcam.FormatSeven[VideoMode].MaxSize();
    ImageSize.cx = ImageSize.cx & ~3; // Beware : Windows Bitmaps have to have a DWORD alligned width :-(
    CPoint AoiPosition(0,0);
    CSize AoiSize(ImageSize);
    m_Bcam.FormatSeven[VideoMode].Position = AoiPosition;
    m_Bcam.FormatSeven[VideoMode].Size = AoiSize;
    
    // Set full speed
    unsigned long BytePerPacketMax = m_Bcam.FormatSeven[VideoMode].BytePerPacket.Max();
    m_Bcam.FormatSeven[VideoMode].BytePerPacket = BytePerPacketMax;
    
    // Create suitable bitmaps
    for(int i=0; i<NUM_BUFFERS; ++i)
      m_ptrBitmaps[i].Create(AoiSize, 8, CDib::TopDown, CDib::Monochrome);
    
    // Allocate Resources 
    m_Bcam.AllocateResources(NUM_BUFFERS, AoiSize.cx * AoiSize.cy );
    
    // Start the grab thread
    if ( ! m_GrabThread.Create(&GrabThreadProc, this, THREAD_PRIORITY_HIGHEST) )
    {
      throw  BcamException(::GetLastError(), "CMainFrame::OnGrabLive : Create Grab Thread");
    }
    
    // reset the frame counter
    m_FrameCounter = 0;
    
    // Indicate that we're grabbing live now
    m_LiveGrabbing = true;
    
    m_StopWatch.Start();
    
    // Enqueue Grab commands 
    for(i=0; i<NUM_BUFFERS; ++i)
    {
      m_Bcam.GrabImageAsync((char*)m_ptrBitmaps[i]->GetPixels(), AoiSize.cx * AoiSize.cy, (void*)i, USE_ONESHOT);  
    }
    
    // Switch on the camera (in case we're using ContinuousShot)
    if(!USE_ONESHOT)
      m_Bcam.ContinuousShot = true;
    
  } 
  CATCH_MSGBOX( "CMainFrame::OnGrabLive" );
    
  return 0;
}

/*!
Waits on the completion port for finished commands to show up.
- In case of a a finished grab command a #WM_GRAB_FINISHED message is send to the GUI thread
causing the #OnGrabFinished method to be fired.
- In case a #NotifyQuit message turns up a #WM_GRAB_STOPPED message is send to the GUI thread
causing the #OnGrabStopped method to be fired.
- If an error occurs a #WM_ERROR message is send to the GUI thread
causing the #OnError method to be fired.
*/
DWORD CMainFrame::GrabThreadProc(void* pParameter)
{
  CMainFrame* This = (CMainFrame*) pParameter;  // instance pointer
  
  // Handle for the AVI file
  PAVIFILE hAviFile = NULL;
  
  // Handle for the raw video stream
  PAVISTREAM hVideoStream = NULL;
  
  // Handle for the raw video stream
  PAVISTREAM hTextStream = NULL;
  
  // Buffer to hold the toppled image in case this is required
  CDibPtr ptrToppledImage;
  
  try
  {
    // Initilaize the operating system's AVI support
    // Use explicit CoInitilize to force the thread in the MTA
    HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED);
    if (hr != AVIERR_OK)
      throw BcamException(hr, "CMainFrame::GrabThreadProc");
    AVIFileInit();
    
    /**************************************/
    
    // Open an AVI file to store the video
    
    // For some reason AVIFileOpen will not shrink the file even with OF_CREATE set
    ::DeleteFile( (LPCTSTR)This->m_AviFilename );
    
    hr = AVIFileOpen(
      &hAviFile,
      (LPCTSTR)This->m_AviFilename,
      OF_WRITE | OF_CREATE,       
      NULL);  // use handler determined from file extension....
    if (hr != AVIERR_OK)
      throw BcamException(hr, "CMainFrame::GrabThreadProc");
    
    /**************************************/
    
    // Create a raw video stream in the file
    AVISTREAMINFO StreamInfo;
    ::ZeroMemory(&StreamInfo, sizeof(StreamInfo));
    StreamInfo.fccType                = streamtypeVIDEO;    // stream type
    StreamInfo.fccHandler             = 0;                                  // No compressor
    StreamInfo.dwScale                = SCALE;                                       
    StreamInfo.dwRate                 = RATE;                       
    
    // compressing the image and pre-allocating for (uncompressed) video data does
    // not make sense
    assert(!PRE_ALLOCATE_FILE || (PRE_ALLOCATE_FILE && !COMPRESS_IMAGE));
    if(PRE_ALLOCATE_FILE)
    {
      StreamInfo.dwSuggestedBufferSize  = MAX_NUM_FRAMES * This->m_ptrBitmaps[0]->GetTotalPixelBytes();
      StreamInfo.dwSampleSize = This->m_ptrBitmaps[0]->GetTotalPixelBytes();
    }
    SetRect(&StreamInfo.rcFrame, 0, 0,                                              // rectangle for stream
      (int) This->m_ptrBitmaps[0]->GetSize().cx,
      (int) This->m_ptrBitmaps[0]->GetSize().cy);
    
    hr = AVIFileCreateStream(hAviFile,  // file pointer
      &hVideoStream,     // returned stream pointer
      &StreamInfo);      // stream header
    if (hr != AVIERR_OK) 
      throw BcamException(hr, "CMainFrame::GrabThreadProc");
    
    /**************************************/
    
    // Make a compressed stream from the raw stream
    
    // Most compressors don't like top down images :-)
    assert(!COMPRESS_IMAGE || (COMPRESS_IMAGE && TOPPLE_IMAGE));
    if(COMPRESS_IMAGE && TOPPLE_IMAGE)
    {
      // Handle for the raw video stream
      PAVISTREAM hCompressedVideoStream = NULL;
      
      AVICOMPRESSOPTIONS CompressionOptions;
      AVICOMPRESSOPTIONS FAR * pCompressionOptions[1] = {&CompressionOptions};
      ::ZeroMemory(&CompressionOptions, sizeof(CompressionOptions));
      
      // Let the user choose the compression format (this will show a message box!)
      if (!AVISaveOptions(NULL, 0, 1, &hVideoStream, (LPAVICOMPRESSOPTIONS FAR *) &pCompressionOptions))
        throw BcamException(E_FAIL, "CMainFrame::GrabThreadProc");
      
      hr = AVIMakeCompressedStream(
        &hCompressedVideoStream, 
        hVideoStream, 
        &CompressionOptions, 
        NULL);
      if (hr != AVIERR_OK) 
        throw BcamException(hr, "CMainFrame::GrabThreadProc");
      
      // We need only the handle of the compressed stream so close the handle 
      // of the raw stream
      AVIStreamClose(hVideoStream);
      hVideoStream = hCompressedVideoStream;
    }
    
    /**************************************/
    
    // Set the stream format (= the format of the DIBs)
    unsigned long BitmapInfoBytes;
    BITMAPINFO *pBitmapInfo;
    This->m_ptrBitmaps[0]->GetBitmapInfo(&pBitmapInfo, &BitmapInfoBytes);
    
    // See TopDown discussion in the CDib class' header
    if(!TOPPLE_IMAGE && (This->m_ptrBitmaps[0]->GetOrientation() == CDib::TopDown))
    {
      pBitmapInfo->bmiHeader.biHeight = -pBitmapInfo->bmiHeader.biHeight;
    }
    else
    {
      ptrToppledImage = This->m_ptrBitmaps[0]->Clone(true);  // Topple
    }
    
    hr = AVIStreamSetFormat(hVideoStream, 0,
      pBitmapInfo,   
      BitmapInfoBytes);
    free(pBitmapInfo);
    if (hr != AVIERR_OK) 
      throw BcamException(hr, "CMainFrame::GrabThreadProc");
    
    
    /**************************************/
    
    // Create an additional text stream for comments
    // The MS Media Player V6.4 will show that
    if(STORE_TEXT_STREAM)
    {
      ::ZeroMemory(&StreamInfo, sizeof(StreamInfo));
      StreamInfo.fccType                = streamtypeTEXT;
      StreamInfo.fccHandler             = mmioFOURCC('D', 'R', 'A', 'W');
      StreamInfo.dwScale                = SCALE;                                       
      StreamInfo.dwRate                 = RATE;                       
      StreamInfo.dwSuggestedBufferSize  = TEXT_SIZE;
      SetRect(&StreamInfo.rcFrame, 0, (int) This->m_ptrBitmaps[0]->GetSize().cy,
        (int) This->m_ptrBitmaps[0]->GetSize().cx,
        (int) This->m_ptrBitmaps[0]->GetSize().cy + TEXT_HEIGHT);
      
      hr = AVIFileCreateStream(hAviFile, &hTextStream, &StreamInfo);
      if (hr != AVIERR_OK) 
        throw BcamException(hr, "CMainFrame::GrabThreadProc");
      
      DWORD TextFormat;
      TextFormat = sizeof(TextFormat);
      hr = AVIStreamSetFormat(hTextStream, 0, &TextFormat, sizeof(TextFormat));
      if (hr != AVIERR_OK) 
        throw BcamException(hr, "CMainFrame::GrabThreadProc");
    }
    
    /**************************************/
    
    // Wait for images and process them
    unsigned long RunningIndex = 0;
    for(;;)
    {
      FunctionCode_t FunctionCode;
      unsigned long ErrorCode;
      void *pContext;
      
      // Wait for things to show up at the driver's completion port
      This->m_Bcam.WaitForCompletion(&FunctionCode, &ErrorCode, &pContext, INFINITE); 
      
      if(ErrorCode)
        throw BcamException(ErrorCode, "CMainFrame::GrabThreadProc");
      
      switch(FunctionCode)
      {
      case AsyncGrabImage:
        {
          // Stop the watch and restart it again immediately
          float ElapsedTime = (float)This->m_StopWatch.Stop(true);
          
          // Identify the image
          unsigned int BufferIndex = *(unsigned int*)&pContext;
          
          // Make sure only MAX_NUM_FRAMES are stored (for the sake of your hard disk :-)
          if(RunningIndex < MAX_NUM_FRAMES)
          {
            
            LPBYTE pSrc = (unsigned char*)This->m_ptrBitmaps[BufferIndex]->GetPixels();             
            LPBYTE pDst = pSrc;             
            if(TOPPLE_IMAGE && (This->m_ptrBitmaps[0]->GetOrientation() == CDib::TopDown))
            {
              // Topple the data only without telling the image 
              // thus don't use CDib's topple method 
              
              CSize ImageSize;
              This->m_ptrBitmaps[0]->GetSize(&ImageSize);
              DWORD WidthBytes = This->m_ptrBitmaps[0]->GetWidthBytes();
              pDst = (unsigned char*)ptrToppledImage->GetPixels();
              for( int i = 0, m = abs(ImageSize.cy) - 1;  i < abs(ImageSize.cy); i++, m-- )
              {
                memcpy(pDst + m * WidthBytes, pSrc + i * WidthBytes, WidthBytes);
              }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -