hugo

Fork of github.com/gohugoio/hugo with reverse pagination support

git clone git://git.shimmy1996.com/hugo.git

images.go (2466B)

    1 // Copyright 2019 The Hugo Authors. All rights reserved.
    2 //
    3 // Licensed under the Apache License, Version 2.0 (the "License");
    4 // you may not use this file except in compliance with the License.
    5 // You may obtain a copy of the License at
    6 // http://www.apache.org/licenses/LICENSE-2.0
    7 //
    8 // Unless required by applicable law or agreed to in writing, software
    9 // distributed under the License is distributed on an "AS IS" BASIS,
   10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   11 // See the License for the specific language governing permissions and
   12 // limitations under the License.
   13 
   14 // Package images provides template functions for manipulating images.
   15 package images
   16 
   17 import (
   18 	"image"
   19 	"sync"
   20 
   21 	"errors"
   22 
   23 	"github.com/gohugoio/hugo/resources/images"
   24 
   25 	// Importing image codecs for image.DecodeConfig
   26 	_ "image/gif"
   27 	_ "image/jpeg"
   28 	_ "image/png"
   29 
   30 	// Import webp codec
   31 	_ "golang.org/x/image/webp"
   32 
   33 	"github.com/gohugoio/hugo/deps"
   34 	"github.com/spf13/cast"
   35 )
   36 
   37 // New returns a new instance of the images-namespaced template functions.
   38 func New(deps *deps.Deps) *Namespace {
   39 	return &Namespace{
   40 		Filters: &images.Filters{},
   41 		cache:   map[string]image.Config{},
   42 		deps:    deps,
   43 	}
   44 }
   45 
   46 // Namespace provides template functions for the "images" namespace.
   47 type Namespace struct {
   48 	*images.Filters
   49 	cacheMu sync.RWMutex
   50 	cache   map[string]image.Config
   51 
   52 	deps *deps.Deps
   53 }
   54 
   55 // Config returns the image.Config for the specified path relative to the
   56 // working directory.
   57 func (ns *Namespace) Config(path any) (image.Config, error) {
   58 	filename, err := cast.ToStringE(path)
   59 	if err != nil {
   60 		return image.Config{}, err
   61 	}
   62 
   63 	if filename == "" {
   64 		return image.Config{}, errors.New("config needs a filename")
   65 	}
   66 
   67 	// Check cache for image config.
   68 	ns.cacheMu.RLock()
   69 	config, ok := ns.cache[filename]
   70 	ns.cacheMu.RUnlock()
   71 
   72 	if ok {
   73 		return config, nil
   74 	}
   75 
   76 	f, err := ns.deps.Fs.WorkingDirReadOnly.Open(filename)
   77 	if err != nil {
   78 		return image.Config{}, err
   79 	}
   80 	defer f.Close()
   81 
   82 	config, _, err = image.DecodeConfig(f)
   83 	if err != nil {
   84 		return config, err
   85 	}
   86 
   87 	ns.cacheMu.Lock()
   88 	ns.cache[filename] = config
   89 	ns.cacheMu.Unlock()
   90 
   91 	return config, nil
   92 }
   93 
   94 func (ns *Namespace) Filter(args ...any) (images.ImageResource, error) {
   95 	if len(args) < 2 {
   96 		return nil, errors.New("must provide an image and one or more filters")
   97 	}
   98 
   99 	img := args[len(args)-1].(images.ImageResource)
  100 	filtersv := args[:len(args)-1]
  101 
  102 	return img.Filter(filtersv...)
  103 }