refactor(重构提升): 优化转换渲染与资源压缩
build.yaml / build (push) Successful in 2m49s

This commit is contained in:
xiaoqidun committed 2026-10-06 17:53:24 +08:00
1 parent bcb9f98f8b
commit 3959664448
52 files changed
+1864 -407

No files matched your search

+113
View File
@@ -0,0 +1,113 @@
// 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 (
"fmt"
"image/color"
"math"
"slices"
"strconv"
"strings"
"github.com/xiaoqidun/pdfgo"
)
// colorProfile 保存包内配置的不可变解析结果,不跨阅读器或文档共享
type colorProfile struct {
space *pdfgo.ColorSpace
err error
}
// colorProfileUsed 判断新增ICC文件是否被颜色空间引用,不作为资源XML登记
// 入参: spaces 当前使用的新增颜色空间
// 返回: bool 是否保留文件
func (r editorResource) colorProfileUsed(spaces []ColorSpace) bool {
return r.space != nil && r.name != "" && r.space.Profile != "" && slices.ContainsFunc(spaces, func(space ColorSpace) bool { return space.Profile == r.space.Profile })
}
// parseColorProfile 验证OFD模型与ICC源模型一致,不以设备色替代声明的配置
// 入参: kind OFD颜色模型, data ICC文件
// 返回: *colorProfile 解析结果, error 模型或配置错误
func parseColorProfile(kind string, data []byte) (*colorProfile, error) {
model := map[string]string{"GRAY": "GRAY", "RGB": "RGB ", "CMYK": "CMYK"}[strings.ToUpper(kind)]
if len(data) < 132 || model == "" || string(data[16:20]) != model {
return nil, fmt.Errorf("ICC source model does not match OFD color space %q", kind)
}
space, err := pdfgo.NewICCColorSpace(data)
if err != nil {
return nil, err
}
return &colorProfile{space: space}, nil
}
// colorProfile 按文件及模型复用只读配置,读取失败也保留结果以免重复读取
// 入参: space 颜色空间
// 返回: *colorProfile 配置,未声明时为nil, error 读取或配置错误
func (r *Reader) colorProfile(space *ColorSpace) (*colorProfile, error) {
if space == nil || space.Profile == "" {
return nil, nil
}
if space.profile != nil {
return space.profile, space.profile.err
}
if r == nil {
return nil, fmt.Errorf("color profile %q is unavailable", space.Profile)
}
name := r.ResPath(space.Profile)
for _, other := range r.colorSpaceCache {
if other != nil && other.profile != nil && strings.EqualFold(other.Type, space.Type) && strings.EqualFold(r.ResPath(other.Profile), name) {
space.profile = other.profile
return space.profile, space.profile.err
}
}
data, err := r.readFile(name)
if err == nil {
space.profile, err = parseColorProfile(space.Type, data)
}
if err != nil {
space.profile = &colorProfile{err: fmt.Errorf("color profile %q: %w", space.Profile, err)}
}
return space.profile, space.profile.err
}
// colorDefinition 获取显式或文档默认颜色空间,统一资源标识别名
// 入参: id 颜色空间标识
// 返回: *ColorSpace 已加载定义,未声明时为nil
func (r *Renderer) colorDefinition(id string) *ColorSpace {
if r.Reader == nil {
return nil
}
if id == "" && r.Reader.doc != nil {
id = strconv.Itoa(r.Reader.doc.CommonData.DefaultCS)
}
space, _ := resourceValue(r.Reader.colorSpaceCache, id)
return space
}
// rgb 转换归一化源分量,不在ICC变换前量化为8位
// 入参: values 源分量
// 返回: [3]float64 sRGB分量, error 变换错误
func (p *colorProfile) rgb(values [4]float64) ([3]float64, error) {
return p.space.RGB(values[:p.space.Components()], p.space.DefaultIntent())
}
// profileColor 将显示分量一次量化并按透明度预乘
// 入参: rgb sRGB分量, alpha 非预乘透明度
// 返回: color.RGBA 预乘颜色
func profileColor(rgb [3]float64, alpha float64) color.RGBA {
alpha = math.Max(0, math.Min(1, alpha))
return color.RGBA{meshByte(rgb[0] * alpha), meshByte(rgb[1] * alpha), meshByte(rgb[2] * alpha), meshByte(alpha)}
}