github.com/pdfcpu/pdfcpu@v0.11.1/pkg/api/image.go (about) 1 /* 2 Copyright 2021 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 "io" 21 "os" 22 "path/filepath" 23 "strconv" 24 "strings" 25 26 "github.com/pdfcpu/pdfcpu/pkg/pdfcpu" 27 "github.com/pdfcpu/pdfcpu/pkg/pdfcpu/model" 28 "github.com/pkg/errors" 29 ) 30 31 // Images returns all embedded images of rs. 32 func Images(rs io.ReadSeeker, selectedPages []string, conf *model.Configuration) ([]map[int]model.Image, error) { 33 if rs == nil { 34 return nil, errors.New("pdfcpu: ListImages: missing rs") 35 } 36 37 if conf == nil { 38 conf = model.NewDefaultConfiguration() 39 } 40 conf.Cmd = model.LISTIMAGES 41 42 ctx, err := ReadValidateAndOptimize(rs, conf) 43 if err != nil { 44 return nil, err 45 } 46 47 pages, err := PagesForPageSelection(ctx.PageCount, selectedPages, true, true) 48 if err != nil { 49 return nil, err 50 } 51 52 ii, _, err := pdfcpu.Images(ctx, pages) 53 54 return ii, err 55 } 56 57 // UpdateImages replaces the XObject identified by objNr or (pageNr and resourceId). 58 func UpdateImages(rs io.ReadSeeker, rd io.Reader, w io.Writer, objNr, pageNr int, id string, conf *model.Configuration) error { 59 60 if rs == nil { 61 return errors.New("pdfcpu: UpdateImages: missing rs") 62 } 63 64 if conf == nil { 65 conf = model.NewDefaultConfiguration() 66 } 67 conf.Cmd = model.UPDATEIMAGES 68 69 ctx, err := ReadValidateAndOptimize(rs, conf) 70 if err != nil { 71 return err 72 } 73 74 if objNr > 0 { 75 if err := pdfcpu.UpdateImagesByObjNr(ctx, rd, objNr); err != nil { 76 return err 77 } 78 79 return Write(ctx, w, conf) 80 } 81 82 if pageNr == 0 || id == "" { 83 return errors.New("pdfcpu: UpdateImages: missing pageNr or id ") 84 } 85 86 if err := pdfcpu.UpdateImagesByPageNrAndId(ctx, rd, pageNr, id); err != nil { 87 return err 88 } 89 90 return Write(ctx, w, conf) 91 } 92 93 func ensurePageNrAndId(pageNr *int, id *string, imageFile string) (err error) { 94 // If objNr and pageNr and id are not set, we assume an image filename produced by "pdfcpu image list" and parse this info. 95 // eg. mountain_1_Im0.png => pageNr:1, id:Im0 96 97 if *pageNr > 0 && *id != "" { 98 return nil 99 } 100 101 s := strings.TrimSuffix(imageFile, filepath.Ext(imageFile)) 102 103 ss := strings.Split(s, "_") 104 105 if len(ss) < 3 { 106 return errors.Errorf("pdfcpu: invalid image filename:%s - must conform to output filename of \"pdfcpu extract\"", imageFile) 107 } 108 109 *id = ss[len(ss)-1] 110 111 *pageNr, err = strconv.Atoi(ss[len(ss)-2]) 112 if err != nil { 113 return err 114 } 115 116 return nil 117 } 118 119 // UpdateImagesFile replaces the XObject identified by objNr or (pageNr and resourceId). 120 func UpdateImagesFile(inFile, imageFile, outFile string, objNr, pageNr int, id string, conf *model.Configuration) (err error) { 121 122 if objNr < 1 { 123 if err = ensurePageNrAndId(&pageNr, &id, imageFile); err != nil { 124 return err 125 } 126 } 127 128 var f0, f1, f2 *os.File 129 130 if f0, err = os.Open(inFile); err != nil { 131 return err 132 } 133 134 if f1, err = os.Open(imageFile); err != nil { 135 return err 136 } 137 138 tmpFile := inFile + ".tmp" 139 if outFile != "" && inFile != outFile { 140 tmpFile = outFile 141 logWritingTo(outFile) 142 } else { 143 logWritingTo(inFile) 144 } 145 if f2, err = os.Create(tmpFile); err != nil { 146 f1.Close() 147 return err 148 } 149 150 defer func() { 151 if err != nil { 152 f2.Close() 153 f1.Close() 154 f0.Close() 155 os.Remove(tmpFile) 156 return 157 } 158 if err = f2.Close(); err != nil { 159 return 160 } 161 if err = f1.Close(); err != nil { 162 return 163 } 164 if err = f0.Close(); err != nil { 165 return 166 } 167 if outFile == "" || inFile == outFile { 168 err = os.Rename(tmpFile, inFile) 169 } 170 }() 171 172 return UpdateImages(f0, f1, f2, objNr, pageNr, id, conf) 173 }