From e5f34c6ea65986be24c74ef06c34d7a4d64a07a2 Mon Sep 17 00:00:00 2001 From: xiaoqidun Date: Sun, 11 Oct 2026 19:21:57 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E5=9B=BE=E5=83=8F=E5=A4=84=E7=90=86):=20?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E5=9B=BE=E5=83=8F=E5=8E=8B=E7=BC=A9=E5=AF=86?= =?UTF-8?q?=E5=BA=A6=E4=B8=8E=E6=AF=94=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 2 +- go.sum | 4 +- ofdgo_compression_raster.go | 76 +++++++++++++++++++------------------ ofdgo_compression_tiff.go | 2 +- 4 files changed, 44 insertions(+), 40 deletions(-) diff --git a/go.mod b/go.mod index f390bb3..ce4e68b 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/tdewolff/canvas v0.0.0-20260923214215-09804640d00c github.com/xiaoqidun/j2kgo v0.0.0-20261011021706-cedb3037ff6e github.com/xiaoqidun/jbig2 v1.1.4 - github.com/xiaoqidun/pdfgo v0.0.0-20261011103616-6cafccc7f8f6 + github.com/xiaoqidun/pdfgo v0.0.0-20261011112043-b424d0248fb2 golang.org/x/crypto v0.58.0 golang.org/x/image v0.47.0 golang.org/x/text v0.43.0 diff --git a/go.sum b/go.sum index d1da391..e527a08 100644 --- a/go.sum +++ b/go.sum @@ -62,8 +62,8 @@ github.com/xiaoqidun/j2kgo v0.0.0-20261011021706-cedb3037ff6e h1:OuRcvG5g5AieBN3 github.com/xiaoqidun/j2kgo v0.0.0-20261011021706-cedb3037ff6e/go.mod h1:DCwAfuDzCDYqUiAlZ7BDwigTjaXw7o9L1FtEma/D1aA= github.com/xiaoqidun/jbig2 v1.1.4 h1:LF6J1si4JY+TszTh9+m4KAg9/ba0JjfXoGtQTQC2S8c= github.com/xiaoqidun/jbig2 v1.1.4/go.mod h1:9jromqVwMqlptUDEt6Yip8vqYA5I1YjhG7FgMl/Z2dA= -github.com/xiaoqidun/pdfgo v0.0.0-20261011103616-6cafccc7f8f6 h1:TW7d8qguwR6+WAxXw4ncAXdHTSrAgz6zjj7NmKbipyo= -github.com/xiaoqidun/pdfgo v0.0.0-20261011103616-6cafccc7f8f6/go.mod h1:hkZn8gHOI94K0fE2ynbXaE8J5T0/jCvoTS/yroKgb+E= +github.com/xiaoqidun/pdfgo v0.0.0-20261011112043-b424d0248fb2 h1:bPq5g3O7XWOQAKG46vUYkVYXjFGiHhlvHhyjvlnJ9H8= +github.com/xiaoqidun/pdfgo v0.0.0-20261011112043-b424d0248fb2/go.mod h1:hkZn8gHOI94K0fE2ynbXaE8J5T0/jCvoTS/yroKgb+E= 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_compression_raster.go b/ofdgo_compression_raster.go index a05e2e9..555a8ae 100644 --- a/ofdgo_compression_raster.go +++ b/ofdgo_compression_raster.go @@ -123,10 +123,10 @@ func optimizeBMPResource(ctx context.Context, data []byte, options CompressionOp } // optimizeRasterResource 编码已解码的资源图片,同步降采样后的像素密度,仅采用更小结果 +// 绝对密度在降采样后量化为PNG整数,避免原始有理数密度被二次舍入 // 入参: ctx 取消上下文, data 原编码, pixels 像素, options 压缩选项, size 像素需求, density 像素密度 // 返回: []byte 图片编码, error 编码或取消错误 func optimizeRasterResource(ctx context.Context, data []byte, pixels image.Image, options CompressionOptions, size image.Point, density rasterDensity) ([]byte, error) { - width, height := pixels.Bounds().Dx(), pixels.Bounds().Dy() var encoded bytes.Buffer limit := &outputCompressionBuffer{buffer: &encoded, limit: outputOptimizationBufferLimit} if err := pdfgo.EncodePNG(ctx, limit, pixels); err != nil { @@ -135,43 +135,47 @@ func optimizeRasterResource(ctx context.Context, data []byte, pixels image.Image } return nil, err } - var candidate []byte - var err error - if density.x == 0 && density.y == 0 { - candidate, err = pdfgo.OptimizeImageResource(ctx, encoded.Bytes(), options, size) - } else { - candidate, err = pdfgo.OptimizeImageSize(ctx, encoded.Bytes(), options, size) - if err == nil { - config, _, configErr := image.DecodeConfig(bytes.NewReader(candidate)) - if configErr != nil { - return nil, configErr - } - x := density.x * float64(config.Width) / float64(width) - y := density.y * float64(config.Height) / float64(height) - if density.unit == 0 { - factor := float64(math.MaxUint32) / max(x, y) - x, y = x*factor, y*factor - } - x, y = math.Round(x), math.Round(y) - if x > math.MaxUint32 || y > math.MaxUint32 || density.x > 0 && x < 1 || density.y > 0 && y < 1 { - return data, ctx.Err() - } - chunk := make([]byte, 21) - binary.BigEndian.PutUint32(chunk, 9) - copy(chunk[4:], "pHYs") - binary.BigEndian.PutUint32(chunk[8:], uint32(x)) - binary.BigEndian.PutUint32(chunk[12:], uint32(y)) - chunk[16] = density.unit - binary.BigEndian.PutUint32(chunk[17:], crc32.ChecksumIEEE(chunk[4:17])) - var output bytes.Buffer - writer := imageMetadataWriter{writer: &output, skip: 33, data: chunk} - if _, err = writer.Write(candidate); err == nil { - candidate = output.Bytes() - } + input := encoded.Bytes() + hasDensity := density.x != 0 || density.y != 0 + if hasDensity && density.unit == 1 { + var err error + input, err = pdfgo.OptimizeImageSize(ctx, input, options, size) + if err != nil { + return nil, err } + config, _, err := image.DecodeConfig(bytes.NewReader(input)) + if err != nil { + return nil, err + } + density.x *= float64(config.Width) / float64(pixels.Bounds().Dx()) + density.y *= float64(config.Height) / float64(pixels.Bounds().Dy()) } - if err != nil { - return nil, err + if hasDensity { + x, y := math.Round(density.x), math.Round(density.y) + if x > math.MaxInt32 || y > math.MaxInt32 || density.x > 0 && x < 1 || density.y > 0 && y < 1 || len(input) > outputOptimizationBufferLimit-21 { + return data, ctx.Err() + } + chunk := make([]byte, 21) + binary.BigEndian.PutUint32(chunk, 9) + copy(chunk[4:], "pHYs") + binary.BigEndian.PutUint32(chunk[8:], uint32(x)) + binary.BigEndian.PutUint32(chunk[12:], uint32(y)) + chunk[16] = density.unit + binary.BigEndian.PutUint32(chunk[17:], crc32.ChecksumIEEE(chunk[4:17])) + var output bytes.Buffer + writer := imageMetadataWriter{writer: &output, skip: 33, data: chunk} + if _, err := writer.Write(input); err != nil { + return nil, err + } + input = output.Bytes() + } + candidate := input + if !hasDensity || density.unit == 0 { + var err error + candidate, err = pdfgo.OptimizeImageResource(ctx, input, options, size) + if err != nil { + return nil, err + } } if err := ctx.Err(); err != nil { return nil, err diff --git a/ofdgo_compression_tiff.go b/ofdgo_compression_tiff.go index f16cbcb..340bd82 100644 --- a/ofdgo_compression_tiff.go +++ b/ofdgo_compression_tiff.go @@ -157,7 +157,7 @@ func tiffCompressionDensity(data []byte, layout tiffImageLayout) (rasterDensity, } density = rasterDensity{x: float64(x[0]) / float64(x[1]) * factor, y: float64(y[0]) / float64(y[1]) * factor, unit: 1} } - if math.Round(density.x) < 1 || math.Round(density.y) < 1 || math.Round(density.x) > math.MaxUint32 || math.Round(density.y) > math.MaxUint32 { + if math.Round(density.x) < 1 || math.Round(density.y) < 1 || math.Round(density.x) > math.MaxInt32 || math.Round(density.y) > math.MaxInt32 { return density, false } if layout.orientation >= 5 {