Skip to content

Commit

Permalink
Merge branch 'feature/better-watermarking'
Browse files Browse the repository at this point in the history
  • Loading branch information
DarthSim committed Aug 29, 2019
2 parents e6deed2 + 8cef2ee commit c641e3e
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 153 deletions.
74 changes: 72 additions & 2 deletions process.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,66 @@ func scaleSize(size int, scale float64) int {
return roundToInt(float64(size) * scale)
}

func prepareWatermark(wm *vipsImage, wmData *watermarkData, opts *watermarkOptions, imgWidth, imgHeight int) error {
if err := wm.Load(wmData.data, wmData.imgtype, 1, 1.0, 1); err != nil {
return err
}

po := processingOptions{
Resize: resizeFit,
Dpr: 1,
Enlarge: true,
Format: wmData.imgtype,
}

if opts.Scale > 0 {
po.Width = maxInt(int(float64(imgWidth)*opts.Scale), 1)
po.Height = maxInt(int(float64(imgHeight)*opts.Scale), 1)
}

if err := transformImage(context.Background(), wm, wmData.data, &po, wmData.imgtype); err != nil {
return err
}

if err := wm.EnsureAlpha(); err != nil {
return nil
}

if opts.Replicate {
if err := wm.Replicate(imgWidth, imgHeight); err != nil {
return err
}
} else {
if err := wm.Embed(opts.Gravity, imgWidth, imgHeight, opts.OffsetX, opts.OffsetY, rgbColor{0, 0, 0}); err != nil {
return err
}
}

return wm.CopyMemory()
}

func applyWatermark(img *vipsImage, wmData *watermarkData, opts *watermarkOptions, framesCount int) error {
wm := new(vipsImage)
defer wm.Clear()

width := img.Width()
height := img.Height()

if err := prepareWatermark(wm, wmData, opts, width, height/framesCount); err != nil {
return err
}

if framesCount > 1 {
if err := wm.Replicate(width, height); err != nil {
return err
}
}

opacity := opts.Opacity * conf.WatermarkOpacity

return img.ApplyWatermark(wm, opacity)
}

