Meet us at PRINT 19. Chicago, IL. Oct. 3 - 5.
This documentation is for the old version. Go to the latest Graphics Mill docs

Working with Watermarks

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.

Class Structure

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

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:

Visual Basic
' 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.
C#
// 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.

Timer Watermark

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:

  • AviTimerStyle.CurrentDateTime (displays the current date/time on each frame - it is the same for all frames in the movie);
  • AviTimerStyle.VideoTime (displays the timing information of each frame - this way the timer increases when the movie is played);
  • AviTimerStyle.VideoTimeAndFrame (displays the timinig information in the same manner as the VideoTime, and in addition appends the frame number).

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:

Visual Basic
' 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.
C#
// 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:

Visual Basic
' 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.
C#
// 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.
Note

Bitmap and timer watermark may be used together and do not exclude each other.

Advanced Watermarking

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:

  • Bitmap representing the current frame;
  • Frame index;
  • Frame timing.

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:

  1. DrawingWatermark event raised;
  2. Bitmap watermark is drawn;
  3. Timer watermark is drawn;
  4. DrawnWatermark event is raised.

The code snippet below demonstrates how to use the DrawnWatermark event. See comments in the code for details.

Visual Basic
' 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
C#
// 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.

See Also

Manual