]> git.maquefel.me Git - brevno-suite/hugo/commitdiff
Decode webp.ImageConfig natively
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Tue, 13 Jan 2026 11:28:47 +0000 (12:28 +0100)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Tue, 13 Jan 2026 16:58:34 +0000 (17:58 +0100)
This has 2 main benefits:

1. When you only need width/height, we don't need to spin up a WASM runtime.
2. When all processed images are cached in the file cache, we don't need to spin up a WASM runtime.

The above is only really visible for smaller sites, but it's annoying to potentially have a site building in 15ms take e.g. 200ms because of WASM startup time.

Fixes #14371

go.mod
go.sum
resources/images/codec.go
resources/images/exif/exif.go

diff --git a/go.mod b/go.mod
index b2f609c839c471f3fe8d9a25438a7bceec561c01..f4c3031f7df3f07cf61907785436d0d3af92a3b7 100644 (file)
--- a/go.mod
+++ b/go.mod
@@ -14,7 +14,7 @@ require (
        github.com/bep/golibsass v1.2.0
        github.com/bep/goportabletext v0.1.0
        github.com/bep/helpers v0.6.0
-       github.com/bep/imagemeta v0.12.1
+       github.com/bep/imagemeta v0.13.0
        github.com/bep/lazycache v0.8.0
        github.com/bep/logg v0.4.0
        github.com/bep/mclib v1.20400.20402
@@ -78,7 +78,7 @@ require (
        golang.org/x/mod v0.31.0
        golang.org/x/net v0.48.0
        golang.org/x/sync v0.19.0
-       golang.org/x/text v0.32.0
+       golang.org/x/text v0.33.0
        golang.org/x/tools v0.40.0
        google.golang.org/api v0.255.0
        rsc.io/qr v0.2.0
diff --git a/go.sum b/go.sum
index 7708058ae8645afe13b3261ae7d4137d1bf6f7aa..59ab21bee19b6aa7e95f650c1738925ec6f39e4d 100644 (file)
--- a/go.sum
+++ b/go.sum
@@ -162,6 +162,8 @@ github.com/bep/helpers v0.6.0 h1:qtqMCK8XPFNM9hp5Ztu9piPjxNNkk8PIyUVjg6v8Bsw=
 github.com/bep/helpers v0.6.0/go.mod h1:IOZlgx5PM/R/2wgyCatfsgg5qQ6rNZJNDpWGXqDR044=
 github.com/bep/imagemeta v0.12.1 h1:43sIg/XJhXLVOo6troJFj9dyUr1jH+VN2UjO4/l26cQ=
 github.com/bep/imagemeta v0.12.1/go.mod h1:23AF6O+4fUi9avjiydpKLStUNtJr5hJB4rarG18JpN8=
+github.com/bep/imagemeta v0.13.0 h1:xVwqXjxAjtfM5xv9fth8lHq+JsTUy16Ym+HI+sLhMBU=
+github.com/bep/imagemeta v0.13.0/go.mod h1:3psQjuZwn53rPCa86ai0p4KKnO+QArpuWLRdi5/30q8=
 github.com/bep/lazycache v0.8.0 h1:lE5frnRjxaOFbkPZ1YL6nijzOPPz6zeXasJq8WpG4L8=
 github.com/bep/lazycache v0.8.0/go.mod h1:BQ5WZepss7Ko91CGdWz8GQZi/fFnCcyWupv8gyTeKwk=
 github.com/bep/logg v0.4.0 h1:luAo5mO4ZkhA5M1iDVDqDqnBBnlHjmtZF6VAyTp+nCQ=
@@ -722,6 +724,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
 golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
+golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
+golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
index b36c1b15be81b1ee02a1ae7529badca0e38a4577..b70d054563d863f77b15366931742b454aba00c0 100644 (file)
@@ -18,6 +18,7 @@ import (
        "errors"
        "fmt"
        "image"
+       "image/color"
        "image/color/palette"
        "image/draw"
        "image/gif"
@@ -25,6 +26,7 @@ import (
        "image/png"
        "io"
 
+       "github.com/bep/imagemeta"
        "github.com/gohugoio/hugo/common/himage"
        "golang.org/x/image/bmp"
        "golang.org/x/image/tiff"
@@ -203,8 +205,30 @@ func (d *Codec) DecodeConfig(r io.Reader) (image.Config, string, error) {
        if err != nil {
                return image.Config{}, "", err
        }
+       r = rr
        if format == WEBP {
-               cfg, err := d.webp.DecodeConfig(rr)
+               if rs, ok := r.(io.ReadSeeker); ok {
+                       rs.Seek(0, 0)
+                       // Avoid spinning up a WASM runtime if we don't have to.
+                       res, err := imagemeta.Decode(
+                               imagemeta.Options{
+                                       R:           rs,
+                                       ImageFormat: imagemeta.WebP,
+                                       Sources:     imagemeta.CONFIG,
+                               },
+                       )
+                       if err == nil {
+                               return image.Config{
+                                       Width:      res.ImageConfig.Width,
+                                       Height:     res.ImageConfig.Height,
+                                       ColorModel: color.RGBAModel,
+                               }, "webp", nil
+                       }
+                       rs.Seek(0, 0)
+                       r = rs
+               }
+               // Fallback to the webp codec config decode.
+               cfg, err := d.webp.DecodeConfig(r)
                return cfg, "webp", err
        }
 
index a7f0e0757a7cbfddf31207fc56378db99e8f8bad..8819cd6fe33280ce1fefaf37341904ce905b6b76 100644 (file)
@@ -187,7 +187,7 @@ func (d *Decoder) Decode(filename string, format imagemeta.ImageFormat, r io.Rea
                }
        }
 
-       err = imagemeta.Decode(
+       _, err = imagemeta.Decode(
                imagemeta.Options{
                        R:               r.(io.ReadSeeker),
                        ImageFormat:     format,