diff options
author | Bjørn Erik Pedersen <[email protected]> | 2019-09-01 17:27:21 +0200 |
---|---|---|
committer | Bjørn Erik Pedersen <[email protected]> | 2019-09-02 16:37:28 +0200 |
commit | ce47c21a2998630f8edcbd056983d9c59a80b676 (patch) | |
tree | 01b7f680f631cc3418fa0e8457bff2b95a6f553d /resources/image.go | |
parent | de9cbf61954201943a7b170a7d0a8b34afb5942c (diff) | |
download | hugo-ce47c21a2998630f8edcbd056983d9c59a80b676.tar.gz hugo-ce47c21a2998630f8edcbd056983d9c59a80b676.zip |
resources: Cache Exif data to disk
```bash
name old time/op new time/op delta
ImageExif/Cold_cache-4 312µs ±28% 355µs ± 7% ~ (p=0.343 n=4+4)
ImageExif/Cold_cache,_10-4 479µs ± 6% 546µs ± 0% +13.91% (p=0.029 n=4+4)
ImageExif/Warm_cache-4 272µs ± 1% 81µs ± 5% -70.30% (p=0.029 n=4+4)
name old alloc/op new alloc/op delta
ImageExif/Cold_cache-4 151kB ± 0% 161kB ± 0% +6.46% (p=0.029 n=4+4)
ImageExif/Cold_cache,_10-4 179kB ± 0% 189kB ± 0% +5.49% (p=0.029 n=4+4)
ImageExif/Warm_cache-4 151kB ± 0% 13kB ± 0% -91.52% (p=0.029 n=4+4)
name old allocs/op new allocs/op delta
ImageExif/Cold_cache-4 1.03k ± 0% 1.21k ± 0% +17.78% (p=0.029 n=4+4)
ImageExif/Cold_cache,_10-4 1.65k ± 0% 1.83k ± 0% +11.09% (p=0.029 n=4+4)
ImageExif/Warm_cache-4 1.03k ± 0% 0.28k ± 0% -72.40% (p=0.029 n=4+4)
```
Fixes #6291
Diffstat (limited to 'resources/image.go')
-rw-r--r-- | resources/image.go | 84 |
1 files changed, 69 insertions, 15 deletions
diff --git a/resources/image.go b/resources/image.go index f335e97da..8242f7119 100644 --- a/resources/image.go +++ b/resources/image.go @@ -14,15 +14,20 @@ package resources import ( + "encoding/json" "fmt" "image" "image/draw" _ "image/gif" _ "image/png" + "io" + "io/ioutil" "os" + "path" "strings" "sync" + "github.com/gohugoio/hugo/cache/filecache" "github.com/gohugoio/hugo/resources/images/exif" "github.com/gohugoio/hugo/resources/internal" @@ -55,43 +60,81 @@ type imageResource struct { // original (first). root *imageResource - exifInit sync.Once - exifInitErr error - exif *exif.Exif + metaInit sync.Once + metaInitErr error + meta *imageMeta baseResource } +type imageMeta struct { + Exif *exif.Exif +} + func (i *imageResource) Exif() (*exif.Exif, error) { return i.root.getExif() } func (i *imageResource) getExif() (*exif.Exif, error) { - i.exifInit.Do(func() { + i.metaInit.Do(func() { + supportsExif := i.Format == images.JPEG || i.Format == images.TIFF if !supportsExif { return + } - f, err := i.root.ReadSeekCloser() - if err != nil { - i.exifInitErr = err - return + key := i.getImageMetaCacheTargetPath() + + read := func(info filecache.ItemInfo, r io.Reader) error { + meta := &imageMeta{} + data, err := ioutil.ReadAll(r) + if err != nil { + return err + } + + if err = json.Unmarshal(data, &meta); err != nil { + return err + } + + i.meta = meta + + return nil } - defer f.Close() - x, err := i.getSpec().imaging.DecodeExif(f) - if err != nil { - i.exifInitErr = err - return + create := func(info filecache.ItemInfo, w io.WriteCloser) (err error) { + + f, err := i.root.ReadSeekCloser() + if err != nil { + i.metaInitErr = err + return + } + defer f.Close() + + x, err := i.getSpec().imaging.DecodeExif(f) + if err != nil { + i.metaInitErr = err + return + } + + i.meta = &imageMeta{Exif: x} + + // Also write it to cache + enc := json.NewEncoder(w) + return enc.Encode(i.meta) + } - i.exif = x + _, i.metaInitErr = i.getSpec().imageCache.fileCache.ReadOrCreate(key, read, create) }) - return i.exif, i.exifInitErr + if i.metaInitErr != nil { + return nil, i.metaInitErr + } + + return i.meta.Exif, nil } func (i *imageResource) Clone() resource.Resource { @@ -271,6 +314,17 @@ func (i *imageResource) setBasePath(conf images.ImageConfig) { i.getResourcePaths().relTargetDirFile = i.relTargetPathFromConfig(conf) } +func (i *imageResource) getImageMetaCacheTargetPath() string { + const imageMetaVersionNumber = 1 // Increment to invalidate the meta cache + + cfg := i.getSpec().imaging.Cfg + df := i.getResourcePaths().relTargetDirFile + p1, _ := helpers.FileAndExt(df.file) + h, _ := i.hash() + idStr := internal.HashString(h, i.size(), imageMetaVersionNumber, cfg) + return path.Join(df.dir, fmt.Sprintf("%s%s.json", p1, idStr)) +} + func (i *imageResource) relTargetPathFromConfig(conf images.ImageConfig) dirFile { p1, p2 := helpers.FileAndExt(i.getResourcePaths().relTargetDirFile.file) if conf.Action == "trace" { |