}
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
}),
croppedAgain, err := image.Crop("300x300 topRight")
c.Assert(err, qt.IsNil)
c.Assert(cropped, qt.Equals, croppedAgain)
-
}
func TestImageTransformFormat(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
c.Assert(err, qt.IsNil)
c.Assert(resized, qt.Not(qt.IsNil))
c.Assert(resized.Width(), qt.Equals, 200)
-
})
// Issue #7955
c.Assert(resized.Width(), qt.Equals, test.targetWH)
c.Assert(resized.Height(), qt.Equals, test.targetWH)
})
-
}
-
})
}
dir2 := filepath.FromSlash("testdata/golden_webp")
assetGoldenDirs(c, dir1, dir2)
-
}
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
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)
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).
c.Assert(rel, qt.Not(qt.Equals), "")
}
- f := &images.Filters{}
-
filters := []gift.Filter{
f.Grayscale(),
f.GaussianBlur(6),
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)
// 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 {
}
}
+// 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{
--- /dev/null
+// 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())
+}