Using the CDXBaseNTo1 Base Class
CDXBaseNTo1 is a base class that you can use to implement transforms that take multiple images as inputs and produce a single image. If you choose not to use this base class, you can create a transform by directly implementing the IDXTransform interface, the IObjectWithSite Component Object Model (COM) interface, and, if you are using an image transform, the IDXSurfacePick interface. However, you will find it easier to use this base class because it performs parameter validation, preprocesses data, and implements the full IDXTransform interface. This simplifies development by only requiring implementation of the code specific to the transform.
The base class is an Active Template Library (ATL) object, which is based on the multithreaded version of the CComObjectRootEx class. It implements IDXTransform, the IDXBaseObject interface, IObjectWithSite, the IObjectSafety ATL interface, and for image-to-image transforms, the IDXSurfacePick interface. CDXBaseNTo1 contains several data members that can be accessed directly. Other members can only be accessed through helper functions.
This article contains the following sections.
- Data Members
- Mapping Bounds
- Helper Functions
You will probably need to change some base class defaults in the constructor of your derived class or, if you prefer, you can override the ATL CComObjectRootEx::FinalConstruct method and initialize the object there. The base class sets all default settings for one required input and one output image-to-image transform.
The m_dwOptionsFlags member is used to determine restrictions on inputs and outputs.
For image-to-image transforms that have multiple inputs, you can set DXBOF_SAME_SIZE_INPUTS, which forces the base class to make all input surfaces have the same width and height. In this case, the common size uses the largest width and height from all input surfaces, with undefined regions in the inputs padded with zero alpha samples. If this flag is set in combination with DXBOF_CENTER_INPUTS, images that are smaller than the common size are placed in the center of the bounds; otherwise they will originate at (0,0).
Next, you must decide on appropriate values for m_dwOptionsFlags. The default setting for this data member is BLEND_SUPPORTED | DITHER_SUPPORTED | BOUNDS_SUPPORTED | PLACEMENT_SUPPORTED | BLEND_WITH_OUTPUT | DITHER_OUTPUT. This is the appropriate default setting for image-to-image transforms. If the image transform can support the
Quality property, you should set m_dwMiscFlags |= DXTMF_QUALITY_SUPPORTED.
Set the m_ulMaxInputs member to the appropriate value. The default is 1.
Set the m_ulNumInRequired member to the appropriate value. The default is 1.
If the transform is an image-to-image transform, you can change m_ulMaxImageBands. If the transform cannot break operations into multiple bands, but you still want to use the CDXBaseNTo1::WorkProc method of execution, set this member to 1. To call the IDXTransform::Execute method directly, set this member to 0, and your class's CDXBaseNTo1::OnExecute method will be called. Otherwise, leave this at its default value, which is 4. For more information, see the Execution section.
When your transform's IDXTransform::Setup method is called, the base class validates the number and type of inputs and outputs, and, if everything looks correct, it calls your derived function, as shown in the following code example.
HRESULT OnSetup(DWORD dwSetupFlags);
The flags are undefined at this time and will always be zero. At this point, you can perform the initialization you need. You are not required to override the CDXBaseNTo1::OnSetup method. Typical operations that are performed during a call to CDXBaseNTo1::OnSetup to determinine the native pixel formats of inputs and outputs.
When the transform is cleared by a call to IDXTransform::Setup with NULL input and output parameters, you can be notified to release the transform's resources by overriding CDXBaseNTo1::OnReleaseObjects, as shown in the following code example.
If the transform is an image-to-image transform, and you have not set m_ulMaxImageBands to zero, you should override the CDXBaseNTo1::WorkProc virtual function, as shown in the following code example.
HRESULT WorkProc(const CDXTWorkInfoNTo1 & WorkInfo, BOOL* pbContinueProcessing);
The CDXTWorkInfoNTo1 object contains a DoBnds data member, which specifies the logical portion of the output space to produce, and an OutputBnds data member, which specifies where the output should be placed on the output surface. Use the OutputBnds when locking the output surface to make sure you only request a write lock on the appropriate portion of the output surface to enable multiple bands to execute on separate processors.
When the CDXBaseNTo1::OnExecute method is called, the base class has already performed appropriate parameter validation. For example, it makes sure that only supported parameters are provided and that the transform is appropriately set up prior to calling CDXBaseNTo1::OnExecute. This makes implementation of IDXTransform::Execute easier than overriding the IDXTransform::Execute method.
All transforms must support the IDXTransform::MapBoundsIn2Out method. Generally, you can accomplish this by simply overriding the appropriate version of the CDXBaseNTo1::DetermineBnds virtual function. For image-to-image transforms, override the CDXBaseNTo1::DetermineBnds that operates on a CDXBnds. If your transform performs a one-to-one mapping of input to output space, you don't need to implement CDXBaseNTo1::DetermineBnds because the base class implements this by default.
If you are using an image transform, the bounds structure contains the union of all input bounds. You should modify the bounds to the resulting output bounds.
Transforms also must support the IDXTransform::MapBoundsOut2In method if the transform's input and output bounds differ. For example, this is the case for an image scaling transform. This method is important because it enables the base class to perform several operations generically, such as picking. If you implement surface picking in your transform, you need to override the IDXTransform::MapBoundsOut2In method.
Image transforms must implement picking by overriding the CDXBaseNTo1::OnSurfacePick method, which lets the derived class fully implement picking or by overriding the CDXBaseNTo1::OnGetSurfacePickOrder method, which requires the derived class to return stacking order and weights so the base class can determine which input was hit. If the transform does not have any inputs, the derived class should hit test against the output space returning DXT_S_HITOUTPUT for a successful hit.
The CDXBaseNTo1::InputSurface helper function returns an IDXSurface interface for the specified input. Similarly, the CDXBaseNTo1::OutputSurface function returns an IDXSurface interface for the output.
The CDXBaseNTo1::DoOver helper function returns TRUE if one or more inputs has transparent or translucent pixels and if the DXTMF_BLEND_WITH_OUTPUT flag is set in the m_dwMiscFlags. This is correct for most image transforms. However, if your transform creates transparent or translucent pixels, you should not use this helper function to determine whether to blend the transform output over the output surface. You should instead check that DXTMF_BLEND_WITH_OUTPUT flag is set in m_dwMiscFlags.
The CDXBaseNTo1::DoDither helper function returns TRUE under two possible circumstances: If there are no inputs and DXTMF_DITHER_OUTPUT is set, the return value is TRUE. Also, if one or more of the inputs has a greater number of bits per pixel than the output surface and if DXTMF_DITHER_OUTPUT is set, the function returns TRUE.
For information on other helper functions, see the CDXBaseNTo1 Helper Function reference.