Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Build a Simple Watermarking Utility in Visual Basic 2005

0.00/5 (No votes)
19 Jan 2008 1  
An article on building a simple Watermarking utility in Visual Basic 2005

Introduction

This article shall describe an approach to building a simple watermarking utility that may be used to add watermarks to any supported image file format. The resulting application shall permit the user to open any supported image file format into a scrollable picture box, to define the text to be applied as a watermark (with a default version supplied), to set the font and color of the watermark, to define the opacity of the watermark, to determine whether or not the watermark appears at the top or bottom of the image, and to preview the watermark prior to saving it to the image.

Figure 1: The Utility Application showing a Watermarked Image.

If you are at all curious about the image, it is of an American Goldfinch, this time of year, I have about 50 or so such birds hanging around my bird feeders. I took the picture with my Fuji S700 digital camera through the kitchen window.

Getting Started

The solution contains a single Windows Forms project called WatermarkingVB written in Visual Basic 2005; the application contains only a single form (frmWatermark.vb) and all of the code necessary to drive the application is contained in that single Form class.

Figure 2: Solution Explorer with the Project Visible.

Code: Watermarking Main Form (frmWatermark.vb)

All of the code necessary for this project is contained in this single form; the form shall be described entirely in this section.

The code for this Form class begins with the following:

Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports System.Drawing.Imaging
Imports System.Text

''' <summary>
''' An Image Watermarking Utility
''' </summary>
''' <remarks></remarks>
Public Class frmWatermark

Following the declaration of the Form class, the next order of business in the application is to declare a collection of member variables requiring form wide scope; these variables are contained in a defined region entitled, Member Variables. The declaration of the variables follows; as can been determined, the variables are used to keep track of the current file location and image, codec and encoder information used to translate the image from one format to another, and the color and font used to display the image watermark.

#Region "Member Variables"

    Private CurrentFile As String
    Private img As Image
    Private myImageCodecInfo As ImageCodecInfo
    Private myEncoder As System.Drawing.Imaging.Encoder
    Private myEncoderParameter As EncoderParameter
    Private myEncoderParameters As EncoderParameters
    Private myWatermarkColor As System.Drawing.Color
    Private myFont As System.Drawing.Font

#End Region

The next block of code in the Form class is the constructor; in this instance, the constructor is used to establish a default configuration including the definition of the watermark color, the opacity level of the watermark, the positioning option (top or bottom), the text contained in the watermark, and the font used to display the watermark.

#Region "Constructor"

    ''' <summary>
    ''' Constructor with default settings
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub New()

        InitializeComponent()

        ' setup default settings
        myWatermarkColor = Color.SteelBlue
        cboOpacity.SelectedIndex = 2
        optTop.Checked = True

        txtWaterMark.Text = "Your Name " & _
            Char.ConvertFromUtf32(169).ToString() & " " & _
            DateTime.Now.Year.ToString() + ", All Rights Reserved"

        myFont = txtWaterMark.Font

    End Sub

#End Region

Following the constructor, there is a region defined to handle file input/output operations. This region contains two event handlers, one for the selection of the Open File menu strip option, and one for the Save buttons’ click event. The Open File menu option is used to allow the user to navigate to and select an image file for load; the selected image file is placed into a scrollable picturebox.

The Save button click event handler is used to save the image file with the watermark; the original file may be renamed or overwritten.

