A MontiVision Filter SDK DLL contains one function which is provided for the implementation of custom algorithms, the TransformSample() function. This function is called for every frame passing the filter in a started filter configuration. The function provides two pointers to arrays of bytes, one array contains the input and the other one the output image. The arrays are of the same size. Your new DirectShow filter reads the data from the input image buffer, processes it and writes the resulting data into the output image buffer.To help you navigating through the image, a couple of additional parameters are passed to the function. The iWidth and the iHeight parameters contain the dimension of the image. It is not possible to change the input image to a smaller or larger output image size. The iBytePerPixel parameter defines the number of bytes used per pixel. There are three possible values: 1 (grayscale), 3 (RGB in byte order B G R) or 4 (ARGB in byte order B G R A). The input and output images have the same number of bytes per pixel. It is not possible to change the color depth of the output image. The global variable g_dwTypes sets the possible video formats the filter accepts.
Image Organization
Input and output images are stored in a one-dimensional buffer of type BYTE, where a BYTE is an unsigned 8 bit value. Each pixel of the image contains one, three or four bytes. The number of bytes per pixel depends on the color bit depth of the image.
| RGB_8 | 1 |
| RGB_24 | 3 |
| RGB_32 | 4 |
The pixels are encoded as RGB(A) values. The image buffer
is organized in lines. In a RGB24 image, the first pixel of the
first line of the image is represented in the array as the
first three values of the array, the following three values
represent the next pixel of the image and so on. Each line of the
image is DWORD aligned. The first line in the array is followed by
the second line and so on. The first line of the array is the
bottom line of the image. This image layout used
in DirectShow® is different from the layout used in
Windows bitmaps and Windows GDI. The color values for a pixel
are stored in the order: blue, green, red,
alpha.
Sample:
The easiest way to understand this is through a diagram. Below you see a 2x2 pixel image in RGB 24 mode.
Image:
| RGB Line 2 Pixel 1 |
RGB Line 2 Pixel 2 |
| RGB Line 1 Pixel 1 |
RGB Line 1 Pixel 2 |
Array:
| image[0] | image[1] | image[2] | image[3] | image[4] | image[5] | image[6] | image[7] | image[8] | image[9] | image[10] | image[11] | image[12] | image[13] | image[14] | image[15] |
| Blue value Pixel 1 Line 1 |
Green
value Pixel 1 Line 1 |
Red value Pixel 1 Line 1 |
Blue value Pixel 2 Line 1 |
Green value Pixel 2 Line 1 |
Red value Pixel 2 Line 1 |
padding |
padding |
Blue value Pixel 1 Line 2 |
Green value Pixel 1 Line 2 |
Red value Pixel 1 Line 2 |
Blue value Pixel 2 Line 2 |
Green value Pixel 2 Line 2 |
Red value Pixel 2 Line 2 |
padding for DWORD allignment |
padding for DWORD allignment |
Because of the DWORD alignment one line of the image is stored in 8 bytes. The iPitch parameter of the TransformSample function is set to 8.
Sample
This is a working TransformSample() function. It reads a parameter from the parameter structure (*pSavePointer) which was initialized in the function InitDLL() . Three "for" loops go through the input image and copy the bytes of every pixel to the output image.
STDAPI TransformSample(
BYTE*
pInBuffer,
BYTE*
pOutBuffer,
int
iWidth,
int
iHeight,
int
iBytePerPixel,
int
iPitch
void* pSavePointer,
void*
pTempPointer,
PVOID
pIOInBuffer,
int iIOInBufferSize,
PVOID pIOOutBuffer,
int
iIOOutBufferSize,
SAMPLE_TIMES times)
{
int i, j;
int iParam = 0;
int iTemp = 0;
iParam =
((FILTER_PARAMETER*)pSavePointer)->iParam;
iTemp =
++((FILTER_TEMP_DATA*)pTempPointer)->iTemp;
// Sample
for IO_UINT8 I/O input pin type
BYTE invalue;
if((pIOInBuffer != 0L) &&
(iIOInBufferSize >= sizeof(BYTE)))
{
invalue =
*((BYTE*)pIOInBuffer);
}
for( i=0; i<iHeight; i++ )
{
for( j=0;
j<iPitch; j++ )
{
*pOutBuffer++ = *pInBuffer++;
}
}
// Sample for IO_STRING I/O output pin
type
char* outvalue;
if((pIOOutBuffer != 0L) &&
(iIOOutBufferSize >= 256))
{
outvalue =
(char*)pIOOutBuffer;
StringCchPrintf(outvalue, "Input Value: 0x%02X, frame %d", invalue,
iTemp);
}
return S_OK;
}