@@ -2,12 +2,37 @@ package main
22
33import (
44 "fmt"
5+ "image"
6+ "image/color"
7+ "image/gif"
8+ "image/jpeg"
59 "image/png"
10+ "log"
11+ "net"
612 "os"
13+ "time"
714
15+ "github.com/disintegration/gift"
816 "github.com/kbinani/screenshot"
17+ "github.com/pwaller/go-hexcolor"
18+ "golang.org/x/image/draw"
19+ "golang.org/x/image/font"
20+ "golang.org/x/image/font/inconsolata"
21+ "golang.org/x/image/math/fixed"
922)
1023
24+ func GetOutboundIP () net.IP {
25+ conn , err := net .Dial ("udp" , "8.8.8.8:80" )
26+ if err != nil {
27+ log .Fatal (err )
28+ }
29+ defer conn .Close ()
30+
31+ localAddr := conn .LocalAddr ().(* net.UDPAddr )
32+
33+ return localAddr .IP
34+ }
35+
1136func main () {
1237 n := screenshot .NumActiveDisplays ()
1338
@@ -18,11 +43,85 @@ func main() {
1843 if err != nil {
1944 panic (err )
2045 }
21- fileName := fmt .Sprintf ("%d_%dx%d.png" , i , bounds .Dx (), bounds .Dy ())
22- file , _ := os .Create (fileName )
46+
47+ rawTime := time .Now ()
48+
49+ myIP := GetOutboundIP ()
50+
51+ curTime := rawTime .Unix ()
52+ timeText := rawTime .Local ()
53+
54+ watermarkText := fmt .Sprintf ("%s - %s" , timeText , myIP .To4 ().String ())
55+ rawFilepath := fmt .Sprintf ("%d_%d_%dx%d.png" , curTime , i , bounds .Dx (), bounds .Dy ())
56+ format := "png"
57+ watermark := createWatermark (watermarkText , 2.0 , parseColor ("#FF0000FF" ))
58+
59+ sourceBounds := img .Bounds ()
60+ watermarkBounds := watermark .Bounds ()
61+ markedImage := image .NewRGBA (sourceBounds )
62+ draw .Draw (markedImage , sourceBounds , img , image .ZP , draw .Src )
63+
64+ var offset image.Point
65+ for offset .X = watermarkBounds .Max .X / - 2 ; offset .X < sourceBounds .Max .X ; offset .X += watermarkBounds .Max .X {
66+ for offset .Y = watermarkBounds .Max .Y / - 2 ; offset .Y < sourceBounds .Max .Y ; offset .Y += watermarkBounds .Max .Y {
67+ draw .Draw (markedImage , watermarkBounds .Add (offset ), watermark , image .ZP , draw .Over )
68+ }
69+ }
70+
71+ file , _ := os .Create (rawFilepath )
2372 defer file .Close ()
24- png .Encode (file , img )
2573
26- fmt .Printf ("#%d : %v \" %s\" \n " , i , bounds , fileName )
74+ switch format {
75+ case "png" :
76+ err = png .Encode (file , markedImage )
77+ case "gif" :
78+ err = gif .Encode (file , markedImage , & gif.Options {NumColors : 265 })
79+ case "jpeg" :
80+ err = jpeg .Encode (file , markedImage , & jpeg.Options {Quality : jpeg .DefaultQuality })
81+ default :
82+ log .Fatalf ("unknown format %s" , format )
83+ }
84+ if err != nil {
85+ log .Fatalf ("unable to encode image: %s" , err )
86+ }
87+
88+ fmt .Printf ("[*] Screenshot Written: %s\n " , rawFilepath )
89+ }
90+ }
91+
92+ func parseColor (str string ) color.Color {
93+ r , g , b , a := hexcolor .HexToRGBA (hexcolor .Hex (str ))
94+ return color.RGBA {
95+ A : a ,
96+ R : r ,
97+ G : g ,
98+ B : b ,
2799 }
28100}
101+
102+ func createWatermark (text string , scale float64 , textColor color.Color ) image.Image {
103+ var padding float64 = 2
104+ w := 8 * (float64 (len (text )) + (padding * 2 ))
105+ h := 16 * padding
106+ img := image .NewRGBA (image .Rect (0 , 0 , int (w ), int (h )))
107+ point := fixed.Point26_6 {fixed .Int26_6 (64 * padding ), fixed .Int26_6 (h * 64 )}
108+
109+ d := & font.Drawer {
110+ Dst : img ,
111+ Src : image .NewUniform (textColor ),
112+ Face : inconsolata .Regular8x16 ,
113+ Dot : point ,
114+ }
115+ d .DrawString (text )
116+
117+ bounds := img .Bounds ()
118+ scaled := image .NewRGBA (image .Rect (0 , 0 , int (float64 (bounds .Max .X )* scale ), int (float64 (bounds .Max .Y )* scale )))
119+ draw .BiLinear .Scale (scaled , scaled .Bounds (), img , bounds , draw .Src , nil )
120+
121+ g := gift .New (
122+ gift .Rotate (45 , color .Transparent , gift .CubicInterpolation ),
123+ )
124+ rot := image .NewNRGBA (g .Bounds (scaled .Bounds ()))
125+ g .Draw (rot , scaled )
126+ return rot
127+ }
0 commit comments