github.com/pietrocarrara/hugo@v0.47.1/resource/smartcrop.go (about)

     1  // Copyright 2017-present 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 resource
    15  
    16  import (
    17  	"image"
    18  
    19  	"github.com/disintegration/imaging"
    20  	"github.com/muesli/smartcrop"
    21  )
    22  
    23  const (
    24  	// Do not change.
    25  	smartCropIdentifier = "smart"
    26  
    27  	// This is just a increment, starting on 1. If Smart Crop improves its cropping, we
    28  	// need a way to trigger a re-generation of the crops in the wild, so increment this.
    29  	smartCropVersionNumber = 1
    30  )
    31  
    32  // Needed by smartcrop
    33  type imagingResizer struct {
    34  	filter imaging.ResampleFilter
    35  }
    36  
    37  func (r imagingResizer) Resize(img image.Image, width, height uint) image.Image {
    38  	return imaging.Resize(img, int(width), int(height), r.filter)
    39  }
    40  
    41  func newSmartCropAnalyzer(filter imaging.ResampleFilter) smartcrop.Analyzer {
    42  	return smartcrop.NewAnalyzer(imagingResizer{filter: filter})
    43  }
    44  
    45  func smartCrop(img image.Image, width, height int, anchor imaging.Anchor, filter imaging.ResampleFilter) (*image.NRGBA, error) {
    46  
    47  	if width <= 0 || height <= 0 {
    48  		return &image.NRGBA{}, nil
    49  	}
    50  
    51  	srcBounds := img.Bounds()
    52  	srcW := srcBounds.Dx()
    53  	srcH := srcBounds.Dy()
    54  
    55  	if srcW <= 0 || srcH <= 0 {
    56  		return &image.NRGBA{}, nil
    57  	}
    58  
    59  	if srcW == width && srcH == height {
    60  		return imaging.Clone(img), nil
    61  	}
    62  
    63  	smart := newSmartCropAnalyzer(filter)
    64  
    65  	rect, err := smart.FindBestCrop(img, width, height)
    66  
    67  	if err != nil {
    68  		return nil, err
    69  	}
    70  
    71  	b := img.Bounds().Intersect(rect)
    72  
    73  	cropped, err := imaging.Crop(img, b), nil
    74  	if err != nil {
    75  		return nil, err
    76  	}
    77  
    78  	return imaging.Resize(cropped, width, height, filter), nil
    79  
    80  }