#Region "File IO"

    Private Sub openToolStripMenuItem_Click(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles openToolStripMenuItem.Click

        ' configure the open file dialog to point to some
        ' common (usable) image file formats
        openFileDialog1.Title = "Open Image File"
        openFileDialog1.Filter = "Bitmap Files|*.bmp" & _
            "|Enhanced Windows MetaFile|*.emf" & _
                "|Exchangeable Image File|*.exif" & _
                "|Gif Files|*.gif|JPEG Files|*.jpg" & _
                "|PNG Files|*.png|TIFF Files|*.tif|Windows MetaFile|*.wmf"
        openFileDialog1.DefaultExt = "bmp"
        openFileDialog1.FilterIndex = 1
        openFileDialog1.FileName = ""
        openFileDialog1.ShowDialog()

        ' if the user did not select a file, return
        If (openFileDialog1.FileName = "") Then Return

        ' update the current file and form caption text
        CurrentFile = openFileDialog1.FileName.ToString()
        Me.Text = "Watermark Utility: " & CurrentFile.ToString()

        Try
            ' open the image into the picture box
            img = Image.FromFile(openFileDialog1.FileName, True)
            picContainer.Image = img

            ' resize the picture box to support scrolling
            ' large images
            picContainer.Size = img.Size

        Catch ex As Exception

            MessageBox.Show(ex.Message, "File Open Error")
        End Try

    End Sub

    Private Sub btnSave_Click(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles btnSave.Click

        Try
            ' get the extension to figure out how to limit the save
            ' option to the current image file type
            Dim strExt As String
            strExt = System.IO.Path.GetExtension(CurrentFile)
            strExt = strExt.ToUpper()
            strExt = strExt.Remove(0, 1)

            ' if the current image is, for example, a GIF, only
            ' allow the user to save the file with the watermark
            ' as a GIF
            SaveFileDialog1.Title = "Save File"
            SaveFileDialog1.DefaultExt = strExt
            SaveFileDialog1.Filter = strExt & " Image Files|*." + strExt
            SaveFileDialog1.FilterIndex = 1

            If SaveFileDialog1.ShowDialog() = DialogResult.OK Then
                If (SaveFileDialog1.FileName = "") Then
                    Return
                Else
                    ' save the file with the name supplied by the user
                    picContainer.Image.Save(SaveFileDialog1.FileName)
                End If

                ' update the current image file to point to the newly saved
                ' image
                CurrentFile = SaveFileDialog1.FileName
                Me.Text = "Watermark Utility: " + CurrentFile
                MessageBox.Show(CurrentFile.ToString() + " saved.", "File
                Save")
            Else
                MessageBox.Show("The save file request was cancelled by
                user.", "Save Cancelled")
            End If

        Catch ex As Exception
            MessageBox.Show(ex.Message.ToString(), "Image Save Error")
        End Try

    End Sub

#End Region

After handling the file IO operations, the next region of code is the Image Format Conversion section. In this region, the methods provided are used to convert the open image into an alternative format (e.g. bitmap to JPEG, or JPEG to GIF, etc.). Each section of code is annotated and may be reviewed in the following:

#Region "Image Format Conversion"

    Private Function GetEncoderInfo(ByVal mimeType As String) As ImageCodecInfo

        Dim j As Integer
        Dim encoders As ImageCodecInfo()
        encoders = ImageCodecInfo.GetImageEncoders()

        For j = 0 To encoders.Length

            If (encoders(j).MimeType = mimeType) Then
                Return encoders(j)
            End If

        Next

        Return Nothing

    End Function

    Private Sub bitmapToolStripMenuItem_Click(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles bitmapToolStripMenuItem.Click

        ' create a new name with the bitmap extension
        Dim newName As String = _
            System.IO.Path.GetFileNameWithoutExtension(CurrentFile)
        newName = newName + ".bmp"

        Try
            ' save the file as a bitmap
            img.Save(newName, ImageFormat.Bmp)
            CurrentFile = newName
            picContainer.Image = Image.FromFile(CurrentFile)
            Me.Text = "Watermark Utility: " + CurrentFile.ToString()
        Catch
            MessageBox.Show("Failed to save image to bitmap.", "Error", _
            MessageBoxButtons.OK, MessageBoxIcon.Error)
            Return
        End Try

        MessageBox.Show("Image file saved to " + newName.ToString(), _
        "Image Saved", MessageBoxButtons.OK, MessageBoxIcon.Information)

    End Sub

    Private Sub emfToolStripMenuItem_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles emfToolStripMenuItem.Click

        ' create a new name with the EMF extension
        Dim newName As String = _
            System.IO.Path.GetFileNameWithoutExtension(CurrentFile)
        newName = newName + ".emf"

        Try
            ' save the file as a EMF
            img.Save(newName, ImageFormat.Emf)
            CurrentFile = newName
            picContainer.Image = Image.FromFile(CurrentFile)
            Me.Text = "Watermark Utility: " + CurrentFile.ToString()
        Catch
            MessageBox.Show("Failed to save image to EMF.", "Error", _
            MessageBoxButtons.OK, MessageBoxIcon.Error)
            Return
        End Try

        MessageBox.Show("Image file saved to " + newName.ToString(), _
        "Image Saved", MessageBoxButtons.OK, MessageBoxIcon.Information)

    End Sub

    Private Sub exifToolStripMenuItem_Click(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles exifToolStripMenuItem.Click

        ' create a new name with the EXIF extension
        Dim newName As String = _
        System.IO.Path.GetFileNameWithoutExtension(CurrentFile)
        newName = newName + ".exif"

        Try
            ' save the file as a EXIF
            img.Save(newName, ImageFormat.Exif)
            CurrentFile = newName
            picContainer.Image = Image.FromFile(CurrentFile)
            Me.Text = "Watermark Utility: " + CurrentFile.ToString()
        Catch
            MessageBox.Show("Failed to save image to EXIF.", "Error", _
            MessageBoxButtons.OK, MessageBoxIcon.Error)
            Return
        End Try

        MessageBox.Show("Image file saved to " + newName.ToString(), _
        "Image Saved", MessageBoxButtons.OK, MessageBoxIcon.Information)

    End Sub

    Private Sub gIFFileToolStripMenuItem_Click(ByVal sender As System.Object, _
           ByVal e As System.EventArgs) Handles gIFFileToolStripMenuItem.Click

        ' create a new name with the GIF extension
        Dim newName As String = _
        System.IO.Path.GetFileNameWithoutExtension(CurrentFile)
        newName = newName + ".gif"

        Try
            ' save the file as a GIF
            img.Save(newName, ImageFormat.Gif)
            CurrentFile = newName
            picContainer.Image = Image.FromFile(CurrentFile)
            Me.Text = "Watermark Utility: " + CurrentFile.ToString()
        Catch
            MessageBox.Show("Failed to save image to GIF.", "Error", _
            MessageBoxButtons.OK, MessageBoxIcon.Error)
            Return
        End Try

        MessageBox.Show("Image file saved to " + newName.ToString(), _
        "Image Saved", MessageBoxButtons.OK, MessageBoxIcon.Information)

    End Sub

    Private Sub jPEGFileToolStripMenuItem_Click(ByVal sender As _
        System.Object, ByVal e As System.EventArgs) Handles _
        jPEGFileToolStripMenuItem.Click

        ' create a new name with the JPEG extension
        Dim newName As String = _
        System.IO.Path.GetFileNameWithoutExtension(CurrentFile)
        newName = newName + ".jpg"

        Try
            ' save the file as a JPG
            img.Save(newName, ImageFormat.Jpeg)
            CurrentFile = newName
            picContainer.Image = Image.FromFile(CurrentFile)
            Me.Text = "Watermark Utility: " + CurrentFile.ToString()
        Catch
            MessageBox.Show("Failed to save image to JPEG.", "Error", _
            MessageBoxButtons.OK, MessageBoxIcon.Error)
            Return
        End Try

        MessageBox.Show("Image file saved to " + newName.ToString(), _
        "Image Saved", MessageBoxButtons.OK, MessageBoxIcon.Information)

    End Sub

    Private Sub pNGFileToolStripMenuItem_Click(ByVal sender As System.Object,
    ByVal e As System.EventArgs) Handles pNGFileToolStripMenuItem.Click

        ' create a new name with the PNG extension
        Dim newName As String = _
        System.IO.Path.GetFileNameWithoutExtension(CurrentFile)
        newName = newName + ".png"

        Try
            ' save the file as a png
            img.Save(newName, ImageFormat.Png)
            CurrentFile = newName
            picContainer.Image = Image.FromFile(CurrentFile)
            Me.Text = "Watermark Utility: " + CurrentFile.ToString()
        Catch
            MessageBox.Show("Failed to save image to PNG.", "Error", _
            MessageBoxButtons.OK, MessageBoxIcon.Error)
            Return
        End Try

        MessageBox.Show("Image file saved to " + newName.ToString(), _
        "Image Saved", MessageBoxButtons.OK, MessageBoxIcon.Information)

    End Sub

    Private Sub tIFFFileToolStripMenuItem_Click(ByVal sender As _
        System.Object, ByVal e As System.EventArgs) Handles _
        tIFFFileToolStripMenuItem.Click

        ' create a new name with the TIF extension
        Dim newName As String = _
        System.IO.Path.GetFileNameWithoutExtension(CurrentFile)
        newName = newName + ".tif"

        Try
            ' save the file as a tif
            img.Save(newName, ImageFormat.Tiff)
            CurrentFile = newName
            picContainer.Image = Image.FromFile(CurrentFile)
            Me.Text = "Watermark Utility: " + CurrentFile.ToString()
        Catch
            MessageBox.Show("Failed to save image to TIF.", "Error", _
            MessageBoxButtons.OK, MessageBoxIcon.Error)
            Return
        End Try

        MessageBox.Show("Image file saved to " + newName.ToString(), _
        "Image Saved", MessageBoxButtons.OK, MessageBoxIcon.Information)

    End Sub

    Private Sub windowsMetafileToolStripMenuItem_Click(ByVal sender As _
        System.Object, ByVal e As System.EventArgs) Handles _
        windowsMetafileToolStripMenuItem.Click

        ' create a new name with the WMF extension
        Dim newName As String = _
        System.IO.Path.GetFileNameWithoutExtension(CurrentFile)
        newName = newName + ".wmf"

        Try
            ' save the file as a WMF
            img.Save(newName, ImageFormat.Wmf)
            CurrentFile = newName
            picContainer.Image = Image.FromFile(CurrentFile)
            Me.Text = "Watermark Utility: " + CurrentFile.ToString()
        Catch
            MessageBox.Show("Failed to save image to WMF.", "Error", _
            MessageBoxButtons.OK, MessageBoxIcon.Error)
            Return
        End Try

        MessageBox.Show("Image file saved to " + newName.ToString(), _
        "Image Saved", MessageBoxButtons.OK, MessageBoxIcon.Information)

    End Sub

#End Region

Following the image conversion routines, the next region of code is used to perform the actual watermarking functions.

#Region "Watermarking"

    ''' <summary>
    ''' Display the watermark as it would appear after
    ''' the watermark were saved to the file
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub btnPreview_Click(ByVal sender As System.Object, ByVal e As _
        System.EventArgs) Handles btnPreview.Click

        ' Update the application by reloading the image
        picContainer.Image = Image.FromFile(CurrentFile)

        Dim opac As Integer = 0
        Dim sOpacity As String = cboOpacity.Text

        ' Determine the opacity of the watermark
        Select Case (sOpacity)
            Case "100%"
                opac = 255 ' 1 * 255
            Case "75%"
                opac = 191 ' .75 * 255
            Case "50%"
                opac = 127 ' .5 * 255
            Case "25%"
                opac = 64  ' .25 * 255
            Case "10%"
                opac = 25  ' .10 * 255
            Case Else
                opac = 127 ' default at 50%; .5 * 255
        End Select

        ' Get a graphics context
        Dim g As Graphics = Graphics.FromImage(picContainer.Image)

        ' Create a solid brush to write the watermark text on the image
        Dim myBrush As Brush
        myBrush = New SolidBrush(Color.FromArgb(opac, myWatermarkColor))

        ' Calculate the size of the text
        Dim sz As SizeF = g.MeasureString(txtWaterMark.Text, myFont)

        ' Create a copy of variables to keep track of the
        ' drawing position (X,Y)
        Dim X As Integer
        Dim Y As Integer

        ' Set the drawing position based on the users
        ' selection of placing the text at the bottom or
        ' top of the image
        If (optTop.Checked = True) Then
            X = Convert.ToInt32((picContainer.Image.Width - sz.Width) / 2)
            Y = Convert.ToInt32((picContainer.Top + sz.Height) / 2)
        Else
            X = Convert.ToInt32((picContainer.Image.Width - sz.Width) / 2)
            Y = Convert.ToInt32((picContainer.Image.Height - sz.Height))
        End If

        ' draw the water mark text
        g.DrawString(txtWaterMark.Text, myFont, myBrush, New Point(X, Y))

    End Sub

    Private Sub btnFont_Click(ByVal sender As System.Object, ByVal e As _
        System.EventArgs) Handles btnFont.Click

        ' default the current font and color to that
        ' used in the watermark textbox
        fontDialog1.ShowColor = True
        fontDialog1.Font = txtWaterMark.Font
        fontDialog1.Color = txtWaterMark.ForeColor

        If fontDialog1.ShowDialog() <> DialogResult.Cancel Then

            myFont = fontDialog1.Font
            myWatermarkColor = fontDialog1.Color
            txtWaterMark.Font = fontDialog1.Font
            txtWaterMark.ForeColor = fontDialog1.Color

        End If

    End Sub

#End Region

That wraps up the sum of the code needed to drive the Watermarking utility. With the code provided, it is possible to convert from one image format to another and to apply a user defined watermark on an existing image file.

Summary

While this article was written to demonstrate an approach to watermarking an image file in the context of a WinForms utility application; the code used in the project could be modified to batch process image files, or to watermark image files programmatically and without user intervention. Even used as a utility, the application could have some value to anyone wishing to watermark or caption an image file before exposing the image file on the Web.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here