mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-07 20:30:36 -05:00
parent
db14238ba3
commit
3ed28e4bfe
4 changed files with 146 additions and 4 deletions
|
@ -104,7 +104,6 @@ The following example will add the text `Hugo rocks!` to the image with the spec
|
|||
You can load a custom font if needed. Load the font as a Hugo `Resource` and set it as an option:
|
||||
|
||||
```go-html-template
|
||||
|
||||
{{ $font := resources.GetRemote "https://github.com/google/fonts/raw/main/apache/roboto/static/Roboto-Black.ttf" }}
|
||||
{{ $img := resources.Get "/images/background.png" }}
|
||||
{{ $img = $img.Filter (images.Text "Hugo rocks!" (dict
|
||||
|
@ -112,6 +111,33 @@ You can load a custom font if needed. Load the font as a Hugo `Resource` and set
|
|||
))}}
|
||||
```
|
||||
|
||||
## Padding
|
||||
|
||||
Padding creates a filter that resizes the image canvas without resizing the image. The last argument is the canvas color, expressed as an RGB or RGBA [hexadecimal color]. The default value is `ffffffff` (opaque white). The preceding arguments are the padding values, in pixels, using the CSS [shorthand property] syntax. Negative padding values will crop the image.
|
||||
|
||||
[hexadecimal color]: https://developer.mozilla.org/en-US/docs/Web/CSS/hex-color
|
||||
[shorthand property]: https://developer.mozilla.org/en-US/docs/Web/CSS/Shorthand_properties#edges_of_a_box
|
||||
|
||||
{{% funcsig %}}
|
||||
images.Padding V1 [V2] [V3] [V4] [COLOR]
|
||||
{{% /funcsig %}}
|
||||
|
||||
This example resizes the image to 300px wide, converts it to the WebP format, adds 20px vertical padding and 50px horizontal padding, then sets the canvas color to dark green with 33% opacity.
|
||||
|
||||
```go-html-template
|
||||
{{ $img := resources.Get "images/a.jpg" }}
|
||||
{{ $filters := slice
|
||||
(images.Process "resize 300x webp")
|
||||
(images.Padding 20 50 "#0705")
|
||||
}}
|
||||
{{ $img = $img.Filter $filters }}
|
||||
```
|
||||
|
||||
To add a 2px gray border to an image:
|
||||
|
||||
```go-html-template
|
||||
{{ $img = $img.Filter (images.Padding 2 "#777") }}
|
||||
```
|
||||
|
||||
## Brightness
|
||||
|
||||
|
|
|
@ -56,13 +56,13 @@ func ColorToHexString(c color.Color) string {
|
|||
func hexStringToColor(s string) (color.Color, error) {
|
||||
s = strings.TrimPrefix(s, "#")
|
||||
|
||||
if len(s) != 3 && len(s) != 6 {
|
||||
if len(s) != 3 && len(s) != 4 && len(s) != 6 && len(s) != 8 {
|
||||
return nil, fmt.Errorf("invalid color code: %q", s)
|
||||
}
|
||||
|
||||
s = strings.ToLower(s)
|
||||
|
||||
if len(s) == 3 {
|
||||
if len(s) == 3 || len(s) == 4 {
|
||||
var v string
|
||||
for _, r := range s {
|
||||
v += string(r) + string(r)
|
||||
|
@ -80,7 +80,9 @@ func hexStringToColor(s string) (color.Color, error) {
|
|||
}
|
||||
|
||||
// Set Alfa to white.
|
||||
if len(s) == 6 {
|
||||
s += "ff"
|
||||
}
|
||||
|
||||
b, err := hex.DecodeString(s)
|
||||
if err != nil {
|
||||
|
|
|
@ -16,6 +16,7 @@ package images
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"image/color"
|
||||
|
||||
"github.com/gohugoio/hugo/common/hugio"
|
||||
"github.com/gohugoio/hugo/common/maps"
|
||||
|
@ -30,6 +31,7 @@ const filterAPIVersion = 0
|
|||
|
||||
type Filters struct{}
|
||||
|
||||
// Process creates a filter that processes an image using the given specification.
|
||||
func (*Filters) Process(spec any) gift.Filter {
|
||||
return filter{
|
||||
Options: newFilterOpts(spec),
|
||||
|
@ -110,6 +112,68 @@ func (*Filters) Text(text string, options ...any) gift.Filter {
|
|||
}
|
||||
}
|
||||
|
||||
// Padding creates a filter that resizes the image canvas without resizing the
|
||||
// image. The last argument is the canvas color, expressed as an RGB or RGBA
|
||||
// hexadecimal color. The default value is `ffffffff` (opaque white). The
|
||||
// preceding arguments are the padding values, in pixels, using the CSS
|
||||
// shorthand property syntax. Negative padding values will crop the image. The
|
||||
// signature is images.Padding V1 [V2] [V3] [V4] [COLOR].
|
||||
func (*Filters) Padding(args ...any) gift.Filter {
|
||||
if len(args) < 1 || len(args) > 5 {
|
||||
panic("the padding filter requires between 1 and 5 arguments")
|
||||
}
|
||||
|
||||
var top, right, bottom, left int
|
||||
var ccolor color.Color = color.White // canvas color
|
||||
var err error
|
||||
|
||||
_args := args // preserve original args for most stable hash
|
||||
|
||||
if vcs, ok := (args[len(args)-1]).(string); ok {
|
||||
ccolor, err = hexStringToColor(vcs)
|
||||
if err != nil {
|
||||
panic("invalid canvas color: specify RGB or RGBA using hex notation")
|
||||
}
|
||||
args = args[:len(args)-1]
|
||||
if len(args) == 0 {
|
||||
panic("not enough arguments: provide one or more padding values using the CSS shorthand property syntax")
|
||||
}
|
||||
}
|
||||
|
||||
var vals []int
|
||||
for _, v := range args {
|
||||
vi := cast.ToInt(v)
|
||||
if vi > 5000 {
|
||||
panic("padding values must not exceed 5000 pixels")
|
||||
}
|
||||
vals = append(vals, vi)
|
||||
}
|
||||
|
||||
switch len(args) {
|
||||
case 1:
|
||||
top, right, bottom, left = vals[0], vals[0], vals[0], vals[0]
|
||||
case 2:
|
||||
top, right, bottom, left = vals[0], vals[1], vals[0], vals[1]
|
||||
case 3:
|
||||
top, right, bottom, left = vals[0], vals[1], vals[2], vals[1]
|
||||
case 4:
|
||||
top, right, bottom, left = vals[0], vals[1], vals[2], vals[3]
|
||||
default:
|
||||
panic(fmt.Sprintf("too many padding values: received %d, expected maximum of 4", len(args)))
|
||||
}
|
||||
|
||||
return filter{
|
||||
Options: newFilterOpts(_args...),
|
||||
Filter: paddingFilter{
|
||||
top: top,
|
||||
right: right,
|
||||
bottom: bottom,
|
||||
left: left,
|
||||
ccolor: ccolor,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Brightness creates a filter that changes the brightness of an image.
|
||||
// The percentage parameter must be in range (-100, 100).
|
||||
func (*Filters) Brightness(percentage any) gift.Filter {
|
||||
|
|
50
resources/images/padding.go
Normal file
50
resources/images/padding.go
Normal file
|
@ -0,0 +1,50 @@
|
|||
// Copyright 2023 The Hugo Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package images
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
"image/draw"
|
||||
|
||||
"github.com/disintegration/gift"
|
||||
)
|
||||
|
||||
var _ gift.Filter = (*paddingFilter)(nil)
|
||||
|
||||
type paddingFilter struct {
|
||||
top, right, bottom, left int
|
||||
ccolor color.Color // canvas color
|
||||
}
|
||||
|
||||
func (f paddingFilter) Draw(dst draw.Image, src image.Image, options *gift.Options) {
|
||||
w := src.Bounds().Dx() + f.left + f.right
|
||||
h := src.Bounds().Dy() + f.top + f.bottom
|
||||
|
||||
if w < 1 {
|
||||
panic("final image width will be less than 1 pixel: check padding values")
|
||||
}
|
||||
if h < 1 {
|
||||
panic("final image height will be less than 1 pixel: check padding values")
|
||||
}
|
||||
|
||||
i := image.NewRGBA(image.Rect(0, 0, w, h))
|
||||
draw.Draw(i, i.Bounds(), image.NewUniform(f.ccolor), image.Point{}, draw.Src)
|
||||
gift.New().Draw(dst, i)
|
||||
gift.New().DrawAt(dst, src, image.Pt(f.left, f.top), gift.OverOperator)
|
||||
}
|
||||
|
||||
func (f paddingFilter) Bounds(srcBounds image.Rectangle) image.Rectangle {
|
||||
return image.Rect(0, 0, srcBounds.Dx()+f.left+f.right, srcBounds.Dy()+f.top+f.bottom)
|
||||
}
|
Loading…
Reference in a new issue