Example #1
0
func MergeFiles(dest string, sources ...string) error {
	merged, err := pdf.Create(dest)
	if err != nil {
		return fmt.Errorf("create %q: %v", dest, err)
	}

	// because pdf files are mmap'ed and objects are zero copied
	// the files must remain open until merged is saved
	closers := make([]io.Closer, 0, len(sources))
	defer func() {
		for _, c := range closers {
			_ = c.Close()
		}
	}()

	// add the contents of each pdf into the merged pdf
	// collects the roots of each pdf
	roots := make([]pdf.ObjectReference, 0, len(sources))
	for _, fn := range sources {
		file, err := pdf.Open(fn)
		if err != nil {
			return fmt.Errorf("open %q: %v", fn, err)
		}
		closers = append(closers, file)

		_, root, err := copyReferencedObjects(map[pdf.ObjectReference]pdf.ObjectReference{}, merged, file, file.Root)
		if err != nil {
			return err
		}
		roots = append(roots, root.(pdf.ObjectReference))
		merged.Root = root.(pdf.ObjectReference)
	}

	// get the catalogs for each of the pdfs for merging their contents
	catalogs := make([]pdf.Dictionary, 0, len(roots))
	for _, root := range roots {
		catalogs = append(catalogs, merged.Get(root).(pdf.Dictionary))
	}

	// merge the page trees
	pageTreeRef, err := mergePageTrees(merged, catalogs)
	if err != nil {
		return err
	}

	// create a new root
	merged.Root, err = merged.Add(pdf.Dictionary{
		"Type":  pdf.Name("Catalog"),
		"Pages": pageTreeRef,
	})
	if err != nil {
		return err
	}

	return merged.Save()
}
Example #2
0
func appendPDF(newPDFfilename string, filenames []string) {
	merged, err := pdf.Create(newPDFfilename)
	if err != nil {
		log.Fatalln(err)
	}

	// add the contents of each pdf into the merged pdf
	// collects the roots of each pdf
	roots := make([]pdf.ObjectReference, 0, len(filenames))
	for _, filename := range filenames {
		file, err := pdf.Open(filename)
		if err != nil {
			log.Fatalln(err)
		}
		// because pdf files are mmap'ed and objects are zero copied
		// the files must remain open until merged is saved
		defer func() {
			err := file.Close()
			if err != nil {
				log.Fatalln(err)
			}
		}()

		_, root := copyReferencedObjects(map[pdf.ObjectReference]pdf.ObjectReference{}, merged, file, file.Root)
		roots = append(roots, root.(pdf.ObjectReference))
		merged.Root = root.(pdf.ObjectReference)
	}

	// get the catalogs for each of the pdfs for merging their contents
	catalogs := make([]pdf.Dictionary, 0, len(roots))
	for _, root := range roots {
		catalogs = append(catalogs, merged.Get(root).(pdf.Dictionary))
	}

	// merge the page trees
	pageTreeRef := mergePageTrees(merged, catalogs)

	// create a new root
	merged.Root, err = merged.Add(pdf.Dictionary{
		"Type":  pdf.Name("Catalog"),
		"Pages": pageTreeRef,
	})
	if err != nil {
		log.Fatalln(err)
	}

	err = merged.Save()
	if err != nil {
		log.Fatalln(err)
	}
}
Example #3
0
File: h7.go Project: nathankerr/pdf
// create the minimal file described in H.2
func createMinimalFile() {
	log.Printf("createMinimalFile")

	minimal, err := pdf.Create("h7-minimal.pdf")
	if err != nil {
		log.Fatalln(errgo.Details(err))
	}
	defer minimal.Close()

	minimal.Root = pdf.ObjectReference{ObjectNumber: 1}

	// catalog
	minimal.Add(pdf.IndirectObject{
		ObjectReference: pdf.ObjectReference{ObjectNumber: 1},
		Object: pdf.Dictionary{
			pdf.Name("Type"): pdf.Name("Catalog"),
			pdf.Name("Outlines"): pdf.ObjectReference{
				ObjectNumber: 2,
			},
			pdf.Name("Pages"): pdf.ObjectReference{
				ObjectNumber: 3,
			},
		},
	})

	// outlines
	minimal.Add(pdf.IndirectObject{
		ObjectReference: pdf.ObjectReference{ObjectNumber: 2},
		Object: pdf.Dictionary{
			pdf.Name("Type"):  pdf.Name("Outlines"),
			pdf.Name("Count"): pdf.Integer(0),
		},
	})

	// pages
	minimal.Add(pdf.IndirectObject{
		ObjectReference: pdf.ObjectReference{ObjectNumber: 3},
		Object: pdf.Dictionary{
			pdf.Name("Type"): pdf.Name("Pages"),
			pdf.Name("Kids"): pdf.Array{
				pdf.ObjectReference{
					ObjectNumber: 4,
				},
			},
			pdf.Name("Count"): pdf.Integer(1),
		},
	})

	// page
	minimal.Add(pdf.IndirectObject{
		ObjectReference: pdf.ObjectReference{ObjectNumber: 4},
		Object: pdf.Dictionary{
			pdf.Name("Type"): pdf.Name("Page"),
			pdf.Name("Parent"): pdf.ObjectReference{
				ObjectNumber: 3,
			},
			pdf.Name("MediaBox"): pdf.Array{
				pdf.Integer(0),
				pdf.Integer(0),
				pdf.Integer(612),
				pdf.Integer(792),
			},
			pdf.Name("Contents"): pdf.ObjectReference{
				ObjectNumber: 5,
			},
			pdf.Name("Resources"): pdf.Dictionary{
				pdf.Name("ProcSet"): pdf.ObjectReference{
					ObjectNumber: 6,
				},
			},
		},
	})

	// content stream
	minimal.Add(pdf.IndirectObject{
		ObjectReference: pdf.ObjectReference{ObjectNumber: 5},
		Object: pdf.Stream{
			Dictionary: pdf.Dictionary{
				pdf.Name("Length"): pdf.Integer(0),
			},
		},
	})

	// procset
	minimal.Add(pdf.IndirectObject{
		ObjectReference: pdf.ObjectReference{ObjectNumber: 6},
		Object: pdf.Array{
			pdf.Name("PDF"),
		},
	})

	minimal.Root = pdf.ObjectReference{ObjectNumber: 1}

	err = minimal.Save()
	if err != nil {
		log.Fatalln(errgo.Details(err))
	}
}