mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-10-29 14:53:44 +08:00
1 parent
f2dbf72885
commit
8de701dbd4
7 files changed
+162
-12
No files matched your search
@@ -0,0 +1,106 @@
|
||||
// Copyright 2025-2026 肖其顿 (XIAO QI DUN)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package ofdgo
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"image"
|
||||
|
||||
"github.com/xiaoqidun/pdfgo"
|
||||
)
|
||||
|
||||
// preserveImages 按实际绘制顺序恢复颜色及透明度精度,不依赖后端资源命名或对象编号
|
||||
// 入参: ctx 取消上下文, data 后端PDF数据
|
||||
// 返回: []byte 保留图像精度的PDF数据, error 资源或写入错误
|
||||
func (r *pdfRenderer) preserveImages(ctx context.Context, data []byte) ([]byte, error) {
|
||||
if !r.exactImages {
|
||||
return data, nil
|
||||
}
|
||||
reader, err := pdfgo.NewReader(bytes.NewReader(data), int64(len(data)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer reader.Close()
|
||||
images := make(map[pdfgo.Reference]image.Image)
|
||||
pages := 0
|
||||
err = reader.WalkPages(ctx, func(index int, page *pdfgo.Page) error {
|
||||
if index >= len(r.images) {
|
||||
return fmt.Errorf("unexpected PDF output page")
|
||||
}
|
||||
pages++
|
||||
value, err := reader.Resolve(page.Resources["XObject"])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resources, _ := value.(pdfgo.Dictionary)
|
||||
var content bytes.Buffer
|
||||
if _, err := page.WriteContent(ctx, &content); err != nil {
|
||||
return err
|
||||
}
|
||||
position := 0
|
||||
if err := pdfgo.WalkOperations(ctx, content.Bytes(), func(operation pdfgo.Operation) error {
|
||||
if operation.Operator != "Do" {
|
||||
return nil
|
||||
}
|
||||
if len(operation.Operands) != 1 || position >= len(r.images[index]) {
|
||||
return fmt.Errorf("unexpected PDF output image")
|
||||
}
|
||||
name, ok := operation.Operands[0].(pdfgo.Name)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid PDF output image name")
|
||||
}
|
||||
ref, ok := resources[name].(pdfgo.Reference)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid PDF output image reference")
|
||||
}
|
||||
original := r.images[index][position]
|
||||
position++
|
||||
if original == nil {
|
||||
return nil
|
||||
}
|
||||
image, err := reader.ReadImage(ref)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if image.Width != original.Bounds().Dx() || image.Height != original.Bounds().Dy() {
|
||||
return fmt.Errorf("PDF output image dimensions differ")
|
||||
}
|
||||
if previous := images[ref]; previous != nil && previous != original {
|
||||
return fmt.Errorf("PDF output image reference conflicts")
|
||||
}
|
||||
images[ref] = original
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if position != len(r.images[index]) {
|
||||
return fmt.Errorf("PDF output image missing")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if pages != len(r.images) {
|
||||
return nil, fmt.Errorf("PDF output page missing")
|
||||
}
|
||||
var result bytes.Buffer
|
||||
if _, err := reader.ReplaceImagesTo(ctx, &result, images); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.Bytes(), nil
|
||||
}
|
||||
Reference in new issue
Block a user