Click here to Skip to main content
15,888,351 members
Articles / Programming Languages / C#

Creating a Watermarked Photograph with GDI+ for .NET

Rate me:
Please Sign up or sign in to vote.
4.95/5 (89 votes)
25 Sep 20025 min read 417.7K   12.6K   263   62
This article describes the process of overlaying a Watermark image on top of a photograph using GDI+ and C# for .NET.

Image 1

Introduction

Often when placing photographic images on a website, it is necessary to permanently overlay a watermark and/or Copyright statement on top of that image. Such an insertion helps to identify the person that took the photograph and indicate the organization that holds the Copyright. Doing this task by hand can become time consuming and is often inconsistent. Using some simple techniques, there is an easy way to accomplish this programmatically using C# and GDI+.

Overview

I am going to show you a variety of techniques for manipulating an image. The following is a high level list of some of those techniques:

  • Inserting text on top of an image positioned relative to the size of an image
  • Dynamically choosing a System.Drawing.Font size to maximize readability
  • Manipulating the opacity of a String of text
  • Replacing a specific color in a bitmap to achieve transparency
  • Changing the opacity of an image through a 5x5 ColorMatrix

Define Images

Small photo
(Photo courtesy of AP wire)

The first step in this process is to load a photographic image for which you would like to apply the watermark.  This image can be virtually any size and resolution.  For this example, we will use an image that has a width of 449 pixels and a height of 346. The resolution is 72 dpi.

When the Main method is instantiated, the two variables of type string are defined. The first will define where to find the photograph, watermark and output the new image. The second will define the Copyright string we will use as part of our watermark.

C#
string WorkingDirectory = @"C:\Projects\WaterMark";
string Copyright = "Copyright © 2002 
                 - AP Photo/David Zalubowski";

The following creates an Image object from the specified file and then defines a variable for both its Width and Height. These dimensions are then used to build a Bitmap object with a 24 bits per pixel format for the color data. Lastly, this Bitmap is then used to create a new Graphics object from the specified Bitmap image.

C#
Image imgPhoto = Image.FromFile(WorkingDirectory 
              + "\\watermark_photo.jpg");
int phWidth = imgPhoto.Width; int phHeight =
                                  imgPhoto.Height;

Bitmap bmPhoto = new Bitmap(phWidth, phHeight, 
                     PixelFormat.Format24bppRgb);
bmPhoto.SetResolution(72, 72); 

Graphics grPhoto = Graphics.FromImage(bmPhoto);

 

Watermark Image This code loads the watermark image that has been saved as a BMP and set with a background color of Green (A=0, R=0, G=255, B=0). Once again, it defines a variable for both its Width and Height.
(Image courtesy of MLB.com)
C#
Image imgWatermark = new Bitmap(WorkingDirectory
                     + "\\watermark.bmp");
int wmWidth = imgWatermark.Width;
int wmHeight = imgWatermark.Height;

Step #1 - Watermark Text

This code draws the imgPhoto to the Graphics object positioning it (x= 0, y=0) at 100% of its original size. All future drawing will occur on top of the original photograph.

C#
grPhoto.SmoothingMode = SmoothingMode.AntiAlias;
grPhoto.DrawImage(
	imgPhoto,                               
	new Rectangle(0, 0, phWidth, phHeight), 
	0,                                      
	0,                                       
	phWidth,                                
	phHeight,                               
	GraphicsUnit.Pixel);

To maximize the size of the Copyright message, we will test 7 different Font sizes to determine the largest possible size we can use for the width of our Photograph. To effectively do this, we will define an array of integers, then iterate through those values measuring the Copyright string in the various point sizes. Once we have determined the largest possible size, we will exit the loop and draw the text.

