1
0
mirror of https://github.com/imgproxy/imgproxy.git synced 2025-01-18 11:12:10 +02:00

Watermark scale

This commit is contained in:
DarthSim 2018-10-28 18:05:57 +06:00
parent fe4810609a
commit c049fb8a28
4 changed files with 77 additions and 25 deletions

View File

@ -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

View File

@ -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.

View File

@ -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
} }
} }

View File

@ -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
} }