mirror of
https://github.com/gohugoio/hugo.git
synced 2025-08-24 21:56:05 +02:00
Allow images to be cropped without being resized
Introduces the Crop method for image processing which implements gift.CropToSize. Also allows a smartCrop without resizing, and updates the documentation. Fixes #9499
This commit is contained in:
committed by
Bjørn Erik Pedersen
parent
aebde49b88
commit
7732da9f93
@@ -100,6 +100,10 @@ func (e *errorResource) Width() int {
|
||||
panic(e.error)
|
||||
}
|
||||
|
||||
func (e *errorResource) Crop(spec string) (resource.Image, error) {
|
||||
panic(e.error)
|
||||
}
|
||||
|
||||
func (e *errorResource) Fill(spec string) (resource.Image, error) {
|
||||
panic(e.error)
|
||||
}
|
||||
|
@@ -181,6 +181,19 @@ func (i *imageResource) Resize(spec string) (resource.Image, error) {
|
||||
})
|
||||
}
|
||||
|
||||
// Crop the image to the specified dimensions without resizing using the given anchor point.
|
||||
// Space delimited config: 200x300 TopLeft
|
||||
func (i *imageResource) Crop(spec string) (resource.Image, error) {
|
||||
conf, err := i.decodeImageConfig("crop", spec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return i.doWithImageConfig(conf, func(src image.Image) (image.Image, error) {
|
||||
return i.Proc.ApplyFiltersFromConfig(src, conf)
|
||||
})
|
||||
}
|
||||
|
||||
// Fit scales down the image using the specified resample filter to fit the specified
|
||||
// maximum width and height.
|
||||
func (i *imageResource) Fit(spec string) (resource.Image, error) {
|
||||
|
@@ -137,6 +137,22 @@ func TestImageTransformBasic(t *testing.T) {
|
||||
filledAgain, err := image.Fill("200x100 bottomLeft")
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(filled, eq, filledAgain)
|
||||
|
||||
cropped, err := image.Crop("300x300 topRight")
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(cropped.RelPermalink(), qt.Equals, "/a/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_300x300_crop_q68_linear_topright.jpg")
|
||||
assertWidthHeight(cropped, 300, 300)
|
||||
|
||||
smartcropped, err := image.Crop("200x200 smart")
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(smartcropped.RelPermalink(), qt.Equals, fmt.Sprintf("/a/sunset_hu59e56ffff1bc1d8d122b1403d34e039f_90587_200x200_crop_q68_linear_smart%d.jpg", 1))
|
||||
assertWidthHeight(smartcropped, 200, 200)
|
||||
|
||||
// Check cache
|
||||
croppedAgain, err := image.Crop("300x300 topRight")
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(cropped, eq, croppedAgain)
|
||||
|
||||
}
|
||||
|
||||
func TestImageTransformFormat(t *testing.T) {
|
||||
|
@@ -364,7 +364,7 @@ func (i ImageConfig) GetKey(format Format) string {
|
||||
|
||||
k += "_" + i.FilterStr
|
||||
|
||||
if strings.EqualFold(i.Action, "fill") {
|
||||
if strings.EqualFold(i.Action, "fill") || strings.EqualFold(i.Action, "crop") {
|
||||
k += "_" + anchor
|
||||
}
|
||||
|
||||
|
@@ -207,6 +207,21 @@ func (p *ImageProcessor) ApplyFiltersFromConfig(src image.Image, conf ImageConfi
|
||||
switch conf.Action {
|
||||
case "resize":
|
||||
filters = append(filters, gift.Resize(conf.Width, conf.Height, conf.Filter))
|
||||
case "crop":
|
||||
if conf.AnchorStr == smartCropIdentifier {
|
||||
bounds, err := p.smartCrop(src, conf.Width, conf.Height, conf.Filter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// First crop using the bounds returned by smartCrop.
|
||||
filters = append(filters, gift.Crop(bounds))
|
||||
// Then center crop the image to get an image the desired size without resizing.
|
||||
filters = append(filters, gift.CropToSize(conf.Width, conf.Height, gift.CenterAnchor))
|
||||
|
||||
} else {
|
||||
filters = append(filters, gift.CropToSize(conf.Width, conf.Height, conf.Anchor))
|
||||
}
|
||||
case "fill":
|
||||
if conf.AnchorStr == smartCropIdentifier {
|
||||
bounds, err := p.smartCrop(src, conf.Width, conf.Height, conf.Filter)
|
||||
|
@@ -62,6 +62,7 @@ type Image interface {
|
||||
type ImageOps interface {
|
||||
Height() int
|
||||
Width() int
|
||||
Crop(spec string) (Image, error)
|
||||
Fill(spec string) (Image, error)
|
||||
Fit(spec string) (Image, error)
|
||||
Resize(spec string) (Image, error)
|
||||
|
@@ -176,6 +176,10 @@ func (r *resourceAdapter) Data() interface{} {
|
||||
return r.target.Data()
|
||||
}
|
||||
|
||||
func (r *resourceAdapter) Crop(spec string) (resource.Image, error) {
|
||||
return r.getImageOps().Crop(spec)
|
||||
}
|
||||
|
||||
func (r *resourceAdapter) Fill(spec string) (resource.Image, error) {
|
||||
return r.getImageOps().Fill(spec)
|
||||
}
|
||||
|
Reference in New Issue
Block a user