using org.pdfclown.documents; using org.pdfclown.files; using org.pdfclown.objects; using org.pdfclown.tools; using System; using io = System.IO; using System.Collections.Generic; using System.Text; namespace org.pdfclown.samples.cli { /** This sample demonstrates how to manipulate the pages collection within a PDF document, to perform page data size calculations, additions, movements, removals, extractions and splits of groups of pages. */ public class PageManagementSample : Sample { internal enum ActionEnum { PageDataSizeCalculation, PageAddition, PageMovement, PageRemoval, PageExtraction, DocumentMerge, DocumentBurst, DocumentSplitByPageIndex, DocumentSplitOnMaximumFileSize } public override bool Run( ) { string mainFilePath = PromptPdfFileChoice("Please select a PDF file"); // Open the PDF file! File mainFile = new File(mainFilePath); Document mainDocument = mainFile.Document; Pages mainPages = mainDocument.Pages; int mainPagesCount = mainPages.Count; ActionEnum action = PromptAction(); switch(action) { case ActionEnum.PageDataSizeCalculation: { Console.WriteLine("\nThis algorithm calculates the data size (expressed in bytes) of the selected document's pages."); Console.WriteLine("Legend:"); Console.WriteLine(" * full: page data size encompassing all its dependencies (like shared resources) -- this is the size of the page when extracted as a single-page document;"); Console.WriteLine(" * differential: additional page data size -- this is the extra-content that's not shared with previous pages;"); Console.WriteLine(" * incremental: data size of the page sublist encompassing all the previous pages and the current one.\n"); // Calculating the page data sizes... HashSet visitedReferences = new HashSet(); long incrementalDataSize = 0; foreach(Page page in mainPages) { long pageFullDataSize = PageManager.GetSize(page); long pageDifferentialDataSize = PageManager.GetSize(page, visitedReferences); incrementalDataSize += pageDifferentialDataSize; Console.WriteLine( "Page " + (page.Index+1) + ": " + pageFullDataSize + " (full); " + pageDifferentialDataSize + " (differential); " + incrementalDataSize + " (incremental)" ); } } break; case ActionEnum.PageAddition: { // Source file. string sourceFilePath = PromptPdfFileChoice("Select the source PDF file"); File sourceFile = new File(sourceFilePath); // Source page collection. Pages sourcePages = sourceFile.Document.Pages; // Source page count. int sourcePagesCount = sourcePages.Count; // First page to add. int fromSourcePageIndex = PromptPageChoice("Select the start source page to add", sourcePagesCount); // Last page to add. int toSourcePageIndex = PromptPageChoice("Select the end source page to add", fromSourcePageIndex + 1, sourcePagesCount) + 1; // Target position. int targetPageIndex = PromptPageChoice("Select the position where to insert the source pages", mainPagesCount + 1); // Add the chosen page range to the main document! new PageManager(mainDocument).Add( targetPageIndex, sourcePages.GetSlice( fromSourcePageIndex, toSourcePageIndex ) ); // Serialize the main file! Serialize(mainFile, action); } break; case ActionEnum.PageMovement: { // First page to move. int fromSourcePageIndex = PromptPageChoice("Select the start page to move", mainPagesCount); // Last page to move. int toSourcePageIndex = PromptPageChoice("Select the end page to move", fromSourcePageIndex + 1, mainPagesCount) + 1; // Target position. int targetPageIndex = PromptPageChoice("Select the position where to insert the pages", mainPagesCount + 1); // Move the chosen page range! new PageManager(mainDocument).Move( fromSourcePageIndex, toSourcePageIndex, targetPageIndex ); // Serialize the main file! Serialize(mainFile, action); } break; case ActionEnum.PageRemoval: { // First page to remove. int fromPageIndex = PromptPageChoice("Select the start page to remove", mainPagesCount); // Last page to remove. int toPageIndex = PromptPageChoice("Select the end page to remove", fromPageIndex + 1, mainPagesCount) + 1; // Remove the chosen page range! new PageManager(mainDocument).Remove( fromPageIndex, toPageIndex ); // Serialize the main file! Serialize(mainFile, action); } break; case ActionEnum.PageExtraction: { // First page to extract. int fromPageIndex = PromptPageChoice("Select the start page", mainPagesCount); // Last page to extract. int toPageIndex = PromptPageChoice("Select the end page", fromPageIndex + 1, mainPagesCount) + 1; // Extract the chosen page range! Document targetDocument = new PageManager(mainDocument).Extract( fromPageIndex, toPageIndex ); // Serialize the target file! Serialize(targetDocument.File, action); } break; case ActionEnum.DocumentMerge: { // Source file. string sourceFilePath = PromptPdfFileChoice("Select the source PDF file"); File sourceFile = new File(sourceFilePath); // Append the chosen source document to the main document! new PageManager(mainDocument).Add(sourceFile.Document); // Serialize the main file! Serialize(mainFile, action); } break; case ActionEnum.DocumentBurst: { // Split the document into single-page documents! IList splitDocuments = new PageManager(mainDocument).Split(); // Serialize the split files! int index = 0; foreach(Document splitDocument in splitDocuments) {Serialize(splitDocument.File, action, ++index, false);} } break; case ActionEnum.DocumentSplitByPageIndex: { // Number of splits to apply to the source document. int splitCount; try {splitCount = Int32.Parse(PromptChoice("Number of split positions: "));} catch {splitCount = 0;} // Split positions within the source document. int[] splitIndexes = new int[splitCount]; { int prevSplitIndex = 0; for(int index = 0; index < splitCount; index++) { int splitIndex = PromptPageChoice("Position " + (index + 1) + " of " + splitCount, prevSplitIndex + 1, mainPagesCount); splitIndexes[index] = splitIndex; prevSplitIndex = splitIndex; } } // Split the document at the chosen positions! IList splitDocuments = new PageManager(mainDocument).Split(splitIndexes); // Serialize the split files! { int index = 0; foreach(Document splitDocument in splitDocuments) {Serialize(splitDocument.File, action, ++index, false);} } } break; case ActionEnum.DocumentSplitOnMaximumFileSize: { // Maximum file size. long maxDataSize; { long mainFileSize = new io::FileInfo(mainFilePath).Length; int kbMaxDataSize; do { try {kbMaxDataSize = Int32.Parse(PromptChoice("Max file size (KB): "));} catch {kbMaxDataSize = 0;} } while(kbMaxDataSize == 0); maxDataSize = kbMaxDataSize << 10; if(maxDataSize > mainFileSize) {maxDataSize = mainFileSize;} } // Split the document on maximum file size! IList splitDocuments = new PageManager(mainDocument).Split(maxDataSize); // Serialize the split files! { int index = 0; foreach(Document splitDocument in splitDocuments) {Serialize(splitDocument.File, action, ++index, false);} } } break; } return true; } private ActionEnum PromptAction( ) { ActionEnum[] actions = (ActionEnum[])Enum.GetValues(typeof(ActionEnum)); IDictionary options = new Dictionary(); for( int actionIndex = 0, actionsLength = actions.Length; actionIndex < actionsLength; actionIndex++ ) {options[actionIndex.ToString()] = actions[actionIndex].GetDescription();} try {return actions[Int32.Parse(PromptChoice(options))];} catch {return actions[0];} } /** Serializes the specified PDF file. File to serialize. Generator. */ private void Serialize( File file, ActionEnum action ) {Serialize(file, action, null, true);} /** Serializes the specified PDF file. File to serialize. Generator. File index. Whether to allow user choice of serialization mode. */ private void Serialize( File file, ActionEnum action, int? index, bool chooseMode ) { Serialize( file, GetType().Name + "_" + action.ToString() + (index.HasValue ? "." + index.Value : ""), chooseMode ); } } internal static class ActionEnumExtension { public static string GetDescription( this PageManagementSample.ActionEnum value ) { StringBuilder builder = new StringBuilder(); foreach(char c in value.ToString()) { if(Char.IsUpper(c) && builder.Length > 0) {builder.Append(" ");} builder.Append(c); } return builder.ToString(); } } }