52 lines
1.4 KiB
Go
52 lines
1.4 KiB
Go
package rasterize
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
|
|
"github.com/pdfcpu/pdfcpu/pkg/api"
|
|
"github.com/pdfcpu/pdfcpu/pkg/pdfcpu/model"
|
|
)
|
|
|
|
// RotatePDFPages applies clockwise rotations (degrees, multiples of 90) to each page.
|
|
// pageRotations is 1-indexed slice aligned with input pages: pageRotations[0] = page 1.
|
|
func RotatePDFPages(in []byte, pageRotations []int) ([]byte, error) {
|
|
conf := model.NewDefaultConfiguration()
|
|
conf.ValidationMode = model.ValidationRelaxed
|
|
|
|
// pdfcpu's Rotate API takes a single rotation and a page selection. We group
|
|
// pages by rotation value to minimize passes.
|
|
groups := map[int][]int{}
|
|
for i, r := range pageRotations {
|
|
r = ((r % 360) + 360) % 360
|
|
if r == 0 {
|
|
continue
|
|
}
|
|
groups[r] = append(groups[r], i+1)
|
|
}
|
|
if len(groups) == 0 {
|
|
out := make([]byte, len(in))
|
|
copy(out, in)
|
|
return out, nil
|
|
}
|
|
|
|
current := bytes.NewReader(in)
|
|
var buf bytes.Buffer
|
|
for rot, pages := range groups {
|
|
buf.Reset()
|
|
selectedPages := make([]string, len(pages))
|
|
for i, p := range pages {
|
|
selectedPages[i] = fmt.Sprintf("%d", p)
|
|
}
|
|
if err := api.Rotate(current, &buf, rot, selectedPages, conf); err != nil {
|
|
return nil, fmt.Errorf("rotate %d°: %w", rot, err)
|
|
}
|
|
current = bytes.NewReader(append([]byte(nil), buf.Bytes()...))
|
|
}
|
|
out := make([]byte, current.Size())
|
|
if _, err := current.ReadAt(out, 0); err != nil {
|
|
return nil, err
|
|
}
|
|
return out, nil
|
|
}
|