github.com/pdfcpu/pdfcpu@v0.11.1/pkg/api/stamp.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 "io" 21 "os" 22 23 "github.com/pdfcpu/pdfcpu/pkg/pdfcpu" 24 "github.com/pdfcpu/pdfcpu/pkg/pdfcpu/model" 25 "github.com/pdfcpu/pdfcpu/pkg/pdfcpu/types" 26 "github.com/pkg/errors" 27 ) 28 29 // WatermarkContext applies wm for selected pages to ctx. 30 func WatermarkContext(ctx *model.Context, selectedPages types.IntSet, wm *model.Watermark) error { 31 return pdfcpu.AddWatermarks(ctx, selectedPages, wm) 32 } 33 34 // AddWatermarksMap adds watermarks in m to corresponding pages in rs and writes the result to w. 35 func AddWatermarksMap(rs io.ReadSeeker, w io.Writer, m map[int]*model.Watermark, conf *model.Configuration) error { 36 if rs == nil { 37 return errors.New("pdfcpu: AddWatermarksMap: missing rs") 38 } 39 40 if conf == nil { 41 conf = model.NewDefaultConfiguration() 42 } 43 conf.Cmd = model.ADDWATERMARKS 44 45 if len(m) == 0 { 46 return errors.New("pdfcpu: missing watermarks") 47 } 48 49 ctx, err := ReadValidateAndOptimize(rs, conf) 50 if err != nil { 51 return err 52 } 53 54 if err = pdfcpu.AddWatermarksMap(ctx, m); err != nil { 55 return err 56 } 57 58 return Write(ctx, w, conf) 59 } 60 61 // AddWatermarksMapFile adds watermarks to corresponding pages in m of inFile and writes the result to outFile. 62 func AddWatermarksMapFile(inFile, outFile string, m map[int]*model.Watermark, conf *model.Configuration) (err error) { 63 var f1, f2 *os.File 64 65 if f1, err = os.Open(inFile); err != nil { 66 return err 67 } 68 69 tmpFile := inFile + ".tmp" 70 if outFile != "" && inFile != outFile { 71 tmpFile = outFile 72 logWritingTo(outFile) 73 } else { 74 logWritingTo(inFile) 75 } 76 if f2, err = os.Create(tmpFile); err != nil { 77 f1.Close() 78 return err 79 } 80 81 defer func() { 82 if err != nil { 83 f2.Close() 84 f1.Close() 85 os.Remove(tmpFile) 86 return 87 } 88 if err = f2.Close(); err != nil { 89 return 90 } 91 if err = f1.Close(); err != nil { 92 return 93 } 94 if outFile == "" || inFile == outFile { 95 err = os.Rename(tmpFile, inFile) 96 } 97 }() 98 99 return AddWatermarksMap(f1, f2, m, conf) 100 } 101 102 // AddWatermarksSliceMap adds watermarks in m to corresponding pages in rs and writes the result to w. 103 func AddWatermarksSliceMap(rs io.ReadSeeker, w io.Writer, m map[int][]*model.Watermark, conf *model.Configuration) error { 104 if rs == nil { 105 return errors.New("pdfcpu: AddWatermarksSliceMap: missing rs") 106 } 107 108 if conf == nil { 109 conf = model.NewDefaultConfiguration() 110 } 111 conf.Cmd = model.ADDWATERMARKS 112 113 if len(m) == 0 { 114 return errors.New("pdfcpu: missing watermarks") 115 } 116 117 ctx, err := ReadValidateAndOptimize(rs, conf) 118 if err != nil { 119 return err 120 } 121 122 if err = pdfcpu.AddWatermarksSliceMap(ctx, m); err != nil { 123 return err 124 } 125 126 return Write(ctx, w, conf) 127 } 128 129 // AddWatermarksSliceMapFile adds watermarks to corresponding pages in m of inFile and writes the result to outFile. 130 func AddWatermarksSliceMapFile(inFile, outFile string, m map[int][]*model.Watermark, conf *model.Configuration) (err error) { 131 var f1, f2 *os.File 132 133 if f1, err = os.Open(inFile); err != nil { 134 return err 135 } 136 137 tmpFile := inFile + ".tmp" 138 if outFile != "" && inFile != outFile { 139 tmpFile = outFile 140 logWritingTo(outFile) 141 } else { 142 logWritingTo(inFile) 143 } 144 if f2, err = os.Create(tmpFile); err != nil { 145 f1.Close() 146 return err 147 } 148 149 defer func() { 150 if err != nil { 151 f2.Close() 152 f1.Close() 153 os.Remove(tmpFile) 154 return 155 } 156 if err = f2.Close(); err != nil { 157 return 158 } 159 if err = f1.Close(); err != nil { 160 return 161 } 162 if outFile == "" || inFile == outFile { 163 err = os.Rename(tmpFile, inFile) 164 } 165 }() 166 167 return AddWatermarksSliceMap(f1, f2, m, conf) 168 } 169 170 // AddWatermarks adds watermarks to all pages selected in rs and writes the result to w. 171 func AddWatermarks(rs io.ReadSeeker, w io.Writer, selectedPages []string, wm *model.Watermark, conf *model.Configuration) error { 172 if rs == nil { 173 return errors.New("pdfcpu: AddWatermarks: missing rs") 174 } 175 176 if conf == nil { 177 conf = model.NewDefaultConfiguration() 178 } 179 conf.Cmd = model.ADDWATERMARKS 180 conf.OptimizeDuplicateContentStreams = false 181 182 if wm == nil { 183 return errors.New("pdfcpu: missing watermark configuration") 184 } 185 186 ctx, err := ReadValidateAndOptimize(rs, conf) 187 if err != nil { 188 return err 189 } 190 191 var pages types.IntSet 192 pages, err = PagesForPageSelection(ctx.PageCount, selectedPages, true, true) 193 if err != nil { 194 return err 195 } 196 197 if err = pdfcpu.AddWatermarks(ctx, pages, wm); err != nil { 198 return err 199 } 200 201 return Write(ctx, w, conf) 202 } 203 204 // AddWatermarksFile adds watermarks to all selected pages of inFile and writes the result to outFile. 205 func AddWatermarksFile(inFile, outFile string, selectedPages []string, wm *model.Watermark, conf *model.Configuration) (err error) { 206 var f1, f2 *os.File 207 208 if f1, err = os.Open(inFile); err != nil { 209 return err 210 } 211 212 tmpFile := inFile + ".tmp" 213 if outFile != "" && inFile != outFile { 214 tmpFile = outFile 215 logWritingTo(outFile) 216 } else { 217 logWritingTo(inFile) 218 } 219 if f2, err = os.Create(tmpFile); err != nil { 220 f1.Close() 221 return err 222 } 223 224 defer func() { 225 if err != nil { 226 f2.Close() 227 f1.Close() 228 os.Remove(tmpFile) 229 return 230 } 231 if err = f2.Close(); err != nil { 232 return 233 } 234 if err = f1.Close(); err != nil { 235 return 236 } 237 if outFile == "" || inFile == outFile { 238 err = os.Rename(tmpFile, inFile) 239 } 240 }() 241 242 return AddWatermarks(f1, f2, selectedPages, wm, conf) 243 } 244 245 // RemoveWatermarks removes watermarks from all pages selected in rs and writes the result to w. 246 func RemoveWatermarks(rs io.ReadSeeker, w io.Writer, selectedPages []string, conf *model.Configuration) error { 247 if rs == nil { 248 return errors.New("pdfcpu: RemoveWatermarks: missing rs") 249 } 250 251 if conf == nil { 252 conf = model.NewDefaultConfiguration() 253 } 254 conf.Cmd = model.REMOVEWATERMARKS 255 256 ctx, err := ReadValidateAndOptimize(rs, conf) 257 if err != nil { 258 return err 259 } 260 261 pages, err := PagesForPageSelection(ctx.PageCount, selectedPages, true, true) 262 if err != nil { 263 return err 264 } 265 266 if err = pdfcpu.RemoveWatermarks(ctx, pages); err != nil { 267 return err 268 } 269 270 return Write(ctx, w, conf) 271 } 272 273 // RemoveWatermarksFile removes watermarks from all selected pages of inFile and writes the result to outFile. 274 func RemoveWatermarksFile(inFile, outFile string, selectedPages []string, conf *model.Configuration) (err error) { 275 var f1, f2 *os.File 276 277 if f1, err = os.Open(inFile); err != nil { 278 return err 279 } 280 281 tmpFile := inFile + ".tmp" 282 if outFile != "" && inFile != outFile { 283 tmpFile = outFile 284 logWritingTo(outFile) 285 } else { 286 logWritingTo(inFile) 287 } 288 if f2, err = os.Create(tmpFile); err != nil { 289 f1.Close() 290 return err 291 } 292 293 defer func() { 294 if err != nil { 295 f2.Close() 296 f1.Close() 297 os.Remove(tmpFile) 298 return 299 } 300 if err = f2.Close(); err != nil { 301 return 302 } 303 if err = f1.Close(); err != nil { 304 return 305 } 306 if outFile == "" || inFile == outFile { 307 err = os.Rename(tmpFile, inFile) 308 } 309 }() 310 311 return RemoveWatermarks(f1, f2, selectedPages, conf) 312 } 313 314 // HasWatermarks checks rs for watermarks. 315 func HasWatermarks(rs io.ReadSeeker, conf *model.Configuration) (bool, error) { 316 if rs == nil { 317 return false, errors.New("pdfcpu: HasWatermarks: missing rs") 318 } 319 320 ctx, err := ReadContext(rs, conf) 321 if err != nil { 322 return false, err 323 } 324 325 if err := pdfcpu.DetectWatermarks(ctx); err != nil { 326 return false, err 327 } 328 329 return ctx.Watermarked, nil 330 } 331 332 // HasWatermarksFile checks inFile for watermarks. 333 func HasWatermarksFile(inFile string, conf *model.Configuration) (bool, error) { 334 if conf == nil { 335 conf = model.NewDefaultConfiguration() 336 } 337 338 f, err := os.Open(inFile) 339 if err != nil { 340 return false, err 341 } 342 343 defer f.Close() 344 345 return HasWatermarks(f, conf) 346 } 347 348 // TextWatermark returns a text watermark configuration. 349 func TextWatermark(text, desc string, onTop, update bool, u types.DisplayUnit) (*model.Watermark, error) { 350 wm, err := pdfcpu.ParseTextWatermarkDetails(text, desc, onTop, u) 351 if err != nil { 352 return nil, err 353 } 354 355 wm.Update = update 356 357 return wm, nil 358 } 359 360 // ImageWatermark returns an image watermark configuration. 361 func ImageWatermark(fileName, desc string, onTop, update bool, u types.DisplayUnit) (*model.Watermark, error) { 362 wm, err := pdfcpu.ParseImageWatermarkDetails(fileName, desc, onTop, u) 363 if err != nil { 364 return nil, err 365 } 366 367 wm.Update = update 368 369 return wm, nil 370 } 371 372 // ImageWatermarkForReader returns an image watermark configuration for r. 373 func ImageWatermarkForReader(r io.Reader, desc string, onTop, update bool, u types.DisplayUnit) (*model.Watermark, error) { 374 wm, err := pdfcpu.ParseImageWatermarkDetails("", desc, onTop, u) 375 if err != nil { 376 return nil, err 377 } 378 379 wm.Update = update 380 wm.Image = r 381 382 return wm, nil 383 } 384 385 // PDFWatermark returns a PDF watermark configuration. 386 func PDFWatermark(fileName, desc string, onTop, update bool, u types.DisplayUnit) (*model.Watermark, error) { 387 wm, err := pdfcpu.ParsePDFWatermarkDetails(fileName, desc, onTop, u) 388 if err != nil { 389 return nil, err 390 } 391 392 wm.Update = update 393 394 return wm, nil 395 } 396 397 // PDFWatermarkForReadSeeker returns a PDF watermark configuration. 398 // Apply watermark/stamp to destination file with pageNrSrc of rs for selected pages. 399 // If pageNr == 0 apply a multi watermark/stamp applying all src pages in ascending manner to destination pages. 400 func PDFWatermarkForReadSeeker(rs io.ReadSeeker, pageNrSrc int, desc string, onTop, update bool, u types.DisplayUnit) (*model.Watermark, error) { 401 wm, err := pdfcpu.ParsePDFWatermarkDetails("", desc, onTop, u) 402 if err != nil { 403 return nil, err 404 } 405 406 wm.Update = update 407 wm.PDF = rs 408 wm.PdfPageNrSrc = pageNrSrc 409 410 return wm, nil 411 } 412 413 // PDFMultiWatermarkForReadSeeker returns a PDF watermark configuration. 414 // Define a source PDF watermark/stamp sequence using rs from page startPageNrSrc thru the last page of rs. 415 // Apply this sequence to the destination PDF file starting at page startPageNrDest for selected pages. 416 func PDFMultiWatermarkForReadSeeker(rs io.ReadSeeker, startPageNrSrc, startPageNrDest int, desc string, onTop, update bool, u types.DisplayUnit) (*model.Watermark, error) { 417 wm, err := pdfcpu.ParsePDFWatermarkDetails("", desc, onTop, u) 418 if err != nil { 419 return nil, err 420 } 421 422 wm.Update = update 423 wm.PDF = rs 424 wm.PdfMultiStartPageNrSrc = startPageNrSrc 425 wm.PdfMultiStartPageNrDest = startPageNrDest 426 427 return wm, nil 428 } 429 430 // AddTextWatermarksFile adds text stamps/watermarks to all selected pages of inFile and writes the result to outFile. 431 func AddTextWatermarksFile(inFile, outFile string, selectedPages []string, onTop bool, text, desc string, conf *model.Configuration) error { 432 unit := types.POINTS 433 if conf != nil { 434 unit = conf.Unit 435 } 436 437 wm, err := TextWatermark(text, desc, onTop, false, unit) 438 if err != nil { 439 return err 440 } 441 442 return AddWatermarksFile(inFile, outFile, selectedPages, wm, conf) 443 } 444 445 // AddImageWatermarksFile adds image stamps/watermarks to all selected pages of inFile and writes the result to outFile. 446 func AddImageWatermarksFile(inFile, outFile string, selectedPages []string, onTop bool, fileName, desc string, conf *model.Configuration) error { 447 unit := types.POINTS 448 if conf != nil { 449 unit = conf.Unit 450 } 451 452 wm, err := ImageWatermark(fileName, desc, onTop, false, unit) 453 if err != nil { 454 return err 455 } 456 457 return AddWatermarksFile(inFile, outFile, selectedPages, wm, conf) 458 } 459 460 // AddImageWatermarksForReaderFile adds image stamps/watermarks to all selected pages of inFile for r and writes the result to outFile. 461 func AddImageWatermarksForReaderFile(inFile, outFile string, selectedPages []string, onTop bool, r io.Reader, desc string, conf *model.Configuration) error { 462 unit := types.POINTS 463 if conf != nil { 464 unit = conf.Unit 465 } 466 467 wm, err := ImageWatermarkForReader(r, desc, onTop, false, unit) 468 if err != nil { 469 return err 470 } 471 472 return AddWatermarksFile(inFile, outFile, selectedPages, wm, conf) 473 } 474 475 // AddPDFWatermarksFile adds PDF stamps/watermarks to inFile and writes the result to outFile. 476 func AddPDFWatermarksFile(inFile, outFile string, selectedPages []string, onTop bool, fileName, desc string, conf *model.Configuration) error { 477 unit := types.POINTS 478 if conf != nil { 479 unit = conf.Unit 480 } 481 482 wm, err := PDFWatermark(fileName, desc, onTop, false, unit) 483 if err != nil { 484 return err 485 } 486 487 return AddWatermarksFile(inFile, outFile, selectedPages, wm, conf) 488 } 489 490 // UpdateTextWatermarksFile adds text stamps/watermarks to all selected pages of inFile and writes the result to outFile. 491 func UpdateTextWatermarksFile(inFile, outFile string, selectedPages []string, onTop bool, text, desc string, conf *model.Configuration) error { 492 unit := types.POINTS 493 if conf != nil { 494 unit = conf.Unit 495 } 496 497 wm, err := TextWatermark(text, desc, onTop, true, unit) 498 if err != nil { 499 return err 500 } 501 502 return AddWatermarksFile(inFile, outFile, selectedPages, wm, conf) 503 } 504 505 // UpdateImageWatermarksFile adds image stamps/watermarks to all selected pages of inFile and writes the result to outFile. 506 func UpdateImageWatermarksFile(inFile, outFile string, selectedPages []string, onTop bool, fileName, desc string, conf *model.Configuration) error { 507 unit := types.POINTS 508 if conf != nil { 509 unit = conf.Unit 510 } 511 wm, err := ImageWatermark(fileName, desc, onTop, true, unit) 512 if err != nil { 513 return err 514 } 515 return AddWatermarksFile(inFile, outFile, selectedPages, wm, conf) 516 } 517 518 // UpdatePDFWatermarksFile adds PDF stamps/watermarks to all selected pages of inFile and writes the result to outFile. 519 func UpdatePDFWatermarksFile(inFile, outFile string, selectedPages []string, onTop bool, fileName, desc string, conf *model.Configuration) error { 520 unit := types.POINTS 521 if conf != nil { 522 unit = conf.Unit 523 } 524 525 wm, err := PDFWatermark(fileName, desc, onTop, true, unit) 526 if err != nil { 527 return err 528 } 529 530 return AddWatermarksFile(inFile, outFile, selectedPages, wm, conf) 531 }