github.com/pdfcpu/pdfcpu@v0.11.1/pkg/api/importImage.go (about) 1 /* 2 Copyright 2020 The pdfcpu 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 "bufio" 21 "io" 22 "os" 23 24 "github.com/pdfcpu/pdfcpu/pkg/log" 25 "github.com/pdfcpu/pdfcpu/pkg/pdfcpu" 26 "github.com/pdfcpu/pdfcpu/pkg/pdfcpu/model" 27 "github.com/pdfcpu/pdfcpu/pkg/pdfcpu/types" 28 ) 29 30 // Import parses an Import command string into an internal structure. 31 func Import(s string, u types.DisplayUnit) (*pdfcpu.Import, error) { 32 return pdfcpu.ParseImportDetails(s, u) 33 } 34 35 // ImportImages appends PDF pages containing images to rs and writes the result to w. 36 // If rs == nil a new PDF file will be written to w. 37 func ImportImages(rs io.ReadSeeker, w io.Writer, imgs []io.Reader, imp *pdfcpu.Import, conf *model.Configuration) error { 38 if conf == nil { 39 conf = model.NewDefaultConfiguration() 40 } 41 conf.Cmd = model.IMPORTIMAGES 42 43 if imp == nil { 44 imp = pdfcpu.DefaultImportConfig() 45 } 46 47 var ( 48 ctx *model.Context 49 err error 50 ) 51 52 if rs != nil { 53 ctx, err = ReadAndValidate(rs, conf) 54 } else { 55 ctx, err = pdfcpu.CreateContextWithXRefTable(conf, imp.PageDim) 56 } 57 if err != nil { 58 return err 59 } 60 61 pagesIndRef, err := ctx.Pages() 62 if err != nil { 63 return err 64 } 65 66 // Page tree root. 67 pagesDict, err := ctx.DereferenceDict(*pagesIndRef) 68 if err != nil { 69 return err 70 } 71 72 for _, r := range imgs { 73 74 indRefs, err := pdfcpu.NewPagesForImage(ctx.XRefTable, r, pagesIndRef, imp) 75 if err != nil { 76 return err 77 } 78 79 for _, indRef := range indRefs { 80 if err := ctx.SetValid(*indRef); err != nil { 81 return err 82 } 83 if err = model.AppendPageTree(indRef, 1, pagesDict); err != nil { 84 return err 85 } 86 ctx.PageCount++ 87 } 88 } 89 90 return Write(ctx, w, conf) 91 } 92 93 func fileExists(filename string) bool { 94 var ret bool 95 f, err := os.Open(filename) 96 if err == nil { 97 ret = true 98 } 99 defer f.Close() 100 return ret 101 102 } 103 104 func prepImgFiles(imgFiles []string, f1 *os.File) ([]io.ReadCloser, []io.Reader, error) { 105 rc := make([]io.ReadCloser, len(imgFiles)) 106 rr := make([]io.Reader, len(imgFiles)) 107 108 for i, fn := range imgFiles { 109 f, err := os.Open(fn) 110 if err != nil { 111 if f1 != nil { 112 f1.Close() 113 } 114 return nil, nil, err 115 } 116 rc[i] = f 117 rr[i] = bufio.NewReader(f) 118 } 119 120 return rc, rr, nil 121 } 122 123 func logImportImages(s, outFile string) { 124 if log.CLIEnabled() { 125 log.CLI.Printf("%s to %s...\n", s, outFile) 126 } 127 } 128 129 // ImportImagesFile appends PDF pages containing images to outFile which will be created if necessary. 130 func ImportImagesFile(imgFiles []string, outFile string, imp *pdfcpu.Import, conf *model.Configuration) (err error) { 131 var f1, f2 *os.File 132 133 rs := io.ReadSeeker(nil) 134 f1 = nil 135 tmpFile := outFile 136 if fileExists(outFile) { 137 if f1, err = os.Open(outFile); err != nil { 138 return err 139 } 140 rs = f1 141 tmpFile += ".tmp" 142 logImportImages("appending", outFile) 143 } else { 144 logImportImages("writing", outFile) 145 } 146 147 rc, rr, err := prepImgFiles(imgFiles, f1) 148 if err != nil { 149 return err 150 } 151 152 if f2, err = os.Create(tmpFile); err != nil { 153 if f1 != nil { 154 f1.Close() 155 } 156 return err 157 } 158 159 defer func() { 160 if err != nil { 161 f2.Close() 162 if f1 != nil { 163 f1.Close() 164 os.Remove(tmpFile) 165 } 166 for _, f := range rc { 167 f.Close() 168 } 169 return 170 } 171 if err = f2.Close(); err != nil { 172 return 173 } 174 if f1 != nil { 175 if err = f1.Close(); err != nil { 176 return 177 } 178 if err = os.Rename(tmpFile, outFile); err != nil { 179 return 180 } 181 } 182 for _, f := range rc { 183 if err := f.Close(); err != nil { 184 return 185 } 186 } 187 }() 188 189 return ImportImages(rs, f2, rr, imp, conf) 190 }