使用vb.net代码实现图像水印技术

使用vb.net代码实现图像水印技术
作者: Builder.com.cn
2006-11-23 10:5 AM

 

水印技术是一门用于商标和版权图像保护的有用技术,这一技术可只需用一小段代码就可动态地实现。

本文解释了如何创建一个水印类(watermark)来实现使用一幅图像或文字在原图像上创造一幅水印图。本文提供一个水印的vb.net应用程序及其完整的源代码和类文件,您可通过运行该程序更为清楚地认识图像水印技术。

图像水印技术是一门使用文字或一幅图像嵌入到另一幅图像,使得原图转换为覆盖图的技术。因为从覆盖图中移除水印是一件相当难的事情,需要很好的手工图像编辑能力,所以水印技术通常用于商标或版权的保护。不幸的是,微软的.net框架没有包含任何内置的动态运行图像水印的功能。

为了弥补这一缺点,我们构造了一个类以实现使用一幅图像或文字在原图上创造一幅水印图的功能。图A和图B所示的是两个水印图的示例,图A嵌入的水印是文字,图B嵌入的是一幅图像。

图A

 

图B

 

您将会注意到水印在图像的黑暗区域效果并不太明显。对于较暗的图像,嵌入文字光环水印或许效果会好些。为了获取创建光环的信息和源代码,请参看“使用vb.net代码给您的文字添加一个光环”。 

水印技术

Watermark 类包含很多属性,可用于测定在原图像的哪个位置嵌入水印、使用哪种类型的水印(文字或图像)以及水印的精确信息等。首先我们需要定义一个工具类(utility)来列举水印的类型和位置信息(参见:表A)。

定义好utility 类之后,就可以构造我们的水印类(watermark)。对于文字类型的水印,我们需要清楚使用什么文字及字体来创建这一水印。对于图像类型的水印,需要知道用于水印的图像的文件名。对于既包含文字又包含图像类型的水印,则需要知道原始图像文件的文件名和水印的位置。

因为所有需要的信息都在这些属性中已经设定好,所以主函数不需要其他的任何信息就可以创建一幅水印图像。程序将返回一个System.Drawing.Bitmap类型的实例。

水印程序在多线程环境下运行得非常理想。基于原图像和水印的程序可能占用很多的CPU运行时间。因此,将其放在后台运行,并将主程序放在前台执行可能会更好一点,这在水印程序是某一Web站点一部分的情况下尤为重要。例如,如果站点允许用户上传他们想要进行水印的图片时,我们需要一边继续运行网页的其余部分供用户使用,一边检测以确保水印图像已被创建。

 

水印的过程相当地简单。首先,我们创建一幅与原图大小相同的覆盖图,在需要的地方嵌入水印。水印可以是从一幅图片中加载,也可以是动态地创建想要的字体和文字。接着,检查覆盖图,搜索每一个像素点的颜色,显示其透明度。当我们找到一个像素点的颜色时,我们用其亮度值去创建一个乘法器。

这一乘法器系统可能使运行减慢,但是它能使水印图像随着原始图像色彩的改变而相应做出调整。同时,通过编辑源代码或者提供一个乘法器,我们就可以在与原始图像相同的像素点上设置与其原来颜色相应的颜色,但是这种颜色的红、绿、蓝分量都相应的乘上一个系数。因为这一系数是一个0-1之间的数,所以它将降低该像素点颜色的饱和度,使之呈现水印的效果。列表B包含了水印技术这一过程的主要处理代码。

下面代码值得注意,这是在创建像素点乘法器的时候使用到的。

PixelMultiplier = 1 - CSng(((1 - WatermarkPixel.GetBrightness)) * 0.25)

改变这行代码中的最终值(0.25)可以调整水印的强度。乘以0.25,水印的饱和度就被限定为原来的0%-25%。也就是说,如果水印图像颜色较暗淡,水印的效果将不太明显,最暗的颜色只能显示原色彩25%的强度。这一值不能低于0.0(显示不出水印效果)也不能高于1.0(使要出现水印的地方都呈现白色)。

通过测试,我们发现使该值维持在0.2-0.3之间效果最好。当然,我们可以将它设定为一个常数值,也可以修改代码使之在运行时动态地设定其大小。 

测试水印技术应用程序

 
<script language="JavaScript1.1" src="http://ad.cn.doubleclick.net/adj/messagingplus.zdnet.com.cn/developer/code;sz=1x1;ord=1730085408?" type="text/javascript"> </script> <script language="VBScript" type="text/javascript"> on error resume next ShockMode = (IsObject(CreateObject("ShockwaveFlash.ShockwaveFlash.5"))) </script>

水印程序可以用于动态网页,或者用于编辑图像以实现业目的。通过使用一个水印类(watermark),我们可以很容易地将水印技术整合到我们的应用系统中。下载安装整个应用程序便能产生水印图像。应用程序安装同样包含该应用程序的所有源代码和所有图像水印的类文件。我们可以很轻松地使用这些代码,将它们整合到我们自己的工程文件中,并修改它使之更加符合我们的需要。

 

 

 

 

 

 

