This article implements frame overlay, generation new frames from local files, and some other frame processing features.
The desired result:
A feature to zoom a selected part of a video under a mouse pointer. Just like this.
Preparations
For the effect, we need an image of the shadow effect and a mask:
The shadow effect: |
The mask: |
The mask uses white color to filter the video, and it uses other colors as transparent. You should use full black for full transparent parts. Other colors for semitransparent parts.
You should use both images to generate new frames:
MFFrame myMaskFrame;
MFFrame myEffectFrame;
MFFactoryClass myFactory = new MFFactoryClass();
myFactory.MFFrameCreateFromFile(@"dark_circle.png", out MFFrame myEffectFrame, "");
myFactory.MFFrameCreateFromFile(@"dark_circle2.png", out myMaskFrame, "");
Frame processing
Once a source frame has been received, you should clone it to avoid any memory access issues:
mSourceFrame.MFClone(out MFFrame myFrameClone, eMFrameClone.eMFC_Full, eMFCC.eMFCC_Default);
And work with the Clone frame later.
The main idea is to cut a square from the original frame, filter it with the mask and overlay it over the source frame.
Cut the square
To calculate proper parameters, you should get video properties of the processed frame:
myFrameClone.MFAVPropsGet(out M_AV_PROPS myProps, out int samples);
Now, you should calculate a relative mouse pointer position:
MFFrame cutFrame;
int x = Math.Abs(myProps.vidProps.nWidth * m_nMousePosX / panelPreview.Width);
int y = Math.Abs(myProps.vidProps.nHeight * m_nMousePosY / panelPreview.Height);
where the panelPreview is your actual preview control, and the m_nMousePosX and the m_nMousePosY are the X and Y coordinates of a mouse pointer over your preview.
So, the target rectangle of 200x200 should have the following parameters:
tagRECT rect = new tagRECT()
{
top = y - 100 < 0 ? 0 : y - 100,
bottom = y + 100 > 1080 ? 1080 : y + 100,
left = x - 100 < 0 ? 0 : x - 100,
right = x + 100 < 0 ? 1920 : x + 100,
};
And, finally, you should cut the rectangle from the source frame:
myFrameClone.MFCut(0, ref rect, out cutFrame);
Zoom and Mask
You should specify a new rectangle to place the cut frame. If the rectangle is bigger then there is a zoom effect. If there is no mask then the result looks like a square overlay. So, you should use the mask frame to create a round overlay.
The bigger rectangle of 500x500:
MF_RECT newRect = new MF_RECT()
{
dblHeight = 500,
dblWidth = 500,
dblPosX = x - 250,
dblPosY = y - 250
};
the x and y point to the center of the rectangle, so there are "-250" in calculations.
The overlay with the filter mask:
myFrameClone.MFOverlayRect(cutFrame, myMaskFrame, ref newRect, eMFOverlayFlags.eMFOF_Crop, 1, "", "");
Technically, it is enough for the proper zooming of the video. But if you like to highlight the zoom area, you might use the effect frame without any filtering:
myFrameClone.MFOverlayRect(myEffectFrame, null, ref newRect, eMFOverlayFlags.eMFOF_Crop, 1, "", "");
Sample application
For your reference, a sample application that illustrates this logic is attached below:
Zoom your video by pressing the left mouse button. Stop zooming by releasing the mouse button.