PDF Merger and Protector






4.97/5 (12 votes)
PDF MERGER and PROTECTOR is the best pdf merger software which is fast and powerful way to join(Merge) PDF files with password protection as well as you can apply stamper with either any type of image or text. Using this utility you don’t required installation of Adobe Acrobat. Looks Exciting ???
- Complete Usage Document
- Complete Technical Guide Line
- Download Latest Source Code - 3.7 MB
- Download Latest Setup - 1.8 MB

Password Protected PDF | Content Protected with Text | Content Protected with Image |
![]() | ![]() | ![]() |
Introduction
PDF Merger and Protector is a free tool for merge and protect your PDF with password and stamping. this tools has several features like:
- Merge any number of PDF files into single PDF file.
- Regenerate page number for every pages.
- No need to install "Adobe Acrobat and Reader".
- It is very simple to use and professional look and feel.
- You can protect your content with password to prevent unauthorized opening, copying or printing.
- You can protect your content with Copyright, Trademark, License or Watermark using text or any image.
Background
This tool you can use any area or field like :
- If you are reader, you can manage every tutorials with different Author Wise.
- If your are employee, You can keep your monthly salary sleep into Financial Year Wise.
- If you are payer, you can keep record of Mobile Bill, Electricity Bill into Category Wise.
- Filing or Unification Purposes.
- Send File via Email instead of list of files.
- Taking Print.
- View in Chronological Order.
Using the code
This application is developed with help of iTextSharp library. I have written complete guide line for How to Use and Technical Usage Guide at Software Development Company site.
Here i am giving you general idea behind PDF Merger and Protector with code and flow. Before starting go-through article, you should have knowledge about following.
Prerequisite
Variable Declaration
//this is the notify file merging process at specified interval private NotifyProgress m_clsNotifyDelegate; //Declaration of thread private Thread m_clsThread; //Provides a way to synchronously or asynchronously execute a delegate private ISynchronizeInvoke m_clsSynchronizingObject; //this is the definition of the progress delegate - it defines the "signature" of the routine... //NotifyProgress has four arguments TotalFiles: total number of files to merge ProcessFileIndex: currently merging file index TotalPages: total number of pages of all files PageIndex: currently merging file page index. public delegate void NotifyProgress(int TotalFiles, int ProcessFileIndex, int TotalPages, int PageIndex);
Properties
//Gets or Sets the Destination File Path. Where save generated file.
public string DestinationFile { get;set; }
//Processing or current File Index,File Name and Total Pages and Process Page Index.
public int ProcessFileIndex { get;set; }
public string ProcessFileName { get;set; }
public int ProcessFilePages { get;set; }
public int ProcessFilePageIndex { get;set; }
//Total Files and Total Pages to be merged in a single file (pdf).
public int TotalFiles { get;set; }
public int TotalPages { get;set; }
public int PageIndex { get;set; }
Constructor
- This class object will requires two parameter “synchronizing object” be passed to it – this tells the class what context “notify delegates” should run in
public PDFManager(ISynchronizeInvoke SynchronizingObject, NotifyProgress NotifyDelegate)
{
m_clsSynchronizingObject = SynchronizingObject;
m_clsNotifyDelegate = NotifyDelegate;
}
Public Methods
- AddFile This method will add list of files into file list. File list contain all those files to be merged into single.
public void AddFile(string pathnname)
{
fileList.Add(pathnname);
}
- Execute Execute method will combine all files into single (pdf) file.
public void Execute()
{
//Method will execute in background thread, it will continuous call “MeregDocs” method to update or notify to the users screen.
m_clsThread = new System.Threading.Thread(MergeDocs);
m_clsThread.Name = "PDF Mereger Background Thread";
m_clsThread.IsBackground = true;
m_clsThread.Start();
}
Private Methods
- MergeDocs This method is a heart of the entire merging process. It will merge all the files into single and save generated file at destination location. This method is very explanatory so no need write more for that.
private void MergeDocs() { string value = ""; setting = new SettingManager(Path.Combine(Application.StartupPath, "settings.ini")); //------------------------------------------------------------------------------------ //Step 1: Create a Docuement-Object //------------------------------------------------------------------------------------ Document document = new Document(); try { //------------------------------------------------------------------------------------ //Step 2: we create a writer that listens to the document //------------------------------------------------------------------------------------ PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(destinationfile, FileMode.Create)); //------------------------------------------------------------------------------------ //Step 3: Set Password Protection if you are set for it //------------------------------------------------------------------------------------ SetPasswordProtection(writer); //------------------------------------------------------------------------------------ //Step 4: Open the document //------------------------------------------------------------------------------------ document.Open(); PdfContentByte cb = writer.DirectContent; PdfImportedPage page; PdfReader reader; int rotation = 0; ProcessFileIndex = 0; TotalFiles = fileList.Count; TotalPages = 0; PageIndex = 0; foreach (string filename in fileList) { reader = new PdfReader(filename); //Gets the number of pages to process TotalPages += reader.NumberOfPages; } //Loops for each file that has been listed foreach (string filename in fileList) { //Create a reader for the document reader = new PdfReader(filename); ProcessFileIndex++; ProcessFileName = filename; //Gets the number of pages to process ProcessFilePages = reader.NumberOfPages; ProcessFilePageIndex = 0; while (ProcessFilePageIndex < ProcessFilePages) { ProcessFilePageIndex++; PageIndex++; NotifyUI(TotalFiles, ProcessFileIndex, TotalPages, PageIndex); Thread.Sleep(1); document.SetPageSize(reader.GetPageSizeWithRotation(1)); document.NewPage(); //Insert to Destination on the first page if (ProcessFilePageIndex == 1) { Chunk fileRef = new Chunk(" "); fileRef.SetLocalDestination(filename); document.Add(fileRef); } page = writer.GetImportedPage(reader, ProcessFilePageIndex); rotation = reader.GetPageRotation(ProcessFilePageIndex); if (rotation == 90 || rotation == 270) cb.AddTemplate(page, 0, -1f, 1f, 0, 0, reader.GetPageSizeWithRotation(ProcessFilePageIndex).Height); else cb.AddTemplate(page, 1f, 0, 0, 1f, 0, 0); //------------------------------------------------------------------------------------ //Step 4: Set Page Number and Formatting if you are set for it //------------------------------------------------------------------------------------ value = setting.Read("Page Number and Formatting", "AollowPageFormatting"); if (!string.IsNullOrEmpty(value) && Convert.ToBoolean(value) == true) { // we tell the ContentByte we're ready to draw text cb.BeginText(); // we draw some text on a perticular position BaseFont bf = BaseFont.CreateFont(BaseFont.TIMES_ROMAN, BaseFont.CP1252, false); cb.SetFontAndSize(bf, 12); value = setting.Read("Page Number and Formatting", "PageText"); string PageNumberText = ""; if (!string.IsNullOrEmpty(value)) PageNumberText = value; string isPageNumber = setting.Read("Page Number and Formatting", "PageNumber"); string isTotalPageNumber = setting.Read("Page Number and Formatting", "TotalPage"); if (!string.IsNullOrEmpty(isPageNumber) && Convert.ToBoolean(isPageNumber) == true && !string.IsNullOrEmpty(isTotalPageNumber) && Convert.ToBoolean(isTotalPageNumber) == true) { PageNumberText = string.Format("{0} {1} of {2}", PageNumberText, PageIndex, TotalPages); } else if (!string.IsNullOrEmpty(isPageNumber) && Convert.ToBoolean(isPageNumber) == true) { PageNumberText = string.Format("{0} {1}", PageNumberText, PageIndex); } else if (!string.IsNullOrEmpty(isTotalPageNumber) && Convert.ToBoolean(isTotalPageNumber) == true) { PageNumberText = string.Format("{0} {1}", PageNumberText, TotalPages); } Coordinates Coordinates = GetPageAlignment(PageNumberText, document); cb.SetTextMatrix(Coordinates.X, Coordinates.Y); cb.ShowText(PageNumberText); // we tell the contentByte, we've finished drawing text cb.EndText(); } } } } catch (Exception e) { MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } finally { //------------------------------------------------------------------------------------ //Step 5: Close the merged pdf document //------------------------------------------------------------------------------------ document.Close(); //------------------------------------------------------------------------------------ //Step 6: Applying watermark Image of Text on PDF //------------------------------------------------------------------------------------ bool isWatermarkEnabled = Convert.ToBoolean(setting.Read("Watermark Image or Write Text", "IsWatermarkEnabled")); if (isWatermarkEnabled) { bool isImagePath = Convert.ToBoolean(setting.Read("Watermark Image or Write Text", "IsImagePath")); string filePath = setting.Read("Merege PDF Location", "PDFLocation"); if (string.IsNullOrEmpty(filePath) || !Directory.Exists(filePath)) { string newFilePath = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "MergedFiles"); setting.Write("Merege PDF Location", "PDFLocation", newFilePath); MessageBox.Show(string.Format("Directory does not exists at {0}\n Default path is {1}", filePath, newFilePath), "Directory Not Found", MessageBoxButtons.OK); filePath = newFilePath; } //Step 6.1: Applying watermark Image if image option was selected filePath = Path.Combine(filePath, DateTime.Now.Ticks + ".pdf"); if (isImagePath) { string imagePath = setting.Read("Watermark Image or Write Text", "ImagePath"); if (imagePath != null && imagePath != "") { if (File.Exists(imagePath)) { AddWatermarkImage(DestinationFile, filePath, imagePath); File.Delete(DestinationFile); File.Copy(filePath, DestinationFile); File.Delete(filePath); } else { MessageBox.Show(string.Format("File could not be found at {0}", imagePath), "File Not Found", MessageBoxButtons.OK); } } } else { //Step 6.2: Applying watermark text if text option was selected string watermarkText = setting.Read("Watermark Image or Write Text", "WatermarkText"); string watermarkFont = setting.Read("Watermark Image or Write Text", "WatermarkFont"); string watermarkColor = setting.Read("Watermark Image or Write Text", "WatermarkColor"); iTextSharp.text.pdf.BaseFont font = ConvertStringToFont(watermarkFont); BaseColor color = ConvertStringToColor(watermarkColor); AddWatermarkText(sourceFile: DestinationFile, outputFile: filePath, watermarkText: watermarkText, watermarkFont: font, watermarkFontColor: color); File.Delete(DestinationFile); File.Copy(filePath, DestinationFile); File.Delete(filePath); } } //Step 7: Destroy PDF Merger object from the memory and release all the objects. m_clsNotifyDelegate = null; m_clsThread = null; m_clsSynchronizingObject = null; fileList.Clear(); } }
- SetPasswordProtection This method will protect your document with user name and password, without user name and password nobody can open it.
private PdfWriter SetPasswordProtection(PdfWriter writer)
{
try
{
string value = setting.Read("File Protection", "AllowFileProtection");
if (!string.IsNullOrEmpty(value) && Convert.ToBoolean(value) == true)
{
string password = setting.Read("File Protection", "Password");
string ownerPassword = "imdadhusen";
if (!string.IsNullOrEmpty(password))
{
int Permission = 0;
bool Strength = false;
value = setting.Read("File Protection", "AllowCopy");
if (!string.IsNullOrEmpty(value)) Permission = 16;
value = setting.Read("File Protection", "AllowPrinting");
if (!string.IsNullOrEmpty(value)) Permission += 2052;
value = setting.Read("File Protection", "EncryptionStrength");
if (!string.IsNullOrEmpty(value) && value == "strength128bits") Strength = true;
writer.SetEncryption(Strength, password, ownerPassword, Permission);
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
return writer;
}
- ConvertStringToFont This method will set Watermark Text font as per selected by you.
private BaseFont ConvertStringToFont(string fontName) { iTextSharp.text.pdf.BaseFont font = null; try { if (string.IsNullOrEmpty(fontName) == false) { switch (fontName.ToUpper()) { case "COURIER": case "HELVETICA": font = BaseFont.CreateFont(CultureInfo.CurrentCulture.TextInfo.ToTitleCase(fontName), BaseFont.CP1252, BaseFont.NOT_EMBEDDED); break; case "TIMES": font = BaseFont.CreateFont(BaseFont.TIMES_BOLD, BaseFont.CP1252, BaseFont.NOT_EMBEDDED); break; } } } catch (Exception ex) { MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } return font; }
- ConvertStringToColor This method will set font color of your Watermark Text
private BaseColor ConvertStringToColor(string colorName) BaseColor color = null; if (string.IsNullOrEmpty(colorName.ToLower()) == false) { Color c = Color.FromName(colorName.ToLower()); color = new BaseColor(c.R, c.G, c.B); } return color; }
- NotifyUI This is the method that determines how to interact with the calling thread, whether by delegate or event. It will update status of merging process on the users screen.
private void NotifyUI(int TotalFiles, int ProcessFileIndex, int TotalPages, int PageIndex)
{
try
{
object[] args = { TotalFiles, ProcessFileIndex, TotalPages, PageIndex };
//call the delegate, specifying the context in which to run...
m_clsSynchronizingObject.Invoke(m_clsNotifyDelegate, args);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private Coordinates GetPageAlignment(string PageNumberText, Document document) { Coordinates Coordinates = new PDFLibrary.Coordinates(); try { frmSettings frmsetting = new frmSettings(); PageNumberSize PageNumberSize = frmsetting.GetPageNumberSize(PageNumberText); float TMargin = document.TopMargin; float RMargin = document.RightMargin; float BMargin = document.BottomMargin; float LMargin = document.LeftMargin; setting = new SettingManager(Path.Combine(Application.StartupPath, "settings.ini")); iTextSharp.text.Rectangle pageSize = document.PageSize; string value = setting.Read("Page Number and Formatting", "VerticalAlignment"); switch (value) { case "top": Coordinates.Y = pageSize.Height - (PageNumberSize.Height + TMargin); break; case "middle": Coordinates.Y = (pageSize.Height - (PageNumberSize.Height + TMargin)) / 2; break; case "bottom": Coordinates.Y = BMargin - PageNumberSize.Height; break; } value = setting.Read("Page Number and Formatting", "HorizontalAlignment"); switch (value) { case "left": Coordinates.X = LMargin; break; case "center": Coordinates.X = (pageSize.Width - (PageNumberSize.Width + RMargin)) / 2; break; case "right": Coordinates.X = pageSize.Width - (PageNumberSize.Width + RMargin); break; } } catch (Exception ex) { MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } return Coordinates; }
private void AddWatermarkImage(string sourceFile, string outputFile, string watermarkImage) { try { using (Stream inputPdfStream = new FileStream(sourceFile, FileMode.Open, FileAccess.Read, FileShare.Read)) using (Stream inputImageStream = new FileStream(watermarkImage, FileMode.Open, FileAccess.Read, FileShare.Read)) using (Stream outputPdfStream = new FileStream(outputFile, FileMode.Create, FileAccess.Write, FileShare.None)) { PdfReader reader; string userPassword = "imdadhusen"; //Imdadhusen is a master Password but you can unlock with User Password also. string ownerPassword = "imdadhusen"; try { reader = new PdfReader(sourceFile); } catch (BadPasswordException) { System.Text.Encoding enc = System.Text.Encoding.ASCII; Byte[] myByteArray = enc.GetBytes(userPassword); reader = new PdfReader(sourceFile, myByteArray); } var stamper = new PdfStamper(reader, outputPdfStream); string value = setting.Read("File Protection", "AllowFileProtection"); if (!string.IsNullOrEmpty(value) && Convert.ToBoolean(value) == true) { userPassword = setting.Read("File Protection", "Password"); if (!string.IsNullOrEmpty(userPassword)) { int Permission = 0; bool Strength = false; value = setting.Read("File Protection", "AllowCopy"); if (!string.IsNullOrEmpty(value)) Permission = 16; value = setting.Read("File Protection", "AllowPrinting"); if (!string.IsNullOrEmpty(value)) Permission += 2052; value = setting.Read("File Protection", "EncryptionStrength"); if (!string.IsNullOrEmpty(value) && value == "strength128bits") Strength = true; stamper.SetEncryption(Strength, userPassword, ownerPassword, Permission); } } iTextSharp.text.Rectangle rect = null; float X = 0; float Y = 0; int pageCount = 0; PdfContentByte underContent = null; rect = reader.GetPageSizeWithRotation(1); pageCount = reader.NumberOfPages; reader.Close(); iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(watermarkImage); if (img.Width > rect.Width || img.Height > rect.Height) { img.ScaleToFit(rect.Width, rect.Height); X = (rect.Width - img.ScaledWidth) / 2; Y = (rect.Height - img.ScaledHeight) / 2; } else { X = (rect.Width - img.Width) / 2; Y = (rect.Height - img.Height) / 2; } img.SetAbsolutePosition(X, Y); for (int i = 1; i <= pageCount; i++) { underContent = stamper.GetUnderContent(i); underContent.AddImage(img); } stamper.Close(); inputPdfStream.Close(); } } catch (Exception ex) { MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
private void AddWatermarkText(string sourceFile, string outputFile, string watermarkText, iTextSharp.text.pdf.BaseFont watermarkFont = null, float watermarkFontSize = 48, BaseColor watermarkFontColor = null, float watermarkFontOpacity = 0.3f, float watermarkRotation = 45f) { using (Stream inputPdfStream = new FileStream(sourceFile, FileMode.Open, FileAccess.Read, FileShare.Read)) using (Stream outputPdfStream = new FileStream(outputFile, FileMode.Create, FileAccess.Write, FileShare.None)) { PdfReader reader; string userPassword = "imdadhusen"; //Imdadhusen is a master Password but you can unlock with User Password also. string ownerPassword = "imdadhusen"; try { reader = new PdfReader(sourceFile); } catch (BadPasswordException) { System.Text.Encoding enc = System.Text.Encoding.ASCII; Byte[] myByteArray = enc.GetBytes(userPassword); reader = new PdfReader(sourceFile, myByteArray); } var stamper = new PdfStamper(reader, outputPdfStream); string value = setting.Read("File Protection", "AllowFileProtection"); if (!string.IsNullOrEmpty(value) && Convert.ToBoolean(value) == true) { userPassword = setting.Read("File Protection", "Password"); if (!string.IsNullOrEmpty(userPassword)) { int Permission = 0; bool Strength = false; value = setting.Read("File Protection", "AllowCopy"); if (!string.IsNullOrEmpty(value)) Permission = 16; value = setting.Read("File Protection", "AllowPrinting"); if (!string.IsNullOrEmpty(value)) Permission += 2052; value = setting.Read("File Protection", "EncryptionStrength"); if (!string.IsNullOrEmpty(value) && value == "strength128bits") Strength = true; stamper.SetEncryption(Strength, userPassword, ownerPassword, Permission); } } iTextSharp.text.Rectangle rect = null; PdfGState gstate = null; int pageCount = 0; PdfContentByte underContent = null; rect = reader.GetPageSizeWithRotation(1); if (watermarkFont == null) watermarkFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED); if (watermarkFontColor == null) watermarkFontColor = BaseColor.BLUE; gstate = new PdfGState(); gstate.FillOpacity = watermarkFontOpacity; gstate.StrokeOpacity = watermarkFontOpacity; pageCount = reader.NumberOfPages; for (int i = 1; i <= pageCount; i++) { underContent = stamper.GetUnderContent(i); var _with1 = underContent; _with1.SaveState(); _with1.SetGState(gstate); _with1.SetColorFill(watermarkFontColor); _with1.BeginText(); _with1.SetFontAndSize(watermarkFont, watermarkFontSize); _with1.SetTextMatrix(30, 30); _with1.ShowTextAligned(Element.ALIGN_CENTER, watermarkText, rect.Width / 2, rect.Height / 2, watermarkRotation); _with1.EndText(); _with1.RestoreState(); } stamper.Close(); inputPdfStream.Close(); } }
public class Coordinates
{
public float X { get; set; }
public float Y { get; set; }
}
- Usage
- Password protection.
- Protect from copy and print.
- Custom page number and alignment.
- Watermark content protection.
- Image
- Text
- Add name space to your project
using PDFMerger;
PDFLibrary.PDFManager merge;
merge = new PDFLibrary.PDFManager(this, new PDFLibrary.PDFManager.NotifyProgress(DelegateProgress));
private void DelegateProgress(int TotalFiles, int ProcessFileIndex, int TotalPages, int PageIndex) { try { if (merge != null && merge.TotalPages > 0) { this.Invoke((MethodInvoker)delegate { int pagepercent = merge.ProcessFilePageIndex * 100 / merge.ProcessFilePages; TextProgressBar pb = (TextProgressBar)lstFiles.GetEmbeddedControl(3, merge.ProcessFileIndex - 1); pb.Text = string.Format("{0:00} %", pagepercent); pb.Value = pagepercent; int percent = merge.PageIndex * 100 / merge.TotalPages; ProgressStripItem statusProgrss = (ProgressStripItem)tsStatus.Items[1]; statusProgrss.TextProgressBar.Value = percent; statusProgrss.TextProgressBar.Text = string.Format("{0:00}%", percent); DisplayStatusMessage(string.Format("File Name:{0}, File {1:00} of {2:00}, Page {3:00} of {4:00}", Path.GetFileName(merge.ProcessFileName), merge.ProcessFileIndex, merge.TotalFiles, merge.ProcessFilePageIndex, merge.ProcessFilePages)); if (percent >= 100) { DisplayStatusMessage(string.Format("File merged successfully at {0}", merge.DestinationFile)); for (int i = 0; i < lstFiles.Items.Count; i++) { lstFiles.RemoveEmbeddedControl(lstFiles.GetEmbeddedControl(3, i)); } ClearList(); merge = null; } }); } else { ((ProgressStripItem)tsStatus.Items[1]).TextProgressBar.Text = string.Format("{0:00}%", 0); DisplayStatusMessage(string.Format("File {0:00} of {1:00}, Page {2:00} of {3:00}", 0, 0, 0, 0)); } } catch (Exception ex) { MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
merge.DestinationFile = “D:/MergedFiles/”;
merge.Execute();
- File Protection Setting
- Encryption Strength
- Password
- Allow Copy
- Allow Printing
- Page Number and Formatting
- Vertical Alignment
- Horizontal Alignment
- Page Number Format
- Watermark Image or Text
- Watermark Image Path
- Watermark Text Value
- Font Name
- Font Color
- Merged PDF Location Using following code you can Get and Set of your global settings in (.ini) file.
- Declaration
SettingManager setting = new SettingManager(Path.Combine(Application.StartupPath, "settings.ini"));
string value = setting.Read("Page Number and Formatting", "AollowPageFormatting");
setting.Write("File Protection", "Password", “imdadhusen”);
Comments and Feedback
Creating and maintaining PDFMerger library has required – and still does – a considerable amount of work and effort.PDFMerger is free, and I hope that you find it useful. If you’d like to support future development and new product features, please make a your valuable comments, feedback, suggestions or appreciation via Comments, mail, messages or rating.
These efforts are used to cover and improve product efficiency.