diff --git a/ofdgo_image.go b/ofdgo_image.go index f14305d..8aff37a 100644 --- a/ofdgo_image.go +++ b/ofdgo_image.go @@ -22,6 +22,7 @@ import ( "image" "image/color" _ "image/gif" + "io" "math" _ "github.com/xiaoqidun/j2kgo" @@ -141,6 +142,21 @@ func (s *transparentEdgeImage64) RGBA64At(x, y int) color.RGBA64 { // 入参: data 图片数据 // 返回: image.Image 图片对象, string 图片格式, error 错误信息 func decodeImageData(data []byte) (image.Image, string, error) { + return decodeImageDataContext(context.Background(), data) +} + +// decodeImageDataContext 解码图片并传递取消状态,PNG和JPEG仍保留惰性像素解码 +// 入参: ctx 取消上下文, data 只读图片编码 +// 返回: image.Image 图片对象, string 图片格式, error 解码或取消错误 +func decodeImageDataContext(ctx context.Context, data []byte) (img image.Image, format string, err error) { + if err := ctx.Err(); err != nil { + return nil, "", err + } + defer func() { + if cancelErr := ctx.Err(); cancelErr != nil { + img, err = nil, cancelErr + } + }() if isJPEGData(data) || isPNGData(data) { img, err := newEncodedImage(data) if err != nil { @@ -153,14 +169,17 @@ func decodeImageData(data []byte) (image.Image, string, error) { if err != nil { return nil, "tiff", err } - img, err := decodeTIFFImage(nil, data, layout) + img, err := decodeTIFFImage(ctx, data, layout) return img, "tiff", err } - img, format, err := image.Decode(bytes.NewReader(data)) + img, format, err = image.Decode(imageInput{ReadCloser: io.NopCloser(bytes.NewReader(data)), context: ctx}) if err == nil { return img, normalizeSealType(format), nil } - if img, err := decodeBMPImage(data); err == nil { + if ctx.Err() != nil { + return nil, "", ctx.Err() + } + if img, err := decodeBMPImageContext(ctx, data); err == nil { return img, "bmp", nil } return nil, "", err diff --git a/ofdgo_image_resource.go b/ofdgo_image_resource.go index b880800..1a4f5d5 100644 --- a/ofdgo_image_resource.go +++ b/ofdgo_image_resource.go @@ -16,12 +16,12 @@ package ofdgo import ( "bytes" + "context" "fmt" "image" "image/color" _ "image/jpeg" _ "image/png" - "io" "sync" ) @@ -144,6 +144,11 @@ func newEncodedImage(data []byte) (*EncodedImage, error) { // 入参: resPath 图片资源路径 // 返回: image.Image 图片对象, error 读取错误 func (r *Renderer) cachedImageResource(resPath string) (image.Image, error) { + if r.pageContext != nil { + if err := r.pageContext.Err(); err != nil { + return nil, err + } + } resPath = cleanPackagePath(r.Reader.ResPath(resPath)) img, ok := r.imageCache.get(resPath) if !ok { @@ -192,19 +197,18 @@ func (r *Renderer) decodeImageResource(resPath string) (image.Image, error) { return img, nil } -// readImageResource 读取图片资源并保留可直接嵌入的原始编码 +// readImageResource 按页面上下文读取图片,借用已加载的只读编码 // 入参: resPath 图片资源路径 // 返回: image.Image 图片对象, error 读取或解码错误 func (r *Renderer) readImageResource(resPath string) (image.Image, error) { - rc, err := r.Reader.openFile(resPath) + ctx := r.pageContext + if ctx == nil { + ctx = context.Background() + } + data, err := r.Reader.readFileViewContext(ctx, resPath) if err != nil { return nil, err } - defer rc.Close() - data, err := io.ReadAll(rc) - if err != nil { - return nil, err - } - img, _, err := decodeImageData(data) + img, _, err := decodeImageDataContext(ctx, data) return img, err }