func transformImage(ctx context.Context, img *vipsImage, data []byte, po *processingOptions, imgtype imageType) error {
var err error

Expand Down Expand Up @@ -380,8 +440,8 @@ func transformImage(ctx context.Context, img *vipsImage, data []byte, po *proces

checkTimeout(ctx)

if po.Watermark.Enabled {
if err = img.ApplyWatermark(&po.Watermark); err != nil {
if po.Watermark.Enabled && watermark != nil {
if err = applyWatermark(img, watermark, &po.Watermark, 1); err != nil {
return err
}
}
Expand Down Expand Up @@ -446,6 +506,10 @@ func transformAnimated(ctx context.Context, img *vipsImage, data []byte, po *pro
}
}()

watermarkEnabled := po.Watermark.Enabled
po.Watermark.Enabled = false
defer func() { po.Watermark.Enabled = watermarkEnabled }()

var errg errgroup.Group

for i := 0; i < framesCount; i++ {
Expand Down Expand Up @@ -477,6 +541,12 @@ func transformAnimated(ctx context.Context, img *vipsImage, data []byte, po *pro
return err
}

if watermarkEnabled && watermark != nil {
if err = applyWatermark(img, watermark, &po.Watermark, framesCount); err != nil {
return err
}
}

img.SetInt("page-height", frames[0].Height())
img.SetInt("gif-delay", delay)
img.SetInt("gif-loop", loop)
Expand Down
43 changes: 0 additions & 43 deletions vips.c
Original file line number Diff line number Diff line change
Expand Up @@ -385,49 +385,6 @@ vips_ensure_alpha(VipsImage *in, VipsImage **out) {
return vips_bandjoin_const1(in, out, 255, NULL);
}

int
vips_apply_opacity(VipsImage *in, VipsImage **out, double opacity){
if (vips_image_hasalpha_go(in)) {
if (opacity < 1) {
VipsImage *img, *img_alpha, *tmp;

if (vips_extract_band(in, &img, 0, "n", in->Bands - 1, NULL))
return 1;

if (vips_extract_band(in, &img_alpha, in->Bands - 1, "n", 1, NULL)) {
clear_image(&img);
return 1;
}

if (vips_linear1(img_alpha, &tmp, opacity, 0, NULL)) {
clear_image(&img);
clear_image(&img_alpha);
return 1;
}
swap_and_clear(&img_alpha, tmp);

if (vips_bandjoin2(img, img_alpha, out, NULL)) {
clear_image(&img);
clear_image(&img_alpha);
return 1;
}

clear_image(&img);
clear_image(&img_alpha);
} else {
if (vips_copy(in, out, NULL)) {
return 1;
}
}
} else {
if (vips_bandjoin_const1(in, out, opacity * 255, NULL)) {
return 1;
}
}

return 0;
}

int
vips_apply_watermark(VipsImage *in, VipsImage *watermark, VipsImage **out, double opacity) {
VipsImage *wm, *wm_alpha, *tmp;
Expand Down
109 changes: 7 additions & 102 deletions vips.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ var (
vipsTypeSupportLoad = make(map[imageType]bool)
vipsTypeSupportSave = make(map[imageType]bool)

watermark *vipsImage
watermark *watermarkData
)

var vipsConf struct {
Expand Down Expand Up @@ -126,18 +126,14 @@ func initVips() {

vipsConf.WatermarkOpacity = C.double(conf.WatermarkOpacity)

if err := vipsPrepareWatermark(); err != nil {
if err := vipsLoadWatermark(); err != nil {
logFatal(err.Error())
}

vipsCollectMetrics()
}

func shutdownVips() {
if watermark != nil {
watermark.Clear()
}

C.vips_shutdown()
}

Expand All @@ -161,61 +157,8 @@ func vipsError() error {
return newUnexpectedError(C.GoString(C.vips_error_buffer()), 1)
}

func vipsPrepareWatermark() error {
data, imgtype, cancel, err := watermarkData()
defer cancel()

if err != nil {
return err
}

if data == nil {
return nil
}

watermark = new(vipsImage)

if err = watermark.Load(data, imgtype, 1, 1.0, 1); err != nil {
return err
}

var tmp *C.VipsImage

if C.vips_apply_opacity(watermark.VipsImage, &tmp, C.double(conf.WatermarkOpacity)) != 0 {
return vipsError()
}
C.swap_and_clear(&watermark.VipsImage, tmp)

if err = watermark.CopyMemory(); err != nil {
return err
}

return nil
}

func vipsResizeWatermark(width, height int) (wm *vipsImage, err error) {
wmW := float64(watermark.VipsImage.Xsize)
wmH := float64(watermark.VipsImage.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
}

wm = new(vipsImage)

if C.vips_resize_with_premultiply(watermark.VipsImage, &wm.VipsImage, C.double(scale)) != 0 {
err = vipsError()
}

func vipsLoadWatermark() (err error) {
watermark, err = getWatermarkData()
return
}

Expand Down Expand Up @@ -632,48 +575,10 @@ func (img *vipsImage) Embed(gravity gravityType, width, height int, offX, offY i
return nil
}

func (img *vipsImage) ApplyWatermark(opts *watermarkOptions) error {
if watermark == nil {
return nil
}

var (
wm *vipsImage
tmp *C.VipsImage
)
defer func() { wm.Clear() }()

var err error

imgW := img.Width()
imgH := img.Height()

if opts.Scale == 0 {
wm = new(vipsImage)

if C.vips_copy_go(watermark.VipsImage, &wm.VipsImage) != 0 {
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 err = wm.Replicate(imgW, imgH); err != nil {
return err
}
} else {
if err = wm.Embed(opts.Gravity, imgW, imgH, opts.OffsetX, opts.OffsetY, rgbColor{0, 0, 0}); err != nil {
return err
}
}
func (img *vipsImage) ApplyWatermark(wm *vipsImage, opacity float64) error {
var tmp *C.VipsImage

if C.vips_apply_watermark(img.VipsImage, wm.VipsImage, &tmp, C.double(opts.Opacity)) != 0 {
if C.vips_apply_watermark(img.VipsImage, wm.VipsImage, &tmp, C.double(opacity)) != 0 {
return vipsError()
}
C.swap_and_clear(&img.VipsImage, tmp)
Expand Down
1 change: 0 additions & 1 deletion vips.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ int vips_replicate_go(VipsImage *in, VipsImage **out, int across, int down);
int vips_embed_go(VipsImage *in, VipsImage **out, int x, int y, int width, int height, double *bg, int bgn);

int vips_ensure_alpha(VipsImage *in, VipsImage **out);
int vips_apply_opacity(VipsImage *in, VipsImage **out, double opacity);

int vips_apply_watermark(VipsImage *in, VipsImage *watermark, VipsImage **out, double opacity);

Expand Down
35 changes: 30 additions & 5 deletions watermark_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,47 @@ import (
"os"
)

func watermarkData() ([]byte, imageType, context.CancelFunc, error) {
type watermarkData struct {
data []byte
imgtype imageType
}

func getWatermarkData() (*watermarkData, error) {
if len(conf.WatermarkData) > 0 {
data, imgtype, err := base64WatermarkData()
return data, imgtype, func() {}, err

if err != nil {
return nil, err
}

return &watermarkData{data, imgtype}, err
}

if len(conf.WatermarkPath) > 0 {
data, imgtype, err := fileWatermarkData()
return data, imgtype, func() {}, err

if err != nil {
return nil, err
}

return &watermarkData{data, imgtype}, err
}

if len(conf.WatermarkURL) > 0 {
return remoteWatermarkData()
b, imgtype, cancel, err := remoteWatermarkData()
defer cancel()

if err != nil {
return nil, err
}

data := make([]byte, len(b))
copy(data, b)

return &watermarkData{data, imgtype}, err
}

return nil, imageTypeUnknown, func() {}, nil
return nil, nil
}

func base64WatermarkData() ([]byte, imageType, error) {
Expand Down

0 comments on commit c641e3e

Please sign in to comment.