1. 程式人生 > >回撥函式處理影象(待整理)

回撥函式處理影象(待整理)

回撥函式是將就是通過函式指標呼叫函式,即將該引數傳遞給其他函式,在呼叫該引數時候也自動呼叫該引數。

#include <iostream>
#include <conio.h>

#include <tisudshl.h>

#include "CmdHelper.h"
#include "Listener.h"

using namespace _DSHOWLIB_NAMESPACE;

// Specify the number of buffers to be used.
////巨集定義
#define NUM_BUFFERS 10

int main(int argc, char* argv[])
{
     ///初始化相機控制元件的類庫
	DShowLib::InitLibrary();
    ///註冊程式正常退出時候需要的呼叫的函式
	atexit( ExitLibrary );
    ///建立採集物件
	Grabber grabber;

	// Create the GrabberListener object.
	// CListener is derived from GrabberListener.
	
	///new CListener()被賦值給指標,在後面呼叫該函式的時候就會呼叫該指標
	CListener *pListener = new CListener();
												
	if( !setupDeviceFromFile( grabber ) )
	{
		return -1;
	}
	
	// Assign the number of buffers to the cListener object.
	pListener->setBufferSize( NUM_BUFFERS );

	// Enable the overlay bitmap to display the frame counter in the live video.
       /////建立幀數視窗
	grabber.getOverlay()->setEnable( true );

	// Register the pListener object for the frame ready and 
	// the overlay callback event.
	//建立一個listener 物件
	grabber.addListener( pListener, GrabberListener::eFRAMEREADY|
										GrabberListener::eOVERLAYCALLBACK );


	// Create a FrameTypeInfoArray data structure describing the allowed color formats.
	///建立一個數據結構用來表示影象的格式
	FrameTypeInfoArray acceptedTypes = FrameTypeInfoArray::createRGBArray();

	// Create the frame handler sink
      // 建立幀儲存
	smart_ptr<FrameHandlerSink> pSink = FrameHandlerSink::create( acceptedTypes, NUM_BUFFERS );

	// enable snap mode (formerly tFrameGrabberMode::eSNAP).

	pSink->setSnapMode( true );

	// Apply the sink to the grabber.
	grabber.setSinkType( pSink );

	grabber.startLive();				// Start the grabber.

	pSink->snapImages( NUM_BUFFERS );	// Grab NUM_BUFFERS images.

	grabber.stopLive();					// Stop the grabber.
	
	// Save the buffers for which CListener::frameReady() has not been called.
	// Since CListener::frameReady() calls Sleep(250), it cannot be called for
	// every buffer. Nevertheless, all buffers are copied to the MemBufferCollection.
	for( size_t i = 0; i < pListener->m_BufferWritten.size(); i++ )
	{
		if( !pListener->m_BufferWritten[i] )
		{
			std::cout << "Buffer " << i << " processed in main()." << std::endl;
			pListener->saveImage( pSink->getMemBufferCollection()->getBuffer( i ), i);
		}
	}
	// The CListener object must be unregistered for all events
	// before it may be destroyed.
	grabber.removeListener( pListener );

	// Now, it must be checked whether the CListener object has been unregistered
	// for all events.
	while( grabber.isListenerRegistered( pListener ) )
	{
		Sleep( 0 ); // Wait and give pending callbacks a chance to complete.
	}

	// Now, the application can be sure that no callback methods of pListener
	// will be called anymore. It is now safe to delete pListener.
	delete pListener;

	std::cout << "Press any key to continue!" << std::endl;
	std::cin.get();
	return 0;
}

listener.h

#include <tisudshl.h>

class CListener : public DShowLib::GrabberListener  
{
public:
	// Overwrite the GrabberListener methods we need
	////在子類中過載父類方法
	virtual void overlayCallback( DShowLib::Grabber& caller, smart_ptr<DShowLib::OverlayBitmap> pBitmap, const DShowLib::tsMediaSampleDesc& MediaSampleDesc ); 
	////
	virtual void frameReady( DShowLib::Grabber& caller, smart_ptr<DShowLib::MemBuffer> pBuffer, DWORD FrameNumber ); 

	// Save one image and mark it as saved
///c儲存一副影象,同時標記這福影象已經儲存
	void		saveImage( smart_ptr<DShowLib::MemBuffer> pBuffer, DWORD currFrame );
	// Setup the buffersize. 
	///計數
	void		setBufferSize( unsigned long NumBuffers );

	std::vector<bool>	m_BufferWritten;	// array of flags which buffers have been saved.
};



listener.cpp
#include <iostream>

#include "Listener.h"

using namespace DShowLib;

//////////////////////////////////////////////////////////////////////////
/*! The overlayCallback() method draws the number of the current frame. The
	frame count is a member of the tsMediaSampleDesc structure that is passed
	to overlayCallback() by the Grabber.
*/
void	CListener::overlayCallback( Grabber& caller, smart_ptr<OverlayBitmap> pBitmap, 
								   const tsMediaSampleDesc& MediaSampleDesc)
{
	char szText[25];
	if( pBitmap->getEnable() == true ) // Draw only, if the overlay bitmap is enabled.
	{
		sprintf( szText,"%04d ", MediaSampleDesc.FrameNumber);
		pBitmap->drawText( RGB(255,0,0), 0, 0, szText );
	}
}

//////////////////////////////////////////////////////////////////////////
/*! The frameReady() method calls the saveImage method to save the image buffer to disk.
*/
void	CListener::frameReady( Grabber& caller, smart_ptr<MemBuffer> pBuffer, DWORD currFrame)
{
	std::cout << "Buffer " << currFrame << " processed in CListener::frameReady()." << std::endl;

	saveImage( pBuffer, currFrame ); // Do the buffer processing.


	::Sleep(250); // Simulate a time expensive processing.
}

//////////////////////////////////////////////////////////////////////////
/*! Initialize the array of bools that is used to memorize, which buffers were processed in 
	the frameReady() method. The size of the array is specified by the parameter NumBuffers.
	It should be equal to the number of buffers in the FrameHandlerSink.
	All members of m_BufferWritten are initialized to false.
	This means that no buffers have been processed.
*/
void	CListener::setBufferSize( unsigned long NumBuffers )
{
	m_BufferWritten.resize( NumBuffers, false );
}

//////////////////////////////////////////////////////////////////////////
/*! The image passed by the MemBuffer pointer is saved to a BMP file.
*/
void	CListener::saveImage( smart_ptr<MemBuffer> pBuffer, DWORD currFrame)
{
	char filename[MAX_PATH];
	if( currFrame < m_BufferWritten.size() )
	{
		sprintf( filename, "image%02i.bmp", currFrame );

		saveToFileBMP( *pBuffer, filename );

		m_BufferWritten.at( currFrame ) = true;
	}
}