feat(图像签章): 完善图像取消与签章缓存
build.yaml / build (push) Successful in 48s

This commit is contained in:
xiaoqidun committed 2026-10-12 19:18:25 +08:00
1 parent 3d37b0d510
commit 5d1fd593cd
4 files changed
+91 -18

No files matched your search

+15 -5
View File
@@ -19,6 +19,7 @@ import (
"context" "context"
"fmt" "fmt"
"image" "image"
"io"
"math" "math"
) )
@@ -90,7 +91,7 @@ func (e *Editor) ImportImages(ctx context.Context, sources []ImagePageSource, at
if err := ctx.Err(); err != nil { if err := ctx.Err(); err != nil {
return err return err
} }
page, err := e.addImagePage(data, options) page, err := e.addImagePage(ctx, data, options)
if err != nil { if err != nil {
return fmt.Errorf("image %q: %w", source.Name, err) return fmt.Errorf("image %q: %w", source.Name, err)
} }
@@ -107,9 +108,12 @@ func (e *Editor) ImportImages(ctx context.Context, sources []ImagePageSource, at
} }
// addImagePage 保留原图并按方向、物理尺寸与纸张选项建页 // addImagePage 保留原图并按方向、物理尺寸与纸张选项建页
// 入参: data 图片数据, options 建页选项 // 入参: ctx 取消上下文, data 图片数据, options 建页选项
// 返回: int 从0开始的页面索引, error 错误信息 // 返回: int 从0开始的页面索引, error 错误信息
func (e *Editor) addImagePage(data []byte, options ImagePageOptions) (int, error) { func (e *Editor) addImagePage(ctx context.Context, data []byte, options ImagePageOptions) (int, error) {
if err := ctx.Err(); err != nil {
return 0, err
}
config, format, err := decodeImageConfigData(data) config, format, err := decodeImageConfigData(data)
if err != nil { if err != nil {
return 0, err return 0, err
@@ -119,9 +123,12 @@ func (e *Editor) addImagePage(data []byte, options ImagePageOptions) (int, error
} }
var decoded image.Image var decoded image.Image
if format == "bmp" || format == "tiff" { if format == "bmp" || format == "tiff" {
decoded, _, err = decodeImageData(data) decoded, _, err = decodeImageDataContext(ctx, data)
} else { } else {
decoded, _, err = image.Decode(bytes.NewReader(data)) decoded, _, err = image.Decode(imageInput{ReadCloser: io.NopCloser(bytes.NewReader(data)), context: ctx})
}
if cancelErr := ctx.Err(); cancelErr != nil {
return 0, cancelErr
} }
if err != nil { if err != nil {
return 0, err return 0, err
@@ -144,6 +151,9 @@ func (e *Editor) addImagePage(data []byte, options ImagePageOptions) (int, error
if !finite(w) || !finite(h) || w <= 0 || h <= 0 { if !finite(w) || !finite(h) || w <= 0 || h <= 0 {
return 0, fmt.Errorf("invalid image page dimensions") return 0, fmt.Errorf("invalid image page dimensions")
} }
if err := ctx.Err(); err != nil {
return 0, err
}
resource, err := e.addImage(data, config, format, decoded) resource, err := e.addImage(data, config, format, decoded)
if err != nil { if err != nil {
return 0, err return 0, err
+11 -3
View File
@@ -16,6 +16,7 @@ package ofdgo
import ( import (
"bytes" "bytes"
"context"
"fmt" "fmt"
"image" "image"
"math" "math"
@@ -158,20 +159,27 @@ func (c *semanticCompiler) drawStampContent(stamp Stamp) error {
if c.textOnly || c.measure || len(stamp.Data) == 0 { if c.textOnly || c.measure || len(stamp.Data) == 0 {
return nil return nil
} }
ctx := c.renderer.pageContext
if ctx == nil {
ctx = context.Background()
}
if err := ctx.Err(); err != nil {
return err
}
if stamp.Type == "ofd" { if stamp.Type == "ofd" {
reader, err := NewReader(bytes.NewReader(stamp.Data), int64(len(stamp.Data))) reader, err := NewReader(bytes.NewReader(stamp.Data), int64(len(stamp.Data)))
if err != nil { if err != nil {
return err return err
} }
defer reader.Close() defer reader.Close()
document, err := reader.Doc() document, err := reader.DocContext(ctx)
if err != nil { if err != nil {
return err return err
} }
renderer := c.renderer.childRenderer(reader) renderer := c.renderer.childRenderer(reader)
renderer.TransparentBackground = true renderer.TransparentBackground = true
for _, reference := range document.Pages.Page { for _, reference := range document.Pages.Page {
content, err := reader.PageContent(reference) content, err := reader.PageContentContext(ctx, reference)
if err != nil { if err != nil {
return err return err
} }
@@ -218,7 +226,7 @@ func (c *semanticCompiler) drawStampContent(stamp Stamp) error {
} }
return nil return nil
} }
img, _, err := decodeImageData(stamp.Data) img, _, err := decodeImageDataContext(ctx, stamp.Data)
if err != nil { if err != nil {
return err return err
} }
+27 -5
View File
@@ -15,6 +15,7 @@
package ofdgo package ofdgo
import ( import (
"context"
"crypto/sha256" "crypto/sha256"
"fmt" "fmt"
"slices" "slices"
@@ -62,6 +63,13 @@ func (c *semanticCompiler) sharedStamp(stamp Stamp, compile func(*semanticCompil
return nil return nil
} }
r := c.renderer r := c.renderer
ctx := r.pageContext
if ctx == nil {
ctx = context.Background()
}
if err := ctx.Err(); err != nil {
return err
}
state, _ := r.backendStates[stampContentStateKey{}].(*stampContentState) state, _ := r.backendStates[stampContentStateKey{}].(*stampContentState)
config := r.backends config := r.backends
if state == nil || !sameBackend(state.config.Fonts, config.Fonts) || !sameBackend(state.config.Geometry, config.Geometry) || if state == nil || !sameBackend(state.config.Fonts, config.Fonts) || !sameBackend(state.config.Geometry, config.Geometry) ||
@@ -80,17 +88,31 @@ func (c *semanticCompiler) sharedStamp(stamp Stamp, compile func(*semanticCompil
local.Box.X, local.Box.Y = 0, 0 local.Box.X, local.Box.Y = 0, 0
page := &RasterPage{Width: c.page.Width, Height: c.page.Height, DPI: c.page.DPI} page := &RasterPage{Width: c.page.Width, Height: c.page.Height, DPI: c.page.DPI}
child := &semanticCompiler{renderer: r, geometry: c.geometry, page: page, patterns: c.patterns} child := &semanticCompiler{renderer: r, geometry: c.geometry, page: page, patterns: c.patterns}
if err := compile(child, local); err != nil { err := compile(child, local)
if cancelErr := ctx.Err(); cancelErr != nil {
return cancelErr
}
if err != nil {
return err return err
} }
commands = page.Commands commands = page.Commands
cost := 0 cost := 0
for _, command := range commands { for _, command := range commands {
cost += rasterCommandCost(command) part := rasterCommandCost(command)
if command.Image != nil { if part < 0 || part > state.cache.limit-cost {
bounds := command.Image.Bounds() cost = state.cache.limit + 1
cost += bounds.Dx() * bounds.Dy() * 4 break
} }
cost += part
if command.Image != nil {
cost += imageResourceCost(command.Image, state.cache.limit-cost)
}
if cost > state.cache.limit {
break
}
}
if err := ctx.Err(); err != nil {
return err
} }
state.cache.put(key, commands, cost) state.cache.put(key, commands, cost)
} }
+38 -5
View File
@@ -16,6 +16,7 @@ package ofdgo
import ( import (
"bytes" "bytes"
"context"
"image" "image"
"github.com/tdewolff/canvas" "github.com/tdewolff/canvas"
@@ -27,6 +28,19 @@ func (r *Renderer) renderStamp(ctx *canvas.Context, s Stamp, pageH float64) {
if r.textOnly { if r.textOnly {
return return
} }
pageContext := r.pageContext
if pageContext == nil {
pageContext = context.Background()
}
defer func() {
if err := pageContext.Err(); err != nil {
r.renderError = err
}
}()
if err := pageContext.Err(); err != nil {
r.renderError = err
return
}
if s.Type == "ofd" && len(s.Data) > 0 { if s.Type == "ofd" && len(s.Data) > 0 {
if s.Clip != nil { if s.Clip != nil {
if img := r.renderOFDStampImage(s.Data); img != nil { if img := r.renderOFDStampImage(s.Data); img != nil {
@@ -37,12 +51,15 @@ func (r *Renderer) renderStamp(ctx *canvas.Context, s Stamp, pageH float64) {
reader, err := NewReader(bytes.NewReader(s.Data), int64(len(s.Data))) reader, err := NewReader(bytes.NewReader(s.Data), int64(len(s.Data)))
if err == nil { if err == nil {
defer reader.Close() defer reader.Close()
doc, err := reader.Doc() doc, err := reader.DocContext(pageContext)
if err == nil { if err == nil {
renderer := r.childRenderer(reader) renderer := r.childRenderer(reader)
for _, pageRef := range doc.Pages.Page { for _, pageRef := range doc.Pages.Page {
content, err := reader.PageContent(pageRef) content, err := reader.PageContentContext(pageContext, pageRef)
if err != nil { if err != nil {
if pageContext.Err() != nil {
return
}
continue continue
} }
sealBox, err := renderer.GetPageBox(content) sealBox, err := renderer.GetPageBox(content)
@@ -64,7 +81,7 @@ func (r *Renderer) renderStamp(ctx *canvas.Context, s Stamp, pageH float64) {
} }
} }
if len(s.Data) > 0 { if len(s.Data) > 0 {
img, _, err := decodeImageData(s.Data) img, _, err := decodeImageDataContext(pageContext, s.Data)
if err == nil { if err == nil {
if r.decodeImages { if r.decodeImages {
img = imagePixelSource(img) img = imagePixelSource(img)
@@ -79,12 +96,25 @@ func (r *Renderer) renderStamp(ctx *canvas.Context, s Stamp, pageH float64) {
// 入参: data OFD印章数据 // 入参: data OFD印章数据
// 返回: image.Image 印章图像 // 返回: image.Image 印章图像
func (r *Renderer) renderOFDStampImage(data []byte) image.Image { func (r *Renderer) renderOFDStampImage(data []byte) image.Image {
ctx := r.pageContext
if ctx == nil {
ctx = context.Background()
}
defer func() {
if err := ctx.Err(); err != nil {
r.renderError = err
}
}()
if err := ctx.Err(); err != nil {
r.renderError = err
return nil
}
reader, err := NewReader(bytes.NewReader(data), int64(len(data))) reader, err := NewReader(bytes.NewReader(data), int64(len(data)))
if err != nil { if err != nil {
return nil return nil
} }
defer reader.Close() defer reader.Close()
doc, err := reader.Doc() doc, err := reader.DocContext(ctx)
if err != nil { if err != nil {
return nil return nil
} }
@@ -92,8 +122,11 @@ func (r *Renderer) renderOFDStampImage(data []byte) image.Image {
renderer.decodeImages = true renderer.decodeImages = true
renderer.TransparentBackground = true renderer.TransparentBackground = true
for _, pageRef := range doc.Pages.Page { for _, pageRef := range doc.Pages.Page {
content, err := reader.PageContent(pageRef) content, err := reader.PageContentContext(ctx, pageRef)
if err != nil { if err != nil {
if ctx.Err() != nil {
return nil
}
continue continue
} }
img, err := renderer.RenderToImage(content) img, err := renderer.RenderToImage(content)