mirror of
https://github.com/imgproxy/imgproxy.git
synced 2025-01-18 11:12:10 +02:00
Watermark scale
This commit is contained in:
parent
fe4810609a
commit
c049fb8a28
@ -162,8 +162,8 @@ Default: disabled
|
|||||||
##### Watermark
|
##### Watermark
|
||||||
|
|
||||||
```
|
```
|
||||||
watermark:%opacity:%position:%x_offset:%y_offset
|
watermark:%opacity:%position:%x_offset:%y_offset:%scale
|
||||||
wm:%opacity:%position:%x_offset:%y_offset
|
wm:%opacity:%position:%x_offset:%y_offset:%scale
|
||||||
```
|
```
|
||||||
|
|
||||||
Puts watermark on the processed image.
|
Puts watermark on the processed image.
|
||||||
@ -180,7 +180,8 @@ Puts watermark on the processed image.
|
|||||||
* `soea`: south-east (bottom-right corner);
|
* `soea`: south-east (bottom-right corner);
|
||||||
* `sowe`: south-west (bottom-left corner);
|
* `sowe`: south-west (bottom-left corner);
|
||||||
* `re`: replicate watermark to fill the whole image;
|
* `re`: replicate watermark to fill the whole image;
|
||||||
* `x_offset`, `y_offset` - (optional) specify watermark offset by X and Y axes. Not applicable to `re` position.
|
* `x_offset`, `y_offset` - (optional) specify watermark offset by X and Y axes. Not applicable to `re` position;
|
||||||
|
* `scale` - (optional) floating point number that defines watermark size relative to the resulting image size. When set to `0` or omitted, watermark size won't be changed.
|
||||||
|
|
||||||
Default: disabled
|
Default: disabled
|
||||||
|
|
||||||
|
@ -17,8 +17,8 @@ You can also specify the base opacity of watermark with `IMGPROXY_WATERMARK_OPAC
|
|||||||
Watermarks are only available with [advanced URL format](generating_the_url_advanced.md). Use `watermark` processing option to put the watermark on the processed image:
|
Watermarks are only available with [advanced URL format](generating_the_url_advanced.md). Use `watermark` processing option to put the watermark on the processed image:
|
||||||
|
|
||||||
```
|
```
|
||||||
watermark:%opacity:%position:%x_offset:%y_offset
|
watermark:%opacity:%position:%x_offset:%y_offset:%scale
|
||||||
wm:%opacity:%position:%x_offset:%y_offset
|
wm:%opacity:%position:%x_offset:%y_offset:%scale
|
||||||
```
|
```
|
||||||
|
|
||||||
Where arguments are:
|
Where arguments are:
|
||||||
@ -35,4 +35,5 @@ Where arguments are:
|
|||||||
* `soea`: south-east (bottom-right corner);
|
* `soea`: south-east (bottom-right corner);
|
||||||
* `sowe`: south-west (bottom-left corner);
|
* `sowe`: south-west (bottom-left corner);
|
||||||
* `re`: replicate watermark to fill the whole image;
|
* `re`: replicate watermark to fill the whole image;
|
||||||
* `x_offset`, `y_offset` - (optional) specify watermark offset by X and Y axes. Not applicable to `re` position.
|
* `x_offset`, `y_offset` - (optional) specify watermark offset by X and Y axes. Not applicable to `re` position;
|
||||||
|
* `scale` - (optional) floating point number that defines watermark size relative to the resulting image size. When set to `0` or omitted, watermark size won't be changed.
|
||||||
|
69
process.go
69
process.go
@ -635,26 +635,25 @@ func vipsImageCopyMemory(img **C.struct__VipsImage) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func vipsReplicateWatermark(width, height C.int) (wm *C.struct__VipsImage, err error) {
|
func vipsReplicate(img **C.struct__VipsImage, width, height C.int) error {
|
||||||
var tmp *C.struct__VipsImage
|
var tmp *C.struct__VipsImage
|
||||||
defer C.clear_image(&tmp)
|
|
||||||
|
|
||||||
if C.vips_replicate_go(watermark, &tmp, 1+width/watermark.Xsize, 1+height/watermark.Ysize) != 0 {
|
if C.vips_replicate_go(*img, &tmp, 1+width/(*img).Xsize, 1+height/(*img).Ysize) != 0 {
|
||||||
err = vipsError()
|
return vipsError()
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
C.swap_and_clear(img, tmp)
|
||||||
|
|
||||||
if C.vips_extract_area_go(tmp, &wm, 0, 0, width, height) != 0 {
|
if C.vips_extract_area_go(*img, &tmp, 0, 0, width, height) != 0 {
|
||||||
err = vipsError()
|
return vipsError()
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
C.swap_and_clear(img, tmp)
|
||||||
|
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func vipsEmbedWatermark(gravity gravityType, width, height C.int, offX, offY C.int) (wm *C.struct__VipsImage, err error) {
|
func vipsEmbed(img **C.struct__VipsImage, gravity gravityType, width, height C.int, offX, offY C.int) error {
|
||||||
wmWidth := watermark.Xsize
|
wmWidth := (*img).Xsize
|
||||||
wmHeight := watermark.Ysize
|
wmHeight := (*img).Ysize
|
||||||
|
|
||||||
left := (width-wmWidth+1)/2 + offX
|
left := (width-wmWidth+1)/2 + offX
|
||||||
top := (height-wmHeight+1)/2 + offY
|
top := (height-wmHeight+1)/2 + offY
|
||||||
@ -687,9 +686,34 @@ func vipsEmbedWatermark(gravity gravityType, width, height C.int, offX, offY C.i
|
|||||||
top = 0
|
top = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
if C.vips_embed_go(watermark, &wm, left, top, width, height) != 0 {
|
var tmp *C.struct__VipsImage
|
||||||
|
if C.vips_embed_go(*img, &tmp, left, top, width, height) != 0 {
|
||||||
|
return vipsError()
|
||||||
|
}
|
||||||
|
C.swap_and_clear(img, tmp)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func vipsResizeWatermark(width, height int) (wm *C.struct__VipsImage, err error) {
|
||||||
|
wmW := float64(watermark.Xsize)
|
||||||
|
wmH := float64(watermark.Ysize)
|
||||||
|
|
||||||
|
wr := float64(width) / wmW
|
||||||
|
hr := float64(height) / wmH
|
||||||
|
|
||||||
|
scale := math.Min(wr, hr)
|
||||||
|
|
||||||
|
if wmW*scale < 1 {
|
||||||
|
scale = 1 / wmW
|
||||||
|
}
|
||||||
|
|
||||||
|
if wmH*scale < 1 {
|
||||||
|
scale = 1 / wmH
|
||||||
|
}
|
||||||
|
|
||||||
|
if C.vips_resize_go(watermark, &wm, C.double(scale)) != 0 {
|
||||||
err = vipsError()
|
err = vipsError()
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
@ -709,12 +733,25 @@ func vipsApplyWatermark(img **C.struct__VipsImage, opts *watermarkOptions) error
|
|||||||
imgW := (*img).Xsize
|
imgW := (*img).Xsize
|
||||||
imgH := (*img).Ysize
|
imgH := (*img).Ysize
|
||||||
|
|
||||||
|
if opts.Scale == 0 {
|
||||||
|
if wm = C.vips_image_copy_memory(watermark); wm == nil {
|
||||||
|
return vipsError()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
wmW := maxInt(int(float64(imgW)*opts.Scale), 1)
|
||||||
|
wmH := maxInt(int(float64(imgH)*opts.Scale), 1)
|
||||||
|
|
||||||
|
if wm, err = vipsResizeWatermark(wmW, wmH); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if opts.Replicate {
|
if opts.Replicate {
|
||||||
if wm, err = vipsReplicateWatermark(imgW, imgH); err != nil {
|
if err = vipsReplicate(&wm, imgW, imgH); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if wm, err = vipsEmbedWatermark(opts.Gravity, imgW, imgH, C.int(opts.OffsetX), C.int(opts.OffsetY)); err != nil {
|
if err = vipsEmbed(&wm, opts.Gravity, imgW, imgH, C.int(opts.OffsetX), C.int(opts.OffsetY)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,6 +103,7 @@ type watermarkOptions struct {
|
|||||||
Gravity gravityType
|
Gravity gravityType
|
||||||
OffsetX int
|
OffsetX int
|
||||||
OffsetY int
|
OffsetY int
|
||||||
|
Scale float64
|
||||||
}
|
}
|
||||||
|
|
||||||
type processingOptions struct {
|
type processingOptions struct {
|
||||||
@ -431,6 +432,10 @@ func applyPresetOption(po *processingOptions, args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func applyWatermarkOption(po *processingOptions, args []string) error {
|
func applyWatermarkOption(po *processingOptions, args []string) error {
|
||||||
|
if len(args) > 7 {
|
||||||
|
return fmt.Errorf("Invalid watermark arguments: %v", args)
|
||||||
|
}
|
||||||
|
|
||||||
if o, err := strconv.ParseFloat(args[0], 64); err == nil && o >= 0 && o <= 1 {
|
if o, err := strconv.ParseFloat(args[0], 64); err == nil && o >= 0 && o <= 1 {
|
||||||
po.Watermark.Enabled = o > 0
|
po.Watermark.Enabled = o > 0
|
||||||
po.Watermark.Opacity = o
|
po.Watermark.Opacity = o
|
||||||
@ -438,7 +443,7 @@ func applyWatermarkOption(po *processingOptions, args []string) error {
|
|||||||
return fmt.Errorf("Invalid watermark opacity: %s", args[0])
|
return fmt.Errorf("Invalid watermark opacity: %s", args[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(args) > 1 {
|
if len(args) > 1 && len(args[1]) > 0 {
|
||||||
if args[1] == "re" {
|
if args[1] == "re" {
|
||||||
po.Watermark.Replicate = true
|
po.Watermark.Replicate = true
|
||||||
} else if g, ok := gravityTypes[args[1]]; ok && g != gravityFocusPoint && g != gravitySmart {
|
} else if g, ok := gravityTypes[args[1]]; ok && g != gravityFocusPoint && g != gravitySmart {
|
||||||
@ -448,7 +453,7 @@ func applyWatermarkOption(po *processingOptions, args []string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(args) > 2 {
|
if len(args) > 2 && len(args[2]) > 0 {
|
||||||
if x, err := strconv.Atoi(args[2]); err == nil {
|
if x, err := strconv.Atoi(args[2]); err == nil {
|
||||||
po.Watermark.OffsetX = x
|
po.Watermark.OffsetX = x
|
||||||
} else {
|
} else {
|
||||||
@ -456,7 +461,7 @@ func applyWatermarkOption(po *processingOptions, args []string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(args) > 3 {
|
if len(args) > 3 && len(args[3]) > 0 {
|
||||||
if y, err := strconv.Atoi(args[3]); err == nil {
|
if y, err := strconv.Atoi(args[3]); err == nil {
|
||||||
po.Watermark.OffsetY = y
|
po.Watermark.OffsetY = y
|
||||||
} else {
|
} else {
|
||||||
@ -464,6 +469,14 @@ func applyWatermarkOption(po *processingOptions, args []string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(args) > 4 && len(args[4]) > 0 {
|
||||||
|
if s, err := strconv.ParseFloat(args[4], 64); err == nil && s >= 0 {
|
||||||
|
po.Watermark.Scale = s
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("Invalid watermark scale: %s", args[4])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user