github.com/pdfcpu/pdfcpu@v0.11.1/pkg/api/nup.go (about) 1 /* 2 Copyright 2020 The model Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package api 18 19 import ( 20 "io" 21 "os" 22 23 "github.com/pdfcpu/pdfcpu/pkg/log" 24 "github.com/pdfcpu/pdfcpu/pkg/pdfcpu" 25 "github.com/pdfcpu/pdfcpu/pkg/pdfcpu/model" 26 "github.com/pdfcpu/pdfcpu/pkg/pdfcpu/types" 27 ) 28 29 // PDFNUpConfig returns an NUp configuration for Nup-ing PDF files. 30 func PDFNUpConfig(val int, desc string, conf *model.Configuration) (*model.NUp, error) { 31 return pdfcpu.PDFNUpConfig(val, desc, conf) 32 } 33 34 // ImageNUpConfig returns an NUp configuration for Nup-ing image files. 35 func ImageNUpConfig(val int, desc string, conf *model.Configuration) (*model.NUp, error) { 36 return pdfcpu.ImageNUpConfig(val, desc, conf) 37 } 38 39 // PDFGridConfig returns a grid configuration for Grid-ing PDF files. 40 func PDFGridConfig(rows, cols int, desc string, conf *model.Configuration) (*model.NUp, error) { 41 return pdfcpu.PDFGridConfig(rows, cols, desc, conf) 42 } 43 44 // ImageGridConfig returns a grid configuration for Grid-ing image files. 45 func ImageGridConfig(rows, cols int, desc string, conf *model.Configuration) (*model.NUp, error) { 46 return pdfcpu.ImageGridConfig(rows, cols, desc, conf) 47 } 48 49 // PDFBookletConfig returns an NUp configuration for Booklet-ing PDF files. 50 func PDFBookletConfig(val int, desc string, conf *model.Configuration) (*model.NUp, error) { 51 return pdfcpu.PDFBookletConfig(val, desc, conf) 52 } 53 54 // ImageBookletConfig returns an NUp configuration for Booklet-ing image files. 55 func ImageBookletConfig(val int, desc string, conf *model.Configuration) (*model.NUp, error) { 56 return pdfcpu.ImageBookletConfig(val, desc, conf) 57 } 58 59 // NUpFromImage creates a single page n-up PDF for one image 60 // or a sequence of n-up pages for more than one image. 61 func NUpFromImage(conf *model.Configuration, imageFileNames []string, nup *model.NUp) (*model.Context, error) { 62 if nup.PageDim == nil { 63 // Set default paper size. 64 nup.PageDim = types.PaperSize[nup.PageSize] 65 } 66 67 ctx, err := pdfcpu.CreateContextWithXRefTable(conf, nup.PageDim) 68 if err != nil { 69 return nil, err 70 } 71 72 pagesIndRef, err := ctx.Pages() 73 if err != nil { 74 return nil, err 75 } 76 77 // This is the page tree root. 78 pagesDict, err := ctx.DereferenceDict(*pagesIndRef) 79 if err != nil { 80 return nil, err 81 } 82 83 if len(imageFileNames) == 1 { 84 err = pdfcpu.NUpFromOneImage(ctx, imageFileNames[0], nup, pagesDict, pagesIndRef) 85 } else { 86 err = pdfcpu.NUpFromMultipleImages(ctx, imageFileNames, nup, pagesDict, pagesIndRef) 87 } 88 89 return ctx, err 90 } 91 92 // NUp rearranges PDF pages or images into page grids and writes the result to w. 93 // Either rs or imgFiles will be used. 94 func NUp(rs io.ReadSeeker, w io.Writer, imgFiles, selectedPages []string, nup *model.NUp, conf *model.Configuration) error { 95 if conf == nil { 96 conf = model.NewDefaultConfiguration() 97 } 98 conf.Cmd = model.NUP 99 100 if log.InfoEnabled() { 101 log.Info.Printf("%s", nup) 102 } 103 104 var ( 105 ctx *model.Context 106 err error 107 ) 108 109 if nup.ImgInputFile { 110 111 if ctx, err = NUpFromImage(conf, imgFiles, nup); err != nil { 112 return err 113 } 114 115 } else { 116 117 if ctx, err = ReadAndValidate(rs, conf); err != nil { 118 return err 119 } 120 121 pages, err := PagesForPageSelection(ctx.PageCount, selectedPages, true, true) 122 if err != nil { 123 return err 124 } 125 126 // New pages get added to ctx while old pages get deleted. 127 // This way we avoid migrating objects between contexts. 128 if err = pdfcpu.NUpFromPDF(ctx, pages, nup); err != nil { 129 return err 130 } 131 132 } 133 134 return Write(ctx, w, conf) 135 } 136 137 // NUpFile rearranges PDF pages or images into page grids and writes the result to outFile. 138 func NUpFile(inFiles []string, outFile string, selectedPages []string, nup *model.NUp, conf *model.Configuration) (err error) { 139 var f1, f2 *os.File 140 141 if !nup.ImgInputFile { 142 // Nup from a PDF page. 143 if f1, err = os.Open(inFiles[0]); err != nil { 144 return err 145 } 146 } 147 148 if f2, err = os.Create(outFile); err != nil { 149 if f1 != nil { 150 f1.Close() 151 } 152 return err 153 } 154 logWritingTo(outFile) 155 156 defer func() { 157 if err != nil { 158 f2.Close() 159 if f1 != nil { 160 f1.Close() 161 } 162 os.Remove(outFile) 163 return 164 } 165 if err = f2.Close(); err != nil { 166 return 167 } 168 if f1 != nil { 169 err = f1.Close() 170 } 171 }() 172 173 return NUp(f1, f2, inFiles, selectedPages, nup, conf) 174 }