mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-10-29 16:59:27 +08:00
This commit is contained in:
1 parent
bcb9f98f8b
commit
3959664448
52 files changed
+1864
-407
No files matched your search
@@ -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)}
|
||||
}
|
||||
Reference in new issue
Block a user