Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Watermark with "fogleman/gg" #183

Open
WillianBR opened this issue Feb 11, 2023 · 4 comments
Open

Watermark with "fogleman/gg" #183

WillianBR opened this issue Feb 11, 2023 · 4 comments

Comments

@WillianBR
Copy link

Watermark with "fogleman/gg"

I stumbled into "fogleman/gg" yesterday and immediately seen it as a nice way to add watermark into my images. But I couldn't make ir work.

I started using "fogleman/gg/blob/master/examples/rotated-text.go" as boilerplate, but it seeans the dc.Rotate() do it with all the canvas and I couldn't center the text!

If course the idea is draw a diagonal text over the hypotenuse of the canvas. Exactly into the center.

When I draw the texto with 0 degrees rotarion it is on center. But if I only rotate 45 degrees, it's a mess.

Does anybody can help with that?

The intended steps are:

  1. Get the image bounds and compute hypotenuse, and fit the most large text possible without get clipped out of canvas;

  2. Create a canvas with transparent backgroud and draw the rotate (45º) text;

  3. Save the new picture with a another name;

The step 2 is the tricky one at the moment!

@fogleman ?

Canvas rotated at 45 degress:

rotated-text 45-degrees

Canvas at 0 degress:

rotated-text 0-degrees

Draft souce code:

//	https://github.com/fogleman/gg/blob/master/examples/rotated-text.go
//	go build -v -ldflags "-s -w" -o rotated-text.exe rotated-text.go
//	
package main

import (
	"flag"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"

	//
	// External packages:
	//
	"github.com/fogleman/gg"
	"github.com/golang/freetype/truetype"
	"golang.org/x/image/font/gofont/goregular"
)


// Execute a external process and return the process object, error object and full executable path
func Start(args ...string) (p *os.Process, err error, executable string) {
	if args[0], err = exec.LookPath(args[0]); err == nil {
		var procAttr os.ProcAttr
		procAttr.Files = []*os.File{os.Stdin,
			os.Stdout, os.Stderr}
		p, err := os.StartProcess(args[0], args, &procAttr)
		if err == nil {
			return p, nil, args[0]
		}
	}
	return nil, err, args[0]
}

func main() {

	xPtr := flag.Int("x", -150, "Valor de X")
	yPtr := flag.Int("y", 160, "Valor de Y")
	rotatePtr := flag.Int("rotate", -45, "Angulo de rotação em graus")
	fontSizePtr := flag.Int("fontSize", 32, "Tamanho da fonte")
	sizePtr := flag.Int("size", 500, "Tamanho do Canvas (size x size)")
	txtPtr := flag.String("text", "Willian & Simone", "Texto para imprimir")
	viewerPtr := flag.String("viewer", "mspaint.exe", "Visualizador de imagem.")
	imageFilePtr := flag.String("file", "rotated-text.go.png", "Arquivo para salvar a imagem")
	bWaitViewer := flag.Bool("WaitViewer", false, "Wait the viewer to finish")
	flag.Parse()

	var S = *sizePtr
	dc := gg.NewContext(S, S)
	dc.SetRGB(1, 1, 1)
	dc.Clear()
	dc.SetRGB(0, 0, 0)
	font, err := truetype.Parse(goregular.TTF)
	if err != nil {
		panic("truetype.Parse()")
	}
	face := truetype.NewFace(font, &truetype.Options{
		Size: float64(*fontSizePtr),
	})
	dc.SetFontFace(face)

	dc.Rotate(gg.Radians(float64(*rotatePtr))) // Left to Right and Up

	var tx, ty float64
	tx, ty = float64(*xPtr), float64(*yPtr)
	text := *txtPtr
	w, h := dc.MeasureString(text)
	fmt.Printf("DEBUG> Text width is %v and height is %v.\n", w, h)

	dc.DrawRectangle(0, 0, float64(S), float64(S))

	dc.SetRGB(0, 0, 0)
	dc.DrawRectangle(tx, ty, w, h)
	dc.Stroke()
	dc.DrawString(text, tx, ty-4+h)

	dc.SavePNG(*imageFilePtr)

	if len(*viewerPtr) > 0 {
		process, err, executable := Start(*viewerPtr, *imageFilePtr)
		if err != nil {
			fmt.Printf("ERROR Unable to run \"%s %s\": %s\n", *viewerPtr, *imageFilePtr, err.Error())
		} else {
			imageFullPath, _ := filepath.Abs(*imageFilePtr)
			fmt.Printf("Running as pid %d with \"%s %s\"\n", process.Pid, executable, imageFullPath)
			if *bWaitViewer {
				process.Wait()
			}
		}
	}
}

/*
rotated-text.exe -rotate 0 -text "Willian & Simone" -size 500 -x 126 -y 234
	Text width is 247 and height is 32.
	x = 500 - 247 / 2
	y = 500 -  32 / 2

rotated-text.exe -rotate -45 -text "Willian & Simone" -size 500 -x 126 -y 234
*/
@splace
Copy link

splace commented Feb 20, 2023

you need to translate to the centre of the rotation

(below works, i think, but has changes other than just bug fix.)

package main

import (
	"flag"
	//"fmt"
	"github.com/fogleman/gg"
	"github.com/golang/freetype/truetype"
	"golang.org/x/image/font/gofont/goregular"
)


func main() {

	xPtr := flag.Int("x", 250, "Valor de X")
	yPtr := flag.Int("y", 250, "Valor de Y")
	rotatePtr := flag.Int("rotate", -45, "Angulo de rotação em graus")
	fontSizePtr := flag.Int("fontSize", 32, "Tamanho da fonte")
	sizePtr := flag.Int("size", 500, "Tamanho do Canvas (size x size)")
	txtPtr := flag.String("text", "Willian & Simone", "Texto para imprimir")
	imageFilePtr := flag.String("file", "rotated-text.go.png", "Arquivo para salvar a imagem")
	flag.Parse()

	dc := gg.NewContext(*sizePtr, *sizePtr)
	dc.SetRGB(1, 1, 1)
	dc.Clear()

	font, err := truetype.Parse(goregular.TTF)
	if err != nil {
		panic("truetype.Parse()")
	}
	face := truetype.NewFace(font, &truetype.Options{
		Size: float64(*fontSizePtr),
	})
	dc.SetFontFace(face)

	dc.SetRGB(0, 0, 0)
       // border inset 10px
	dc.DrawRectangle(10, 10, float64(*sizePtr)-20, float64(*sizePtr)-20)
	dc.Stroke()
	dc.Translate(float64(*xPtr), float64(*yPtr))
	dc.Rotate(gg.Radians(float64(*rotatePtr))) // Left to Right and Up
        // does its own centring 
	dc.DrawStringAnchored(*txtPtr, 0, 0,.5,.5)

	w, h := dc.MeasureString(*txtPtr)
       // added border
	dc.DrawRectangle(-w/2-10,-h/2, w+20, h+10)
	dc.Stroke()

	dc.SavePNG(*imageFilePtr)

}

@splace
Copy link

splace commented Feb 20, 2023

also use alpha color...
dc.SetRGBA(1, 1, 1,100)
... for a transparent watermark

@WillianBR
Copy link
Author

I'll check it later, after I get home!

Thank you!

@WillianBR
Copy link
Author

Hi @splace,

I tested it and work!

I looks like a missed the detail in the documentation about the function DrawStringAnchored().

I started some test and now I'll look for a function group to save the canvas status (colors, etc.) and restore it after.

And ofcourse, add the code to read a existing image and apply the watermark at it center without compromised the original image & text.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants