From 245fffed846d61437b3b190e7261001706d5ba9c Mon Sep 17 00:00:00 2001 From: xiaoqidun Date: Thu, 8 Oct 2026 12:59:00 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E8=BD=AC=E6=8D=A2=E8=83=BD=E5=8A=9B):=20?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=89=B2=E6=96=99=E8=BD=AC=E6=8D=A2=E9=87=87?= =?UTF-8?q?=E6=A0=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 2 +- go.sum | 4 ++-- ofdgo_pdf_composite_draw.go | 27 ++++++++++--------------- ofdgo_pdf_composite_pattern.go | 25 ++++++++++++++--------- ofdgo_pdf_image_native.go | 37 +++++++++++++++++++++++++--------- 5 files changed, 56 insertions(+), 39 deletions(-) diff --git a/go.mod b/go.mod index 9e58dfc..d13f29b 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/tdewolff/canvas v0.0.0-20260923214215-09804640d00c github.com/tdewolff/font v0.0.0-20260913163313-54f98bb59ee6 github.com/xiaoqidun/jbig2 v1.1.1 - github.com/xiaoqidun/pdfgo v0.0.0-20261008021024-e8f1cc0a7ad9 + github.com/xiaoqidun/pdfgo v0.0.0-20261008045044-ada80114c916 golang.org/x/crypto v0.57.0 golang.org/x/image v0.46.0 golang.org/x/text v0.42.0 diff --git a/go.sum b/go.sum index ec838f9..23a4e71 100644 --- a/go.sum +++ b/go.sum @@ -62,8 +62,8 @@ github.com/tdewolff/test v1.0.12 h1:7F21DqIajswxuche0geHdrUZRCWE4oko4b7bcmkkrxk= github.com/tdewolff/test v1.0.12/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= github.com/xiaoqidun/jbig2 v1.1.1 h1:SjliS9ZO0e9HX5oYUfBuXrfFsXhWricrSz+XY4zORDI= github.com/xiaoqidun/jbig2 v1.1.1/go.mod h1:8QonVWtENmh2kc6l+leqeGl7psb79DWlHDkCpdChjfQ= -github.com/xiaoqidun/pdfgo v0.0.0-20261008021024-e8f1cc0a7ad9 h1:aHEEZYzIL7cCLW9IXMlBC+LyCxkYrge3Zw/GfioDT2I= -github.com/xiaoqidun/pdfgo v0.0.0-20261008021024-e8f1cc0a7ad9/go.mod h1:4Pf0JO0BEf1uzRY+uZjlMjN/OPn3PYa0YMi6cqPPTLQ= +github.com/xiaoqidun/pdfgo v0.0.0-20261008045044-ada80114c916 h1:SwXbZ6zLtTCxMeV7A5GBSxgNhyVfdzWLhPh38IdkVTc= +github.com/xiaoqidun/pdfgo v0.0.0-20261008045044-ada80114c916/go.mod h1:4Pf0JO0BEf1uzRY+uZjlMjN/OPn3PYa0YMi6cqPPTLQ= github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= github.com/yuin/goldmark v1.8.5 h1:r6N5afV5qj/5S4UTch8agZHJ8UxNCMwX7WjkkJam2NA= diff --git a/ofdgo_pdf_composite_draw.go b/ofdgo_pdf_composite_draw.go index cb817cf..99d5cc0 100644 --- a/ofdgo_pdf_composite_draw.go +++ b/ofdgo_pdf_composite_draw.go @@ -789,8 +789,12 @@ func (c *pdfCompositor) imageColor(mark *pdfgo.ImageMark, point pdfgo.Point, spa if point.X < 0 || point.X > 1 || point.Y < 0 || point.Y > 1 { return [4]float64{}, 0, nil } + process, err := c.cache.imageProcess(c.importer, mark.Image, space, c.softMask) + if err != nil { + return [4]float64{}, 0, err + } source := c.cache.images[mark.Image] - if source == nil { + if process == nil && source == nil { var err error source, err = mark.Image.DecodeComponentsViewContext(c.importer.ctx) if err != nil { @@ -798,22 +802,13 @@ func (c *pdfCompositor) imageColor(mark *pdfgo.ImageMark, point pdfgo.Point, spa } c.cache.images[mark.Image] = source } - x, y := point.X*float64(source.Rect.Dx())-.5, (1-point.Y)*float64(source.Rect.Dy())-.5 - key := pdfImageProcessKey{image: mark.Image, space: space, softMask: c.softMask} - process, prepared := c.cache.imageProcesses[key] - if !prepared { - var err error - process, err = source.PrepareProcess(&pdfgo.ColorantDevice{Space: space}, space, c.softMask) - if err != nil { - return [4]float64{}, 0, err - } - if c.cache.imageProcesses == nil { - c.cache.imageProcesses = make(map[pdfImageProcessKey]*pdfgo.ImageProcess) - } - c.cache.imageProcesses[key] = process + bounds := process.Bounds() + if process == nil { + bounds = source.Rect } + x, y := point.X*float64(bounds.Dx())-.5, (1-point.Y)*float64(bounds.Dy())-.5 sample := func(x, y int) ([4]float64, float64) { - x, y = source.Rect.Min.X+max(0, min(source.Rect.Dx()-1, x)), source.Rect.Min.Y+max(0, min(source.Rect.Dy()-1, y)) + x, y = bounds.Min.X+max(0, min(bounds.Dx()-1, x)), bounds.Min.Y+max(0, min(bounds.Dy()-1, y)) if process != nil { return process.ValuesAt(x, y) } @@ -862,7 +857,7 @@ func (c *pdfCompositor) imageColor(mark *pdfgo.ImageMark, point pdfgo.Point, spa if process != nil || space.Equal(source.Space) { return values, alpha, nil } - values, err := space.ConvertWith(values[:source.Space.Components()], source.Space, mark.Style.RenderingIntent, mark.Style.ColorConversion) + values, err = space.ConvertWith(values[:source.Space.Components()], source.Space, mark.Style.RenderingIntent, mark.Style.ColorConversion) return values, alpha, err } diff --git a/ofdgo_pdf_composite_pattern.go b/ofdgo_pdf_composite_pattern.go index 231dc29..63f8e8a 100644 --- a/ofdgo_pdf_composite_pattern.go +++ b/ofdgo_pdf_composite_pattern.go @@ -246,17 +246,22 @@ func (p *pdfImporter) directCompositeNode(node pdfCompositeNode, space *pdfgo.Co } if space.Model == "DeviceCMYK" && style.ColorConversion != (pdfgo.ColorConversion{}) { if node.image != nil && !node.image.Image.ImageMask { - source := p.compositingCache().images[node.image.Image] - if source == nil { - var err error - source, err = node.image.Image.DecodeComponentsViewContext(p.ctx) - if err != nil { - return false, err - } - p.compositingCache().images[node.image.Image] = source + _, native, err := pdfImageProcessColorants(node.image.Image) + if err != nil { + return false, err } - if source.Space.Model == "DeviceRGB" && source.Space.Device() { - return false, nil + if !native { + source := p.compositingCache().images[node.image.Image] + if source == nil { + source, err = node.image.Image.DecodeComponentsViewContext(p.ctx) + if err != nil { + return false, err + } + p.compositingCache().images[node.image.Image] = source + } + if source.Space.Model == "DeviceRGB" && source.Space.Device() { + return false, nil + } } } else { for i, paint := range [2]pdfgo.Paint{style.Fill, style.Stroke} { diff --git a/ofdgo_pdf_image_native.go b/ofdgo_pdf_image_native.go index 2cc73f3..12abd95 100644 --- a/ofdgo_pdf_image_native.go +++ b/ofdgo_pdf_image_native.go @@ -53,17 +53,8 @@ func (p *pdfImporter) imageProcessModel(source *pdfgo.Image) (pdfgo.Name, error) // 返回: image.Image 只读图像, error 解码或分量映射错误 func (p *pdfImporter) imageProcess(source *pdfgo.Image, model pdfgo.Name) (image.Image, error) { cache := p.compositingCache() - components := cache.images[source] - if components == nil { - var err error - components, err = source.DecodeComponentsViewContext(p.ctx) - if err != nil { - return nil, err - } - cache.images[source] = components - } space := &pdfgo.ColorSpace{Model: model} - process, err := components.PrepareProcess(&pdfgo.ColorantDevice{Space: space}, space, false) + process, err := cache.imageProcess(p, source, space, false) if err != nil { return nil, err } @@ -73,6 +64,32 @@ func (p *pdfImporter) imageProcess(source *pdfgo.Image, model pdfgo.Name) (image return &pdfNativeImage{source: process, space: space}, nil } +// imageProcess 复用同组原生采样,仅在需要备用颜色时保留完整分量 +// 入参: importer 导入器, source 源图像, space 组混合空间, softMask 是否用于软蒙版 +// 返回: *pdfgo.ImageProcess 原生采样,需要备用色时为nil, error 解码或布局错误 +func (c *pdfCompositeCache) imageProcess(importer *pdfImporter, source *pdfgo.Image, space *pdfgo.ColorSpace, softMask bool) (*pdfgo.ImageProcess, error) { + key := pdfImageProcessKey{image: source, space: space, softMask: softMask} + if process, found := c.imageProcesses[key]; found { + return process, nil + } + device := &pdfgo.ColorantDevice{Space: space} + var process *pdfgo.ImageProcess + var err error + if components := c.images[source]; components != nil { + process, err = components.PrepareProcess(device, space, softMask) + } else { + process, err = source.DecodeProcessContext(importer.ctx, device, space, softMask) + } + if err != nil { + return nil, err + } + if c.imageProcesses == nil { + c.imageProcesses = make(map[pdfImageProcessKey]*pdfgo.ImageProcess) + } + c.imageProcesses[key] = process + return process, nil +} + // ColorModel 保留16位原生分量与源透明度 // 返回: color.Model 非预乘颜色模型 func (s *pdfNativeImage) ColorModel() color.Model { return color.NRGBA64Model }