Using Transforms in C++
To use a transform in a C++ application, you must be familiar with a few key interfaces, methods, and objects. This section describes how to use an existing transform in a C++ application.
There are four key steps for creating a transform in your application. The client must first identify the desired transform, either specifically by class identifier (CLSID) or by using the component category manager to create the transform. After the desired transform has been identified, input and output objects, usually DXSurface objects, must be created and initialized. The transform must then be set up and associated with these objects, and then the transform can be executed.
The process of creating a transform in your application is detailed in the following steps.
- Step 1: Declare and Create the Transform Factory
- Step 2: Create Transform Inputs and Output
- Step 3: Set Up the Transform
- Step 4: Execute the Transform
The following example code uses only DXSurfaces.
Step 1: Declare and Create the Transform Factory
Declare and create the DXTransformFactory (Transform Factory), and use the IDXTransformFactory::CreateTransform method to create and initialize the transform in one step. The following example creates the Compositor transform.
//Create the Transform Factory. IDXTransformFactory* pTransFact; CoCreateInstance( CLSID_DXTransformFactory, NULL, CLSCTX_INPROC, IID_IDXTransformFactory, (void **)&pTransFact ); //Create the transform. IDXTransform *pSomeTrans; pTransFact->CreateTransform( NULL, 0, NULL, 0, NULL, NULL, CLSID_DXTComposite, IID_IDXTransform, (void **)&pSomeTrans );
Step 2: Create Transform Inputs and Output
After you have a pointer to a transform, you need to define the transform's inputs and its single output. To find out about the input and output types for a particular transform, see Visual Filters and Transitions Reference.
To create DXSurfaces, query the Transform Factory for the IDXSurfaceFactory object and use it to create DXSurfaces and to return the IDXSurface pointer. You can use a number of methods on the IDXSurfaceFactory interface to create a DXSurface. The following example uses the IDXSurfaceFactory::LoadImage method to create a DXSurface containing image data.
// Query for IDXSurfaceFactory. pTranFact->QueryInterface(IID_IDXSurfaceFactory, (void**)&pSurfFactory); pTranFact->Release(); // Create a DXSurface with an image loaded on it. IDXSurface *pInSurf; pSurfFactory ->LoadImage("image.png", NULL, NULL &DDPF_PMARGB32, IID_IDXSurface, (void**)&pInSurf ); // Create the output DXSurface for the transform. IDXSurface *pOutSurf; // Give it a size. CDXDBnds bnds; bnds.SetXYSize(100, 100); pSurfFactory->CreateSurface( NULL, NULL, &DDPF_PMARGB32, &bnds, 0, NULL, IID_IDXSurface, (void**)&pOutSurf);
This creates an input DXSurface, a transform that can be applied to the surface, and a blank output DXSurface object on which to place a result.
Step 3: Set Up the Transform
Use the IDXTransform::Setup method to associate the DXSurfaces with the transform, as shown in the following:
//Do transform set up and associate it with input and output DXSurface objects. pSomeTrans->Setup ( (IUnknown**)& pInSurf, 1, (IUnknown**)& pOutSurf, 1, 0);
In the previous case, there is one DXSurface input and one DXSurface output.
In addition, transforms that support the IDXEffect::Progress property for animation need a pointer to an IDXEffect interface. This is done using the Component Object Model (COM) QueryInterface on the transform, as shown in the following code example.
hr = pSomeTrans->QueryInterface( IID_IDXEffect, (void **)&g_pEffect );
You can use the returned interface pointer to call the IDXEffect::Progress method and to set the value for IDXEffect::Progress.
Step 4: Execute the Transform
Use the IDXTransform::Execute method to execute the transform and write the resulting image to the destination at (0,0), as shown in the following code example.
//Set the offset boundaries for the result and execute. pSomeTrans->Execute( NULL, NULL, NULL );
Now you can retrieve the device context (DC) from the output DXSurface and blit the result to the display.
For animated effects, this call to IDXTransform::Execute corresponds to one frame of the animation. To produce a flowing transition, you need to loop over changing values of IDXEffect::Progress, calling put_Progress and IDXTransform::Execute at each step.