You've already forked imgproxy
mirror of
https://github.com/imgproxy/imgproxy.git
synced 2025-11-27 22:48:53 +02:00
Implement padding option (#358)
* Implement padding option * Move padding `embed` to the right place * Move padding `embed` to the right place * Use general background option instead of specific padding's one * Make padding options css-like and fully optional * Add docs for new padding option * Return error if padding embed fails * Make padding outbounds and apply dpr for it Co-authored-by: Ilya Melnitskiy <melnitskiy_i_m@onyx-team.com>
This commit is contained in:
@@ -170,6 +170,24 @@ Defines an area of the image to be processed (crop before resize).
|
|||||||
* `width` and `height` define the size of the area. When `width` or `height` is set to `0`, imgproxy will use the full width/height of the source image.
|
* `width` and `height` define the size of the area. When `width` or `height` is set to `0`, imgproxy will use the full width/height of the source image.
|
||||||
* `gravity` _(optional)_ accepts the same values as [gravity](#gravity) option. When `gravity` is not set, imgproxy will use the value of the [gravity](#gravity) option.
|
* `gravity` _(optional)_ accepts the same values as [gravity](#gravity) option. When `gravity` is not set, imgproxy will use the value of the [gravity](#gravity) option.
|
||||||
|
|
||||||
|
#### Padding
|
||||||
|
|
||||||
|
```
|
||||||
|
padding:%top:%right:%bottom:%left
|
||||||
|
pd:%top:%right:%bottom:%left
|
||||||
|
```
|
||||||
|
|
||||||
|
Defines padding size in css manner. All arguments are optional but at least one dimension must be set. Padded space is filled according to [background](#background) option.
|
||||||
|
|
||||||
|
* `top` - top padding (and all other sides if they won't be set explicitly);
|
||||||
|
* `right` - right padding (and left if it won't be set explicitly);
|
||||||
|
* `bottom` - bottom padding;
|
||||||
|
* `left` - left padding.
|
||||||
|
|
||||||
|
**📝Notes:**
|
||||||
|
* Padding is applied after all image transformations (except watermark) and enlarges generated image which means that if your resize dimensions were 100x200px and you applied `padding:10` option then you will get 120x220px image.
|
||||||
|
* Padding follows [dpr](#dpr) option so it will be scaled too if you set it.
|
||||||
|
|
||||||
#### Trim
|
#### Trim
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
16
process.go
16
process.go
@@ -453,6 +453,22 @@ func transformImage(ctx context.Context, img *vipsImage, data []byte, po *proces
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if po.Padding.Enabled {
|
||||||
|
paddingTop := scaleInt(po.Padding.Top, po.Dpr)
|
||||||
|
paddingRight := scaleInt(po.Padding.Right, po.Dpr)
|
||||||
|
paddingBottom := scaleInt(po.Padding.Bottom, po.Dpr)
|
||||||
|
paddingLeft := scaleInt(po.Padding.Left, po.Dpr)
|
||||||
|
if err = img.Embed(
|
||||||
|
img.Width()+paddingLeft+paddingRight,
|
||||||
|
img.Height()+paddingTop+paddingBottom,
|
||||||
|
paddingLeft,
|
||||||
|
paddingTop,
|
||||||
|
po.Background,
|
||||||
|
); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
checkTimeout(ctx)
|
checkTimeout(ctx)
|
||||||
|
|
||||||
if po.Watermark.Enabled && watermark != nil {
|
if po.Watermark.Enabled && watermark != nil {
|
||||||
|
|||||||
@@ -100,6 +100,14 @@ type cropOptions struct {
|
|||||||
Gravity gravityOptions
|
Gravity gravityOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type paddingOptions struct {
|
||||||
|
Enabled bool
|
||||||
|
Top int
|
||||||
|
Right int
|
||||||
|
Bottom int
|
||||||
|
Left int
|
||||||
|
}
|
||||||
|
|
||||||
type trimOptions struct {
|
type trimOptions struct {
|
||||||
Enabled bool
|
Enabled bool
|
||||||
Threshold float64
|
Threshold float64
|
||||||
@@ -126,6 +134,7 @@ type processingOptions struct {
|
|||||||
Enlarge bool
|
Enlarge bool
|
||||||
Extend extendOptions
|
Extend extendOptions
|
||||||
Crop cropOptions
|
Crop cropOptions
|
||||||
|
Padding paddingOptions
|
||||||
Trim trimOptions
|
Trim trimOptions
|
||||||
Format imageType
|
Format imageType
|
||||||
Quality int
|
Quality int
|
||||||
@@ -208,6 +217,7 @@ func newProcessingOptions() *processingOptions {
|
|||||||
Gravity: gravityOptions{Type: gravityCenter},
|
Gravity: gravityOptions{Type: gravityCenter},
|
||||||
Enlarge: false,
|
Enlarge: false,
|
||||||
Extend: extendOptions{Enabled: false, Gravity: gravityOptions{Type: gravityCenter}},
|
Extend: extendOptions{Enabled: false, Gravity: gravityOptions{Type: gravityCenter}},
|
||||||
|
Padding: paddingOptions{Enabled: false},
|
||||||
Trim: trimOptions{Enabled: false, Threshold: 10, Smart: true},
|
Trim: trimOptions{Enabled: false, Threshold: 10, Smart: true},
|
||||||
Quality: conf.Quality,
|
Quality: conf.Quality,
|
||||||
MaxBytes: 0,
|
MaxBytes: 0,
|
||||||
@@ -556,6 +566,50 @@ func applyCropOption(po *processingOptions, args []string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func applyPaddingOption(po *processingOptions, args []string) error {
|
||||||
|
nArgs := len(args)
|
||||||
|
|
||||||
|
if nArgs < 1 || nArgs > 4 {
|
||||||
|
return fmt.Errorf("Invalid padding arguments: %v", args)
|
||||||
|
}
|
||||||
|
|
||||||
|
po.Padding.Enabled = true
|
||||||
|
|
||||||
|
if nArgs > 0 && len(args[0]) > 0 {
|
||||||
|
if err := parseDimension(&po.Padding.Top, "padding top (+all)", args[0]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
po.Padding.Right = po.Padding.Top
|
||||||
|
po.Padding.Bottom = po.Padding.Top
|
||||||
|
po.Padding.Left = po.Padding.Top
|
||||||
|
}
|
||||||
|
|
||||||
|
if nArgs > 1 && len(args[1]) > 0 {
|
||||||
|
if err := parseDimension(&po.Padding.Right, "padding right (+left)", args[1]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
po.Padding.Left = po.Padding.Right
|
||||||
|
}
|
||||||
|
|
||||||
|
if nArgs > 2 && len(args[2]) > 0 {
|
||||||
|
if err := parseDimension(&po.Padding.Bottom, "padding bottom", args[2]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if nArgs > 3 && len(args[3]) > 0 {
|
||||||
|
if err := parseDimension(&po.Padding.Left, "padding left", args[3]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if po.Padding.Top == 0 && po.Padding.Right == 0 && po.Padding.Bottom == 0 && po.Padding.Left == 0 {
|
||||||
|
po.Padding.Enabled = false
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func applyTrimOption(po *processingOptions, args []string) error {
|
func applyTrimOption(po *processingOptions, args []string) error {
|
||||||
nArgs := len(args)
|
nArgs := len(args)
|
||||||
|
|
||||||
@@ -820,6 +874,8 @@ func applyProcessingOption(po *processingOptions, name string, args []string) er
|
|||||||
return applyCropOption(po, args)
|
return applyCropOption(po, args)
|
||||||
case "trim", "t":
|
case "trim", "t":
|
||||||
return applyTrimOption(po, args)
|
return applyTrimOption(po, args)
|
||||||
|
case "padding", "pd":
|
||||||
|
return applyPaddingOption(po, args)
|
||||||
case "quality", "q":
|
case "quality", "q":
|
||||||
return applyQualityOption(po, args)
|
return applyQualityOption(po, args)
|
||||||
case "max_bytes", "mb":
|
case "max_bytes", "mb":
|
||||||
|
|||||||
Reference in New Issue
Block a user