It is often needed to add watermarks to a video movie. For example, you want to put your logo or a picture to each frame of the video. AVI Processor Add-on for Graphics Mill enables you to do it. This section describes how to use this feature.
The watermark functionality is concentrated in class called Aurigma.GraphicsMill.Codecs.AviWatermark. This class is returned by the Watermark property of the writer object. You can read about writer object in the Writing AVI Files section.
AVI Processor Add-on supports two kinds of watermarks: bitmap watermark and timer watermark.
Within the AviWatermark class for bitmap watermark you can use the following properties:
Whereas for timer watermark you can use these properties:
For advanced usage of AviWatermark class you can use the following events:
These events are useful when functionality provided by bitmap and timer watermarks is not enough. For example, it makes sense to use these events when the watermark is not static.
Bitmap watermark is a static picture that you would like to place on each frame of your video. It may be a logo of your company or any other image.
To apply a bitmap watermark you should load a bitmap through the Bitmap property and set the
BitmapVisible property to
true
. If you need to specify position of the bitmap watermark on the video you may
set coordinates for the bitmap watermark by means of the BitmapOffset property.
The following code snippet shows how to use bitmap watermark:
' It is assumed that reader and writer objects has been properly ' created and initialized (omitted for brevity). ' Enable the bitmap watermark and load the necassary logo writer.Watermark.BitmapVisible = True writer.Watermark.Bitmap = New Aurigma.GraphicsMill.Bitmap("C:\Logo.png") ' Have the writer to display the logo in the bottom right corner ' of the video movie. Dim pos As System.Drawing.Point pos.X = reader.Width - writer.Watermark.Bitmap.Width - 5 pos.Y = reader.Height - writer.Watermark.Bitmap.Height - 5 writer.Watermark.BitmapOffset = pos ' Now during each AddFrame method call the logo will be ' automatically drawn on the frame. Dim frame As Aurigma.GraphicsMill.Codecs.IFrame For Each frame In reader writer.AddFrame(frame) Next ' ... all consequent code (including cleanup) has been omitted for brevity.
// It is assumed that reader and writer objects has been properly // created and initialized (omitted for brevity). // Enable the bitmap watermark and load the necassary logo writer.Watermark.BitmapVisible = true; writer.Watermark.Bitmap = new Aurigma.GraphicsMill.Bitmap(@"C:\Logo.png"); // Have the writer to display the logo in the bottom right corner // of the video movie. System.Drawing.Point pos = new System.Drawing.Point(); pos.X = reader.Width - writer.Watermark.Bitmap.Width - 5; pos.Y = reader.Height - writer.Watermark.Bitmap.Height - 5; writer.Watermark.BitmapOffset = pos; // Now during each AddFrame method call the logo will be // automatically drawn on the frame. foreach (Aurigma.GraphicsMill.Codecs.IFrame frame in reader) { writer.AddFrame(frame); } // ... all consequent code (including cleanup) has been omitted for brevity.
Under the timer watermark we will mean a timestamp on each frame of the video movie. It can be a current date/time, timing of a frame or its number.
If you want to use timer watermark on your video you need to set the TimerVisible property to
true
and specify the timestamp type using the TimerStyle property. This property
can take one of the following values:
If you need to have something written before or after the timing information you may use the TimerPrefix and the TimerSuffix properties correspondently.
You can vary the appearance of the timer watermark using the TimerFont and TimerBrush properties.
The following code snippet shows how to use timer watermark:
' It is assumed that reader and writer objects has been properly ' created and initialized (omitted for brevity). ' Enable the timer watermark and specify that we want to display ' both timing and frame number. writer.Watermark.TimerVisible = True writer.Watermark.TimerStyle = _ Aurigma.GraphicsMill.Codecs.AviTimerStyle.VideoTimeAndFrame ' Specify timer text appearance settings. writer.Watermark.TimerBrush = New Aurigma.GraphicsMill.Drawing.SolidBrush( _ Aurigma.GraphicsMill.RgbColor.Red) writer.Watermark.TimerFont = New Aurigma.GraphicsMill.Drawing.Font("Verdana", 14) ' Now during each AddFrame method call the logo will be ' automatically drawn on the frame. Dim frame As Aurigma.GraphicsMill.Codecs.IFrame For Each frame In reader writer.AddFrame(frame) Next ' ... all consequent code (including cleanup) has been omitted for brevity.
// It is assumed that reader and writer objects has been properly // created and initialized (omitted for brevity). // Enable the bitmap watermark and load the necassary logo writer.Watermark.TimerVisible = true; writer.Watermark.TimerStyle = Aurigma.GraphicsMill.Codecs.AviTimerStyle.VideoTimeAndFrame; // Specify timer text appearance settings. writer.Watermark.TimerBrush = new Aurigma.GraphicsMill.Drawing.SolidBrush( Aurigma.GraphicsMill.RgbColor.Red); writer.Watermark.TimerFont = new Aurigma.GraphicsMill.Drawing.Font("Verdana", 14); // Now during each AddFrame method call the logo will be // automatically drawn on the frame. foreach (Aurigma.GraphicsMill.Codecs.IFrame frame in reader) { writer.AddFrame(frame); } // ... all consequent code (including cleanup) has been omitted for brevity.
When you display the current date/time instead of timing information, you can adjust output formatting with a help of the TimerFormatProvider and TimerFormat properties:
' It is assumed that reader and writer objects has been properly ' created and initialized (omitted for brevity). ' Enable the timer watermark and specify that we want to display ' both timing and frame number. writer.Watermark.TimerVisible = True writer.Watermark.TimerStyle = _ Aurigma.GraphicsMill.Codecs.AviTimerStyle.CurrentDateTime ' Specify timer string formatting. writer.Watermark.TimerFormatProvider = System.Globalization.CultureInfo.CurrentCulture writer.Watermark.TimerFormat = "D" ' Now during each AddFrame method call the logo will be ' automatically drawn on the frame. Dim frame As Aurigma.GraphicsMill.Codecs.IFrame For Each frame In reader writer.AddFrame(frame) Next ' ... all consequent code (including cleanup) has been omitted for brevity.
// It is assumed that reader and writer objects has been properly // created and initialized (omitted for brevity). // Enable the bitmap watermark and load the necassary logo writer.Watermark.TimerVisible = true; writer.Watermark.TimerStyle = Aurigma.GraphicsMill.Codecs.AviTimerStyle.CurrentDateTime; // Specify timer string formatting. writer.Watermark.TimerFormatProvider = System.Globalization.CultureInfo.CurrentCulture; writer.Watermark.TimerFormat = "D"; // Now during each AddFrame method call the logo will be // automatically drawn on the frame. foreach (Aurigma.GraphicsMill.Codecs.IFrame frame in reader) { writer.AddFrame(frame); } // ... all consequent code (including cleanup) has been omitted for brevity.
Bitmap and timer watermark may be used together and do not exclude each other.
Sometimes you may find out that bitmap and timer watermark features described above are not flexible enough. For example, if you want the watermark to be changed depending on the frame number or its timing, it would be necessary to insert the code which generates the watermark into the loop which adds frames to the writer. As usual it leads to the logic complication.
To avoid it, you can use special events exposed by the AviWatermark class - DrawingWatermark and DrawnWatermark. These events are raised every time before and after the "main" watermarks are drawn. These events take a number of arguments including:
This way you can draw any imagery depending on the frame number or its timing. You can use all power of Graphics Mill for .NET to do it.
When the frame is added to the writer the sequence of these events triggering is the following:
The code snippet below demonstrates how to use the DrawnWatermark event. See comments in the code for details.
' This code sample will draw the text first and last 5 seconds ' of the movie (similar to musical clips). Private movieDuration As Integer Public Sub PutWatermarkWithEvents(ByVal inputFilename As String, _ ByVal outputFilename As String) Dim reader As New Aurigma.GraphicsMill.Codecs.AviReader reader.Open(inputFilename) Dim writer As New Aurigma.GraphicsMill.Codecs.AviWriter writer.Open(outputFilename) ' All the code which copies settings from reader to writer is omitted for brevity ' Determines the movie length to be able to detect last 5 seconds. ' It should be measured in 1/100 of seconds. Frame count is ' used during the watermark animation. movieDuration = 100 * (reader.FrameCount - 1) / reader.FramesPerSecond ' Subscribe for the AfterDrawWatermark event. AddHandler writer.Watermark.DrawnWatermark, AddressOf Watermark_AfterDrawWatermark ' Now during each AddFrame method call the Watermark_AfterDrawWatermark method ' will be executed. Dim frame As Aurigma.GraphicsMill.Codecs.IFrame For Each frame In reader writer.AddFrame(frame) Next ' Cleanup writer.Close() reader.Close() End Sub Private Sub Watermark_AfterDrawWatermark(ByVal sender As Object, _ ByVal e As Aurigma.GraphicsMill.Codecs.AviDrawWatermarkEventArgs) ' The time which the watermark is visible in the beginning and the end of the ' movie is hardcoded here. Dim watermarkDuration As Integer = 500 If e.Time <= watermarkDuration Or e.Time >= movieDuration - watermarkDuration Then ' Initialize the text to display and its appearance settings. Dim text As String = "Aurigma - AVI Processor" Dim font As New Aurigma.GraphicsMill.Drawing.Font("Arial", 10) Dim brush As New Aurigma.GraphicsMill.Drawing.SolidBrush( _ Aurigma.GraphicsMill.RgbColor.Yellow) ' Make calculations for the X coordinate (to make the text animated). Dim x As Single Dim textWidth As Single = font.MeasureString(text).Width If (e.Time >= movieDuration - watermarkDuration) Then x = System.Math.Log10(1 + _ ((movieDuration - e.Time) * 9) / watermarkDuration) * _ textWidth - textWidth Else x = System.Math.Log10(1 + _ (e.Time * 9) / watermarkDuration) * _ textWidth - textWidth End If ' Get the graphics object of the current bitmap to draw the text with. Dim graphics As Aurigma.GraphicsMill.Drawing.GdiGraphics = _ e.Bitmap.GetGdiGraphics() graphics.DrawString(text, font, brush, x, 10) End If End Sub
// This code sample will draw the text first and last 5 seconds // of the movie (similar to musical clips). private int movieDuration; public void PutWatermarkWithEvents(string inputFilename, string outputFilename) { Aurigma.GraphicsMill.Codecs.AviReader reader = new Aurigma.GraphicsMill.Codecs.AviReader(inputFilename); Aurigma.GraphicsMill.Codecs.AviWriter writer = new Aurigma.GraphicsMill.Codecs.AviWriter(outputFilename); // All the code which copies settings from reader to writer is omitted for // brevity // Determines the movie length to be able to detect last 5 seconds. // It should be measured in 1/100 of seconds. Frame count is // used during the watermark animation. movieDuration = 100 * (reader.FrameCount - 1) / reader.FramesPerSecond; // Subscribe for the AfterDrawWatermark event. writer.Watermark.DrawnWatermark += new Aurigma.GraphicsMill.Codecs.AviDrawWatermarkEventHandler( Watermark_AfterDrawWatermark); // Now during each AddFrame method call the Watermark_AfterDrawWatermark method // will be executed. foreach (Aurigma.GraphicsMill.Codecs.IFrame frame in reader) { writer.AddFrame(frame); } // Cleanup writer.Close(); reader.Close(); } private void Watermark_AfterDrawWatermark(object sender, Aurigma.GraphicsMill.Codecs.AviDrawWatermarkEventArgs e) { // The time which the watermark is visible in the beginning and the end of the // movie is hardcoded here. int watermarkDuration = 500; if (e.Time <= watermarkDuration || e.Time >= movieDuration - watermarkDuration) { // Initialize the text to display and its appearance settings. string text = "Aurigma - AVI Processor"; Aurigma.GraphicsMill.Drawing.Font font = new Aurigma.GraphicsMill.Drawing.Font("Arial", 10); Aurigma.GraphicsMill.Drawing.SolidBrush brush = new Aurigma.GraphicsMill.Drawing.SolidBrush( Aurigma.GraphicsMill.RgbColor.Yellow); // Make calculations for the X coordinate (to make the text animated). float x; float textWidth = font.MeasureString(text).Width; if (e.Time >= movieDuration - watermarkDuration) { x = 0 - textWidth + (float)System.Math.Log10(1 + (float)((movieDuration - e.Time) * 9) / watermarkDuration) * textWidth; } else { x = 0 - textWidth + (float)System.Math.Log10(1 + (float)(e.Time * 9) / watermarkDuration) * textWidth; } // Get the graphics object of the current bitmap to draw the text with. Aurigma.GraphicsMill.Drawing.GdiGraphics graphics = e.Bitmap.GetGdiGraphics(); graphics.DrawString(text, font, brush, x, 10); } }
The DrawingWatermark event can be used in the same manner.