C#
int[] sizes = new int[]{16,14,12,10,8,6,4};
Font crFont = null; 
SizeF crSize = new	SizeF(); 
for (int i=0 ;i<7; i++)
{ 
    crFont = new Font("arial", sizes[i],
                                 FontStyle.Bold);
    crSize = grPhoto.MeasureString(Copyright,
                                         crFont);

	if((ushort)crSize.Width < (ushort)phWidth)
		break;
}

Since all photographs will have varying heights, determine a position 5% from the bottom of the image. Use the Copyright strings height to determine an appropriate y-coordinate for which to draw the string. Determine its x-coordinate by calculating the centre of the image, then define a StringFormat object and set the StringAlignment to Center

C#
int yPixlesFromBottom = (int)(phHeight *.05);
float yPosFromBottom = ((phHeight - 
           yPixlesFromBottom)-(crSize.Height/2));
float xCenterOfImg = (phWidth/2);

StringFormat StrFormat = new StringFormat();
StrFormat.Alignment = StringAlignment.Center;

Now that we have all of the necessary positioning coordinates, create a SolidBrush with a Color of 60% Black (alpha value of 153).  Draw the Copyright string at the appropriate position offset 1 pixel to the right and 1 pixel down. This offset will create a shadow effect.  Repeat this process using a White Brush drawing the same text directly on top of the previously drawn string.

C#
SolidBrush semiTransBrush2 = 
    new SolidBrush(Color.FromArgb(153, 0, 0,0)); 

grPhoto.DrawString(Copyright,                    
    crFont,                                      
    semiTransBrush2,                             
    new PointF(xCenterOfImg+1,yPosFromBottom+1), 
    StrFormat);

SolidBrush semiTransBrush = new SolidBrush(
             Color.FromArgb(153, 255, 255, 255));

grPhoto.DrawString(Copyright,                 
    crFont,                                   
    semiTransBrush,                           
    new PointF(xCenterOfImg,yPosFromBottom),  
    StrFormat);
Image 4

Step #2 - Watermark Image

Create a Bitmap based on the previously modified photograph. Load this Bitmap into a new Graphic Object.

C#
Bitmap bmWatermark = new Bitmap(bmPhoto); 
bmWatermark.SetResolution(
                imgPhoto.HorizontalResolution, 
                    imgPhoto.VerticalResolution);

Graphics grWatermark =
                 Graphics.FromImage(bmWatermark);

To achieve a translucent watermark, we will apply two color manipulations by defining an ImageAttributes object and setting two of its properties. The first step in manipulating the watermark image is to replace the background color with one that is transparent (Alpha=0, R=0, G=0, B=0). To do this, we will use a Colormap and define a RemapTable. As previously shown, my watermark was defined with a background of 100% Green - this will be the color we search for and replace with transparency.

C#
ImageAttributes imageAttributes =
                           new ImageAttributes();
ColorMap colorMap = new ColorMap();

colorMap.OldColor=Color.FromArgb(255, 0, 255, 0);
colorMap.NewColor=Color.FromArgb(0, 0, 0, 0);
ColorMap[] remapTable = {colorMap};

imageAttributes.SetRemapTable(remapTable,
                         ColorAdjustType.Bitmap);

The second color manipulation is used to change the opacity of the watermark. This is done by applying a 5x5 matrix that contains the coordinates for the RGBA space. By setting the 3rd row and 3rd column to 0.3f, we achieve a level of opacity. The result is a watermark which slightly shows the underlying image.

C#
float[][] colorMatrixElements = { 
   new float[] {1.0f,  0.0f,  0.0f,  0.0f, 0.0f},
   new float[] {0.0f,  1.0f,  0.0f,  0.0f, 0.0f},
   new float[] {0.0f,  0.0f,  1.0f,  0.0f, 0.0f},
   new float[] {0.0f,  0.0f,  0.0f,  0.3f, 0.0f},
   new float[] {0.0f,  0.0f,  0.0f,  0.0f, 1.0f}
};

ColorMatrix wmColorMatrix = new
                ColorMatrix(colorMatrixElements);

