mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-21 20:46:30 -05:00
parent
11fcda971c
commit
f9b3c0f486
8 changed files with 76 additions and 14 deletions
|
@ -34,6 +34,19 @@ A shorter version of the above, if you only need to apply the filter once:
|
|||
|
||||
The above will overlay `$logo` in the upper left corner of `$img` (at position `x=50, y=50`).
|
||||
|
||||
## Opacity
|
||||
|
||||
{{% funcsig %}}
|
||||
images.Opacity SRC OPACITY
|
||||
{{% /funcsig %}}
|
||||
|
||||
Opacity creates a filter that changes the opacity of an image.
|
||||
The OPACITY parameter must be in range (0, 1).
|
||||
|
||||
```go-html-template
|
||||
{{ $img := $img.Filter (images.Opacity 0.5 )}}
|
||||
```
|
||||
|
||||
## Text
|
||||
|
||||
Using the `Text` filter, you can add text to an image.
|
||||
|
|
|
@ -63,7 +63,7 @@ var eq = qt.CmpEquals(
|
|||
}
|
||||
return p1.Name() == p2.Name() && p1.Size() == p2.Size() && p1.IsDir() == p2.IsDir()
|
||||
}),
|
||||
//cmp.Comparer(func(p1, p2 *genericResource) bool { return p1 == p2 }),
|
||||
// cmp.Comparer(func(p1, p2 *genericResource) bool { return p1 == p2 }),
|
||||
cmp.Comparer(func(m1, m2 media.Type) bool {
|
||||
return m1.Type == m2.Type
|
||||
}),
|
||||
|
@ -162,7 +162,6 @@ func TestImageTransformBasic(t *testing.T) {
|
|||
croppedAgain, err := image.Crop("300x300 topRight")
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(cropped, qt.Equals, croppedAgain)
|
||||
|
||||
}
|
||||
|
||||
func TestImageTransformFormat(t *testing.T) {
|
||||
|
@ -267,7 +266,6 @@ func TestImageBugs(t *testing.T) {
|
|||
c.Assert(resized, qt.Not(qt.IsNil))
|
||||
c.Assert(resized.Width(), qt.Equals, 100)
|
||||
c.Assert(resized.RelPermalink(), qt.Equals, "/a/_hu59e56ffff1bc1d8d122b1403d34e039f_90587_c876768085288f41211f768147ba2647.jpg")
|
||||
|
||||
})
|
||||
|
||||
// Issue #6137
|
||||
|
@ -278,7 +276,6 @@ func TestImageBugs(t *testing.T) {
|
|||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(resized, qt.Not(qt.IsNil))
|
||||
c.Assert(resized.Width(), qt.Equals, 200)
|
||||
|
||||
})
|
||||
|
||||
// Issue #7955
|
||||
|
@ -307,9 +304,7 @@ func TestImageBugs(t *testing.T) {
|
|||
c.Assert(resized.Width(), qt.Equals, test.targetWH)
|
||||
c.Assert(resized.Height(), qt.Equals, test.targetWH)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -613,7 +608,6 @@ func TestImageOperationsGoldenWebp(t *testing.T) {
|
|||
dir2 := filepath.FromSlash("testdata/golden_webp")
|
||||
|
||||
assetGoldenDirs(c, dir1, dir2)
|
||||
|
||||
}
|
||||
|
||||
func TestImageOperationsGolden(t *testing.T) {
|
||||
|
@ -621,7 +615,7 @@ func TestImageOperationsGolden(t *testing.T) {
|
|||
c.Parallel()
|
||||
|
||||
// Note, if you're enabling this on a MacOS M1 (ARM) you need to run the test with GOARCH=amd64.
|
||||
// GOARCH=amd64 go test -timeout 30s -run "^TestImageOperationsGolden$" ./resources -v
|
||||
// GOARCH=amd64 go test -count 1 -timeout 30s -run "^TestImageOperationsGolden$" ./resources -v
|
||||
// The above will print out a folder.
|
||||
// Replace testdata/golden with resources/_gen/images in that folder.
|
||||
devMode := false
|
||||
|
@ -644,6 +638,10 @@ func TestImageOperationsGolden(t *testing.T) {
|
|||
gopher, err = gopher.Resize("30x")
|
||||
c.Assert(err, qt.IsNil)
|
||||
|
||||
f := &images.Filters{}
|
||||
|
||||
sunset := fetchImageForSpec(spec, c, "sunset.jpg")
|
||||
|
||||
// Test PNGs with alpha channel.
|
||||
for _, img := range []string{"gopher-hero8.png", "gradient-circle.png"} {
|
||||
orig := fetchImageForSpec(spec, c, img)
|
||||
|
@ -653,7 +651,15 @@ func TestImageOperationsGolden(t *testing.T) {
|
|||
rel := resized.RelPermalink()
|
||||
|
||||
c.Assert(rel, qt.Not(qt.Equals), "")
|
||||
|
||||
}
|
||||
|
||||
// Check the Opacity filter.
|
||||
opacity30, err := orig.Filter(f.Opacity(30))
|
||||
c.Assert(err, qt.IsNil)
|
||||
overlay, err := sunset.Filter(f.Overlay(opacity30.(images.ImageSource), 20, 20))
|
||||
rel := overlay.RelPermalink()
|
||||
c.Assert(rel, qt.Not(qt.Equals), "")
|
||||
}
|
||||
|
||||
// A simple Gif file (no animation).
|
||||
|
@ -699,8 +705,6 @@ func TestImageOperationsGolden(t *testing.T) {
|
|||
c.Assert(rel, qt.Not(qt.Equals), "")
|
||||
}
|
||||
|
||||
f := &images.Filters{}
|
||||
|
||||
filters := []gift.Filter{
|
||||
f.Grayscale(),
|
||||
f.GaussianBlur(6),
|
||||
|
@ -746,11 +750,9 @@ func TestImageOperationsGolden(t *testing.T) {
|
|||
dir2 := filepath.FromSlash("testdata/golden")
|
||||
|
||||
assetGoldenDirs(c, dir1, dir2)
|
||||
|
||||
}
|
||||
|
||||
func assetGoldenDirs(c *qt.C, dir1, dir2 string) {
|
||||
|
||||
// The two dirs above should now be the same.
|
||||
dirinfos1, err := os.ReadDir(dir1)
|
||||
c.Assert(err, qt.IsNil)
|
||||
|
|
|
@ -28,8 +28,7 @@ import (
|
|||
// Increment for re-generation of images using these filters.
|
||||
const filterAPIVersion = 0
|
||||
|
||||
type Filters struct {
|
||||
}
|
||||
type Filters struct{}
|
||||
|
||||
// Overlay creates a filter that overlays src at position x y.
|
||||
func (*Filters) Overlay(src ImageSource, x, y any) gift.Filter {
|
||||
|
@ -39,6 +38,15 @@ func (*Filters) Overlay(src ImageSource, x, y any) gift.Filter {
|
|||
}
|
||||
}
|
||||
|
||||
// Opacity creates a filter that changes the opacity of an image.
|
||||
// The opacity parameter must be in range (0, 1).
|
||||
func (*Filters) Opacity(opacity any) gift.Filter {
|
||||
return filter{
|
||||
Options: newFilterOpts(opacity),
|
||||
Filter: opacityFilter{opacity: cast.ToFloat32(opacity)},
|
||||
}
|
||||
}
|
||||
|
||||
// Text creates a filter that draws text with the given options.
|
||||
func (*Filters) Text(text string, options ...any) gift.Filter {
|
||||
tf := textFilter{
|
||||
|
|
39
resources/images/opacity.go
Normal file
39
resources/images/opacity.go
Normal file
|
@ -0,0 +1,39 @@
|
|||
// 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 = (*opacityFilter)(nil)
|
||||
|
||||
type opacityFilter struct {
|
||||
opacity float32
|
||||
}
|
||||
|
||||
func (f opacityFilter) Draw(dst draw.Image, src image.Image, options *gift.Options) {
|
||||
// 0 is fully transparent and 255 is opaque.
|
||||
alpha := uint8(f.opacity * 255)
|
||||
mask := image.NewUniform(color.Alpha{alpha})
|
||||
draw.DrawMask(dst, dst.Bounds(), src, image.Point{}, mask, image.Point{}, draw.Over)
|
||||
}
|
||||
|
||||
func (f opacityFilter) Bounds(srcBounds image.Rectangle) image.Rectangle {
|
||||
return image.Rect(0, 0, srcBounds.Dx(), srcBounds.Dy())
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 58 KiB |
Binary file not shown.
After Width: | Height: | Size: 40 KiB |
Binary file not shown.
After Width: | Height: | Size: 56 KiB |
Binary file not shown.
After Width: | Height: | Size: 45 KiB |
Loading…
Reference in a new issue