#
Draw multiple text overlays using the OnVideoFrameBuffer event
Video Capture SDK .Net , Video Edit SDK .Net , Media Player SDK .Net
#
Sample code
If video effect API to draw text overlay is not enough, you can draw overlay manually in OnVideoFrameBuffer, using Bitmap and Graphics classes. The bitmap should be 32-bit (with an alpha channel).
A version of code (simple) without an update of text or font on the fly:
// Image
private Bitmap logoImage = null;
// Image RGB32 buffer
private IntPtr logoImageBuffer = IntPtr.Zero;
private int logoImageBufferSize = 0;
private string text1 = "Hello World";
private string text2 = "Hey-hey";
private string text3 = "Ocean of pancakes";
private void SDK_OnVideoFrameBuffer(Object sender, VideoFrameBufferEventArgs e)
{
// draw text to image
if (logoImage == null)
{
logoImage = new Bitmap(e.Frame.Width, e.Frame.Height, PixelFormat.Format32bppArgb);
using (var grf = Graphics.FromImage(logoImage))
{
// antialiasing mode
grf.TextRenderingHint = TextRenderingHint.AntiAlias;
// drawing mode
grf.InterpolationMode = InterpolationMode.HighQualityBicubic;
// smoothing mode
grf.SmoothingMode = SmoothingMode.HighQuality;
// text 1
var brush1 = new SolidBrush(Color.Blue);
var font1 = new Font("Arial", 30, FontStyle.Regular);
grf.DrawString(text1, font1, brush1, 100, 100);
// text 2
var brush2 = new SolidBrush(Color.Red);
var font2 = new Font("Times New Roman", 35, FontStyle.Strikeout);
grf.DrawString(text2, font2, brush2, e.Frame.Width / 2, e.Frame.Height / 2);
// text 3
var brush3 = new SolidBrush(Color.Green);
var font3 = new Font("Verdana", 40, FontStyle.Italic);
grf.DrawString(text3, font3, brush3, 200, 200);
}
}
// create image buffer if not allocated or have zero size
if (logoImageBuffer == IntPtr.Zero || logoImageBufferSize == 0)
{
if (logoImageBuffer == IntPtr.Zero)
{
logoImageBufferSize = ImageHelper.GetStrideRGB32(logoImage.Width) * logoImage.Height;
logoImageBuffer = Marshal.AllocCoTaskMem(logoImageBufferSize);
}
else
{
logoImageBufferSize = ImageHelper.GetStrideRGB32(logoImage.Width) * logoImage.Height;
Marshal.FreeCoTaskMem(logoImageBuffer);
logoImageBuffer = Marshal.AllocCoTaskMem(logoImageBufferSize);
}
ImageHelper.BitmapToIntPtr(logoImage, logoImageBuffer, logoImage.Width, logoImage.Height,
PixelFormat.Format32bppArgb);
}
// Draw image
FastImageProcessing.Draw_RGB32OnRGB24(logoImageBuffer, logoImage.Width, logoImage.Height, e.Frame.Data, e.Frame.Width, e.Frame.Height, 0, 0);
e.UpdateData = true;
}
A version of code with updating on the fly by a button click:
// Image
Bitmap logoImage = null;
// Image RGB32 buffer
IntPtr logoImageBuffer = IntPtr.Zero;
int logoImageBufferSize = 0;
// text settings
string text1 = "Hello World";
Font font1 = new Font("Arial", 30, FontStyle.Regular);
SolidBrush brush1 = new SolidBrush(Color.Blue);
string text2 = "Hey-hey";
Font font2 = new Font("Times New Roman", 35, FontStyle.Strikeout);
SolidBrush brush2 = new SolidBrush(Color.Red);
string text3 = "Ocean of pancakes";
Font font3 = new Font("Verdana", 40, FontStyle.Italic);
SolidBrush brush3 = new SolidBrush(Color.Green);
// update flag
bool textUpdate = false;
object textLock = new object();
// Update text overlay, index is [1..3]
void UpdateText(int index, string text, Font font, SolidBrush brush)
{
lock (textLock)
{
textUpdate = true;
}
switch (index)
{
case 1:
text1 = text;
font1 = font;
brush1 = brush;
break;
case 2:
text2 = text;
font2 = font;
brush2 = brush;
break;
case 3:
text3 = text;
font3 = font;
brush3 = brush;
break;
default:
return;
}
}
private void SDK_OnVideoFrameBuffer(Object sender, VideoFrameBufferEventArgs e)
{
lock (textLock)
{
if (textUpdate)
{
logoImage.Dispose();
logoImage = null;
}
// draw text to image
if (logoImage == null)
{
logoImage = new Bitmap(e.Frame.Width, e.Frame.Height, PixelFormat.Format32bppArgb);
using (var grf = Graphics.FromImage(logoImage))
{
// antialiasing mode
grf.TextRenderingHint = TextRenderingHint.AntiAlias;
// drawing mode
grf.InterpolationMode = InterpolationMode.HighQualityBicubic;
// smoothing mode
grf.SmoothingMode = SmoothingMode.HighQuality;
// text 1
grf.DrawString(text1, font1, brush1, 100, 100);
// text 2
grf.DrawString(text2, font2, brush2, e.Frame.Width / 2, e.Frame.Height / 2);
// text 3
grf.DrawString(text3, font3, brush3, 200, 200);
}
}
// create image buffer if not allocated or have zero size
if (logoImageBuffer == IntPtr.Zero || logoImageBufferSize == 0)
{
if (logoImageBuffer == IntPtr.Zero)
{
logoImageBufferSize = ImageHelper.GetStrideRGB32(e.Frame.Width) * e.Frame.Height;
logoImageBuffer = Marshal.AllocCoTaskMem(logoImageBufferSize);
}
else
{
logoImageBufferSize = ImageHelper.GetStrideRGB32(e.Frame.Width) * e.Frame.Height;
Marshal.FreeCoTaskMem(logoImageBuffer);
logoImageBuffer = Marshal.AllocCoTaskMem(logoImageBufferSize);
}
ImageHelper.BitmapToIntPtr(logoImage, logoImageBuffer, logoImage.Width, logoImage.Height,
PixelFormat.Format32bppArgb);
}
if (textUpdate)
{
textUpdate = false;
ImageHelper.BitmapToIntPtr(logoImage, logoImageBuffer, logoImage.Width, logoImage.Height,
PixelFormat.Format32bppArgb);
}
// Draw image
FastImageProcessing.Draw_RGB32OnRGB24(logoImageBuffer, logoImage.Width, logoImage.Height, e.Frame.Data, e.Frame.Width,
e.Frame.Height, 0, 0);
e.UpdateData = true;
}
}
private void btUpdateText1_Click(object sender, EventArgs e)
{
UpdateText(1, "Hello world", new Font("Arial", 48, FontStyle.Underline),
new SolidBrush(Color.Aquamarine));
}
#
Required redists
- SDK redist
Visit our GitHub page to get more code samples.