imageAttributes.SetColorMatrix(wmColorMatrix, 
                       ColorMatrixFlag.Default, 
                         ColorAdjustType.Bitmap);	

With both color manipulations added to the imageAttributes object, we can now draw the watermark in the upper right hand corner of the photograph. We will offset the image 10 pixels down and 10 pixels to the left.

C#
int xPosOfWm = ((phWidth - wmWidth)-10);
int yPosOfWm = 10;

grWatermark.DrawImage(imgWatermark, 
    new Rectangle(xPosOfWm,yPosOfWm,wmWidth,
                                     wmHeight),
    0,                  
    0,                   
    wmWidth,            
    wmHeight,		    
    GraphicsUnit.Pixel, 
    imageAttributes);
Image 5

Or last and final step will be to replace the original Image with the new Bitmap, dispose of both Graphic objects then save this Image to the file system.

C#
imgPhoto = bmWatermark;
grPhoto.Dispose();
grWatermark.Dispose();

\\watermark_final.jpg", 
imgPhoto.Save(WorkingDirectory + "
	ImageFormat.Jpeg);
imgPhoto.Dispose();
imgWatermark.Dispose();

That's it! Compile the project, run it, and see what happens! The code is fairly straightforward if it all makes sense, then these techniques can be used for 100s of different image manipulations. The possibilities are endless.

Revision History

  • 26th September, 2002 - Initial revision

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.


Written By
Web Developer
United States United States
Joel is a Microsoft.NET system architect and Director of Development for a leading interactive development firm located in Tempe, Arizona. Our firm designs and develops a wide range of custom web applications which leverage Flash, Ajax, ASP.NET and the Microsoft.Net Framework.
In his free time, he enjoys spending time with his wife and children.

Comments and Discussions

 
Questiontry to do a mass watermarking application Pin
Member 1156703424-Apr-15 16:25
Member 1156703424-Apr-15 16:25 
GeneralThanks ! Pin
Gldmelo15-Sep-14 14:18
Gldmelo15-Sep-14 14:18 
QuestionThanks for this great work around. What should I do, if I want to remove this watermark? Pin
AQEEB PATHAN20-Mar-14 20:18
AQEEB PATHAN20-Mar-14 20:18 
Generalafter refactoring Pin
Radoslav Katreniak29-Oct-13 2:05
Radoslav Katreniak29-Oct-13 2:05 
QuestionRe: after refactoring Pin
ratul_ctg19-Jan-14 19:27
professionalratul_ctg19-Jan-14 19:27 
SuggestionRe: after refactoring Pin
ratul_ctg19-Jan-14 20:54
professionalratul_ctg19-Jan-14 20:54 
QuestionGreat Tutorial Pin
CBroos10-Mar-13 6:39
CBroos10-Mar-13 6:39 
GeneralGreat article Pin
filip_andry1-Mar-13 15:42
filip_andry1-Mar-13 15:42 
AnswerEnhancement and question Pin
FransDep12-Feb-13 3:41
FransDep12-Feb-13 3:41 
GeneralGreat work! Pin
Member 77240962-Dec-12 20:49
Member 77240962-Dec-12 20:49 
GeneralMy vote of 5! Pin
Member 956657721-Nov-12 1:50
Member 956657721-Nov-12 1:50 
GeneralMy vote of 5 Pin
hcheng_qi29-Dec-11 16:43
hcheng_qi29-Dec-11 16:43 
GeneralMy vote of 5 Pin
hitesh140715-Nov-11 11:52
hitesh140715-Nov-11 11:52 
QuestionHere's how I used it for my ASP.NET Website Pin
Member 818886925-Aug-11 6:27
Member 818886925-Aug-11 6:27 
GeneralGreat article! Pin
minhhieu_dotnet11-Nov-10 22:21
minhhieu_dotnet11-Nov-10 22:21 
QuestionC# and watermarking? Pin
lapadets27-Sep-10 7:26
lapadets27-Sep-10 7:26 
AnswerRe: C# and watermarking? Pin
Member 813589222-Aug-11 2:38
Member 813589222-Aug-11 2:38 
QuestionHow can apply watermarks to a printer? Pin
giji gangadharan10-Mar-10 19:48
giji gangadharan10-Mar-10 19:48 
GeneralGreat Work Pin
ranunes17-Sep-09 3:28
ranunes17-Sep-09 3:28 
QuestionGreat work! How to watermark diagonally? Pin
DesignerInCore9-Sep-09 16:54
DesignerInCore9-Sep-09 16:54 
AnswerRe: Great work! How to watermark diagonally? Pin
kiquenet.com17-Aug-10 6:28
professionalkiquenet.com17-Aug-10 6:28 
GeneralBrilliant Pin
tezza9812-May-09 15:23
tezza9812-May-09 15:23 
Generalsetlogo as vedio watermarking at center over vedio Pin
sushilabhanvar15-Apr-09 1:29
sushilabhanvar15-Apr-09 1:29 
Generalrequired c# Vedio watermarking code Pin
sushilabhanvar7-Apr-09 0:00
sushilabhanvar7-Apr-09 0:00 
hi friends,