Listing B

    Private Function AddWatermark(ByVal OriginalImage As Bitmap, ByVal WatermarkImage As Bitmap, ByVal Location As ImageWatermarkingUtilities.WatermarkLocation) As Bitmap
        Dim OutputImage As Bitmap
        Dim WatermarkOverlay As Bitmap
        Dim OverlayEditor As Graphics
        Dim StartingX As Integer
        Dim StartingY As Integer
        Dim EndX As Integer
        Dim EndY As Integer
        Dim WatermarkWidth As Integer
        Dim WatermarkHeight As Integer
        Dim X As Integer
        Dim Y As Integer
        Dim WatermarkPixel As Color
        Dim OriginalPixel As Color
        Dim NewPixel As Color
        Dim PixelMultiplier As Single

        If WatermarkImage.Width > OriginalImage.Width Or WatermarkImage.Height > OriginalImage.Height Then
            Throw New Exception("The watermark must be smaller than the original image.")
        End If

        OutputImage = New Bitmap(CType(OriginalImage.Clone(), Bitmap))
        WatermarkOverlay = New Bitmap(OutputImage.Width, OutputImage.Height)
        OverlayEditor = Graphics.FromImage(WatermarkOverlay)
        WatermarkWidth = WatermarkImage.Width
        WatermarkHeight = WatermarkImage.Height

        Select Case Location
            Case ImageWatermarkingUtilities.WatermarkLocation.TopLeft
                StartingX = 0
                StartingY = 0
            Case ImageWatermarkingUtilities.WatermarkLocation.TopCenter
                StartingX = Math.Max(CInt((OutputImage.Width / 2) - (WatermarkWidth / 2)), 0)
                StartingY = 0
            Case ImageWatermarkingUtilities.WatermarkLocation.TopRight
                StartingX = Math.Max(CInt(OutputImage.Width - WatermarkWidth), 0)
                StartingY = 0
            Case ImageWatermarkingUtilities.WatermarkLocation.MiddleLeft
                StartingX = 0
                StartingY = Math.Max(CInt((OutputImage.Height / 2) - (WatermarkHeight / 2)), 0)
            Case ImageWatermarkingUtilities.WatermarkLocation.MiddleCenter
                StartingX = Math.Max(CInt((OutputImage.Width / 2) - (WatermarkWidth / 2)), 0)
                StartingY = Math.Max(CInt((OutputImage.Height / 2) - (WatermarkHeight / 2)), 0)
            Case ImageWatermarkingUtilities.WatermarkLocation.MiddleRight
                StartingX = Math.Max(CInt(OutputImage.Width - WatermarkWidth), 0)
                StartingY = Math.Max(CInt((OutputImage.Height / 2) - (WatermarkHeight / 2)), 0)
            Case ImageWatermarkingUtilities.WatermarkLocation.BottomLeft
                StartingX = 0
                StartingY = Math.Max(CInt(OutputImage.Height - WatermarkHeight), 0)
            Case ImageWatermarkingUtilities.WatermarkLocation.BottomCenter
                StartingX = Math.Max(CInt((OutputImage.Width / 2) - (WatermarkWidth / 2)), 0)
                StartingY = Math.Max(CInt(OutputImage.Height - WatermarkHeight), 0)
            Case ImageWatermarkingUtilities.WatermarkLocation.BottomRight
                StartingX = Math.Max(CInt(OutputImage.Width - WatermarkWidth), 0)
                StartingY = Math.Max(CInt(OutputImage.Height - WatermarkHeight), 0)
        End Select

        StartingX = Math.Max(StartingX - 1, 0)
        StartingY = Math.Max(StartingY - 1, 0)
        EndX = StartingX + WatermarkWidth - 1
        EndY = StartingY + WatermarkHeight - 1

        OverlayEditor.DrawImage(WatermarkImage, StartingX, StartingY)

        For X = StartingX To EndX
            For Y = StartingY To EndY
                WatermarkPixel = WatermarkOverlay.GetPixel(X, Y)

                If WatermarkPixel.A > 0 Then
                    OriginalPixel = OutputImage.GetPixel(X, Y)
                    PixelMultiplier = 1 - CSng(((1 - WatermarkPixel.GetBrightness)) * 0.25)
                    NewPixel = Color.FromArgb(OriginalPixel.A, CInt(OriginalPixel.R * PixelMultiplier), CInt(OriginalPixel.G * PixelMultiplier), CInt(OriginalPixel.B * PixelMultiplier))
                    OutputImage.SetPixel(X, Y, NewPixel)
                End If
            Next
        Next

        WatermarkImage = Nothing
        OriginalImage = Nothing
        WatermarkOverlay = Nothing
        OverlayEditor = Nothing

        Return OutputImage
    End Function

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值