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  }