I am working an desktop application IN C# .NET in which I want use water marking functionality... I have done this but there is a problem in showing text or image as water marking in currect way. whatever i want show as water marking in my vedio it is coming in after vertical flip .
***********<u>I want to show image or text AS IT IS NOT FLIPED </u>*********
CODE which I am using.................PLZ HELP WHERE IT IS CREATING PROBLEM

/****************************************************************************
While the underlying libraries are covered by LGPL, this sample is released
as public domain. It is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.
*****************************************************************************/

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Diagnostics;

using DirectShowLib;


namespace DxLogo
{
/// &lt;summary&gt; Summary description for MainForm. &lt;/summary&gt;
///

internal class Capture : ISampleGrabberCB, IDisposable
//internal class Capture : IDisposable
{
#region Member variables

/// &lt;summary&gt; graph builder interface. &lt;/summary&gt;
private IFilterGraph2 m_FilterGraph = null;
IMediaControl m_mediaCtrl = null;

/// &lt;summary&gt; Set by async routine when it captures an image &lt;/summary&gt;
private bool m_bRunning = false;

/// &lt;summary&gt; Dimensions of the image, calculated once in constructor. &lt;/summary&gt;
private int m_videoWidth;
private int m_videoHeight;
private int m_stride;
public static string FileName;
BitmapData m_bmdLogo = null;
Bitmap m_Bitmap = null;

#if DEBUG
// Allow you to "Connect to remote graph" from GraphEdit
DsROTEntry m_rot = null;
#endif

#endregion

#region API

[DllImport("Kernel32.dll", EntryPoint = "RtlMoveMemory")]
private static extern void CopyMemory(IntPtr Destination, IntPtr Source, [MarshalAs(UnmanagedType.U4)] uint Length);


#endregion

/// zero based device index, and some device parms, plus the file name to save to
public Capture(int iDeviceNum, int iFrameRate, int iWidth, int iHeight, string FileName)
{
DsDevice[] capDevices;

// Get the collection of video devices
capDevices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);

if (iDeviceNum + 1 &gt; capDevices.Length)
{
throw new Exception("No video capture devices found at that index!");
}

try
{
// Set up the capture graph
SetupGraph( capDevices[iDeviceNum], iFrameRate, iWidth, iHeight, FileName);
}
catch
{
Dispose();
throw;
}
}

/// &lt;summary&gt; release everything. &lt;/summary&gt;
public void Dispose()
{
CloseInterfaces();
if (m_Bitmap != null)
{
m_Bitmap.UnlockBits(m_bmdLogo);
m_Bitmap = null;
m_bmdLogo = null;
}
}
// Destructor
~Capture()
{
CloseInterfaces();
}


/// &lt;summary&gt; capture the next image &lt;/summary&gt;
public void Start()
{
if (!m_bRunning)
{
int hr = m_mediaCtrl.Run();
DsError.ThrowExceptionForHR( hr );

m_bRunning = true;
}
}
// Pause the capture graph.
// Running the graph takes up a lot of resources. Pause it when it
// isn't needed.
public void Pause()
{
if (m_bRunning)
{
int hr = m_mediaCtrl.Pause();
DsError.ThrowExceptionForHR( hr );

m_bRunning = false;
}
}

/// &lt;summary&gt; Specify the logo file to write onto each frame &lt;/summary&gt;
public void SetLogo(string fileName)
{

//public Bitmap WaterMarkToImage(string fileName, string Filenameasp)
////{
// Bitmap bmp;
//bmp = new Bitmap(fileName);
// Graphics graphicsObject;
// int x, y;
//try
//{ //create graphics object from bitmap
//graphicsObject = Graphics.FromImage(bmp);
//}
// catch (Exception e)
//{
//Bitmap bmpNew = new Bitmap(bmp.Width, bmp.Height);
// graphicsObject = Graphics.FromImage(bmpNew);
// graphicsObject.DrawImage(bmp, new Rectangle(0, 0, bmpNew.Width, bmpNew.Height), 0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel);
// bmp = bmpNew;
//}
// int startsize = (bmp.Width / Filenameasp.Length);
//get the font size with respect to length of the string
//x and y cordinates to draw a string
//x = 0;
//y = bmp.Height / 2;
// y = 0;
// System.Drawing.StringFormat drawFormat = new System.Drawing.StringFormat(StringFormatFlags.DirectionVertical); -&gt; draws a vertical string for watermark
//System.Drawing.StringFormat drawFormat = new System.Drawing.StringFormat(StringFormatFlags.NoWrap);
//drawing string on Image
//graphicsObject.DrawString(Filenameasp, new Font("Verdana", startsize, FontStyle.Bold), new SolidBrush(Color.FromArgb(60, 255, 255, 255)), x, y, drawFormat);
//return a water marked image
//return (bmp);
// }




lock (this)
{
if (fileName.Length &gt; 0)
{
Bitmap m_Bitmap = new Bitmap(fileName);

Rectangle r = new Rectangle(0, 0, m_Bitmap.Width, m_Bitmap.Height);
//m_Bitmap.LockBits(r, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
m_bmdLogo = m_Bitmap.LockBits(r, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);

// m_Bitmap.SetResolution(imgPhoto.HorizontalResolution, imgPhoto.VerticalResolution);

}

else
{
if (m_Bitmap != null)
{
m_Bitmap.UnlockBits(m_bmdLogo);

m_Bitmap = null;
m_bmdLogo = null;
}
}
}
}


/// &lt;summary&gt; build the capture graph for grabber. &lt;/summary&gt;
private void SetupGraph(DsDevice dev, int iFrameRate, int iWidth, int iHeight, string FileName)
{
int hr;

ISampleGrabber sampGrabber = null;
IBaseFilter baseGrabFlt = null;
IBaseFilter capFilter = null;
IBaseFilter muxFilter = null;
IFileSinkFilter fileWriterFilter = null;
ICaptureGraphBuilder2 capGraph = null;

// Get the graphbuilder object
m_FilterGraph = new FilterGraph() as IFilterGraph2;
m_mediaCtrl = m_FilterGraph as IMediaControl;

#if DEBUG
m_rot = new DsROTEntry(m_FilterGraph);
#endif
try
{
// Get the ICaptureGraphBuilder2
capGraph = (ICaptureGraphBuilder2) new CaptureGraphBuilder2();

// Get the SampleGrabber interface
sampGrabber = (ISampleGrabber) new SampleGrabber();

// Start building the graph
hr = capGraph.SetFiltergraph( m_FilterGraph );
DsError.ThrowExceptionForHR( hr );

// Add the video device
hr = m_FilterGraph.AddSourceFilterForMoniker(dev.Mon, null, dev.Name, out capFilter);
DsError.ThrowExceptionForHR( hr );

baseGrabFlt = (IBaseFilter) sampGrabber;
ConfigureSampleGrabber(sampGrabber);

// Add the frame grabber to the graph
hr = m_FilterGraph.AddFilter(baseGrabFlt, "Ds.NET Grabber");
DsError.ThrowExceptionForHR(hr);

// If any of the default config items are set
//if (iFrameRate + iHeight + iWidth &gt; 0)
if (iFrameRate&gt; 0)
{
SetConfigParms(capGraph, capFilter, iFrameRate, iWidth, iHeight);
}

// Create a filter for the output avi file
hr = capGraph.SetOutputFileName(MediaSubType.Avi, FileName, out muxFilter, out fileWriterFilter);
DsError.ThrowExceptionForHR( hr );

// Connect everything together
hr = capGraph.RenderStream( PinCategory.Capture, MediaType.Video, capFilter, baseGrabFlt, muxFilter);
DsError.ThrowExceptionForHR( hr );

// Now that sizes are fixed, store the sizes
SaveSizeInfo(sampGrabber);
}
finally
{
if (fileWriterFilter != null)
{
Marshal.ReleaseComObject(fileWriterFilter);
fileWriterFilter = null;
}
if (muxFilter != null)
{
Marshal.ReleaseComObject(muxFilter);
muxFilter = null;
}
if (capFilter != null)
{
Marshal.ReleaseComObject(capFilter);
capFilter = null;
}
if (sampGrabber != null)
{
Marshal.ReleaseComObject(sampGrabber);
sampGrabber = null;
}
}
}

/// &lt;summary&gt; Read and store the properties &lt;/summary&gt;
private void SaveSizeInfo(ISampleGrabber sampGrabber)
{
int hr;

// Get the media type from the SampleGrabber
AMMediaType media = new AMMediaType();
hr = sampGrabber.GetConnectedMediaType( media );
DsError.ThrowExceptionForHR( hr );

if( (media.formatType != FormatType.VideoInfo) || (media.formatPtr == IntPtr.Zero) )
{
throw new NotSupportedException( "Unknown Grabber Media Format" );
}

// Grab the size info
VideoInfoHeader videoInfoHeader = (VideoInfoHeader) Marshal.PtrToStructure( media.formatPtr, typeof(VideoInfoHeader) );
m_videoWidth = videoInfoHeader.BmiHeader.Width;
m_videoHeight = videoInfoHeader.BmiHeader.Height;
m_stride = (m_videoWidth * (videoInfoHeader.BmiHeader.BitCount / 8));

DsUtils.FreeAMMediaType(media);
media = null;
}
/// &lt;summary&gt; Set the options on the sample grabber &lt;/summary&gt;
private void ConfigureSampleGrabber(ISampleGrabber sampGrabber)
{
int hr;
AMMediaType media = new AMMediaType();

// Set the media type to Video/RBG24
media.majorType = MediaType.Video;
media.subType = MediaSubType.RGB24;
media.formatType = FormatType.VideoInfo;
hr = sampGrabber.SetMediaType( media );
DsError.ThrowExceptionForHR( hr );

DsUtils.FreeAMMediaType(media);
media = null;

// Configure the samplegrabber callback
hr = sampGrabber.SetCallback( this, 1 );
DsError.ThrowExceptionForHR( hr );
}

// Set the Framerate, and video size
private void SetConfigParms(ICaptureGraphBuilder2 capGraph, IBaseFilter capFilter, int iFrameRate, int iWidth, int iHeight)
{
int hr;
object o;
AMMediaType media;
IAMStreamConfig videoStreamConfig;
IAMVideoControl videoControl = capFilter as IAMVideoControl;

// Find the stream config interface
hr = capGraph.FindInterface(
PinCategory.Capture, MediaType.Video, capFilter, typeof(IAMStreamConfig).GUID, out o );

videoStreamConfig = o as IAMStreamConfig;
try
{
if (videoStreamConfig == null)
{
throw new Exception("Failed to get IAMStreamConfig");
}

hr = videoStreamConfig.GetFormat(out media);
DsError.ThrowExceptionForHR( hr );

// copy out the videoinfoheader
VideoInfoHeader v = new VideoInfoHeader();
Marshal.PtrToStructure( media.formatPtr, v );

// if overriding the framerate, set the frame rate
if (iFrameRate &gt; 0)
{
v.AvgTimePerFrame = 10000000 / iFrameRate;
// v.AvgTimePerFrame = iFrameRate;
}

// if overriding the width, set the width
if (iWidth &gt; 0)
{
v.BmiHeader.Width = iWidth;
}

// if overriding the Height, set the Height
if (iHeight &gt; 0)
{
v.BmiHeader.Height = iHeight;
}

// Copy the media structure back
Marshal.StructureToPtr( v, media.formatPtr,false);

// Set the new format
hr = videoStreamConfig.SetFormat( media );
DsError.ThrowExceptionForHR( hr );

DsUtils.FreeAMMediaType(media);
media = null;

// Fix upsidedown video
if (videoControl != null)
{
VideoControlFlags pCapsFlags;

IPin pPin = DsFindPin.ByCategory(capFilter, PinCategory.Capture,0);
hr = videoControl.GetCaps(pPin, out pCapsFlags);
// DsError.ThrowExceptionForHR( hr );

if ((pCapsFlags &amp; VideoControlFlags.FlipVertical) &gt; 0)
{
hr = videoControl.GetMode(pPin, out pCapsFlags);
DsError.ThrowExceptionForHR(hr);

hr = videoControl.SetMode(pPin, 0);
}
}
}
finally
{
Marshal.ReleaseComObject(videoStreamConfig);
}
}

/// &lt;summary&gt; Shut down capture &lt;/summary&gt;
private void CloseInterfaces()
{
int hr;

try
{
if( m_mediaCtrl != null )
{
// Stop the graph
hr = m_mediaCtrl.Stop();
m_mediaCtrl = null;
m_bRunning = false;
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}

#if DEBUG
if (m_rot != null)
{
m_rot.Dispose();
}
#endif

if (m_FilterGraph != null)
{
Marshal.ReleaseComObject(m_FilterGraph);
m_FilterGraph = null;
}
GC.Collect();
}


/// &lt;summary&gt; sample callback, NOT USED. &lt;/summary&gt;
int ISampleGrabberCB.SampleCB(double SampleTime, IMediaSample pSample)
{
Marshal.ReleaseComObject(pSample);
return 0;
}

/// &lt;summary&gt; buffer callback, COULD BE FROM FOREIGN THREAD. &lt;/summary&gt;
int ISampleGrabberCB.BufferCB( double SampleTime, IntPtr pBuffer, int BufferLen )
{
// Avoid the possibility that someone is calling SetLogo() at this instant
lock (this)
{
if (m_bmdLogo != null)
{
IntPtr ipSource = m_bmdLogo.Scan0;
IntPtr ipDest = pBuffer;

for (int x=0; x &lt;m_bmdLogo.Height; x++)
{
CopyMemory(ipDest, ipSource, (uint)m_bmdLogo.Stride);

//.RotateFlip(RotateFlipType.RotateNoneFlipY);
ipDest = ((IntPtr)(ipDest.ToInt32() + m_stride));
ipSource = (IntPtr)(ipSource.ToInt32() + m_bmdLogo.Stride);
}



}

}
return 0;
}
}
}
GeneralRe: required c# Vedio watermarking code Pin
Nguyen Congbang25-Oct-16 17:29
Nguyen Congbang25-Oct-16 17:29 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.