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 }