目标:
为了做图片水印,需要水平拼接多个logo和文字。。。
之前用过imagick,所以继续使用。
第一个版本:实现了图片和文字的拼接,代码如下:
package main import ( "fmt" "gopkg.in/gographics/imagick.v2/imagick" ) func draw_setfont(mw *imagick.MagickWand, dw *imagick.DrawingWand, font string, size float64, colour string, sx *float64) { sflag := false if len(font) > 0 { dw.SetFont(font) sflag = true } if len(colour) > 0 { pw := imagick.NewPixelWand() pw.SetColor(colour) dw.SetFillColor(pw) pw.Destroy() sflag = true } if size > 0 { dw.SetFontSize(size) } if sflag { fm := mw.QueryFontMetrics(dw, " ") *sx = fm.TextWidth } } // sx is the width of a space in the current font and fontsize. // If the font or fontsize is changed a new value for the space // width must be obtained before calling this again (by calling draw_setfont) func draw_metrics(mw *imagick.MagickWand, dw *imagick.DrawingWand, dx *float64, dy, sx float64, text string) { mw.AnnotateImage(dw, *dx, dy, 0, text) mw.DrawImage(dw) // get the font metrics fm := mw.QueryFontMetrics(dw, text) if fm != nil { // Adjust the new x coordinate *dx += fm.TextWidth + sx } } func main() { imagick.Initialize() defer imagick.Terminate() mw := imagick.NewMagickWand() ll := imagick.NewMagickWand() nn := imagick.NewMagickWand() bb := imagick.NewMagickWand() fmt.Println("read logo...") ll.ReadImage("../logo3.png") nn.ReadImage("../logo2.png") //加上文字 bb.SetSize(400, 128) bb.ReadImage("xc:none") dw := imagick.NewDrawingWand() var dx, dy, sx float64 dx = 10//set y dw.SetFontSize(32) dw.SetFont("Times-New-Roman") fm := bb.QueryFontMetrics(dw, "M") dy = fm.CharacterHeight + fm.Descender + 50 dw.SetTextEncoding("UTF-8") dw.SetFont("../yahei.ttf") fmt.Println("start draw.......") draw_setfont(bb, dw, "", 32, "#40FF80", &sx) fmt.Println("curr:", sx, "dy:", dy) draw_metrics(bb, dw, &dx, dy, sx, "like......你好。。。") bb.DrawImage(dw) bb.WriteImage("font.png") mw.AddImage(ll) mw.AddImage(nn) mw.AddImage(bb) total := mw.MontageImage(ndw, "3x1", "", 0, "0") total.WriteImage("append.png") }
实现效果:图片和文字,都已经拼接到一行,拼接方式由 MontageImage 第二个参数决定(Nx1,表示都在一行。。。)
但是有个问题,原先透明的logo图片,拼接到一起,居然没有透明效果了。。。。。
各种查资料,然后第二版来了
package main import ( "fmt" "gopkg.in/gographics/imagick.v2/imagick" ) func draw_setfont(mw *imagick.MagickWand, dw *imagick.DrawingWand, font string, size float64, colour string, sx *float64) { sflag := false if len(font) > 0 { dw.SetFont(font) sflag = true } if len(colour) > 0 { pw := imagick.NewPixelWand() pw.SetColor(colour) dw.SetFillColor(pw) pw.Destroy() sflag = true } if size > 0 { dw.SetFontSize(size) } if sflag { fm := mw.QueryFontMetrics(dw, " ") *sx = fm.TextWidth } } // sx is the width of a space in the current font and fontsize. // If the font or fontsize is changed a new value for the space // width must be obtained before calling this again (by calling draw_setfont) func draw_metrics(mw *imagick.MagickWand, dw *imagick.DrawingWand, dx *float64, dy, sx float64, text string) { mw.AnnotateImage(dw, *dx, dy, 0, text) mw.DrawImage(dw) // get the font metrics fm := mw.QueryFontMetrics(dw, text) if fm != nil { // Adjust the new x coordinate *dx += fm.TextWidth + sx } } func main() { imagick.Initialize() defer imagick.Terminate() mw := imagick.NewMagickWand() ll := imagick.NewMagickWand() nn := imagick.NewMagickWand() bb := imagick.NewMagickWand() fmt.Println("read logo...") ll.ReadImage("../logo3.png") nn.ReadImage("../logo2.png") //加上文字 bb.SetSize(400, 128) bb.ReadImage("xc:none") dw := imagick.NewDrawingWand() var dx, dy, sx float64 dx = 10 //set y dw.SetFontSize(32) dw.SetFont("Times-New-Roman") fm := bb.QueryFontMetrics(dw, "M") dy = fm.CharacterHeight + fm.Descender + 50 dw.SetTextEncoding("UTF-8") dw.SetFont("../yahei.ttf") fmt.Println("start draw.......") draw_setfont(bb, dw, "", 32, "#40FF80", &sx) fmt.Println("curr:", sx, "dy:", dy) draw_metrics(bb, dw, &dx, dy, sx, "like......你好。。。") bb.DrawImage(dw) mw.AddImage(ll) mw.AddImage(nn) mw.AddImage(bb) mw.ResetIterator() append_img := mw.AppendImages(false) append_img.WriteImage("append.png") }
标红的两行代码是关键,如果不调用 ResetIterator,则拼接的终效果是最后一张图片,这里是让迭代器指向第一张图片,重新开始。
AppendImages的参数,true或者false表示上下排列(true),还是水平排列(false)。
OK,到这里,就可以完成目标了。
不得不说,imagick很强大,但是API研究起来还是很头疼呀。
另外,如果你想把一张有背景的图片的 背景去掉,变成透明,那么可以用下面的方法。
// Port of http://members.shaw.ca/el.supremo/MagickWand/trans_paint.htm to Go package main import "gopkg.in/gographics/imagick.v2/imagick" func main() { imagick.Initialize() defer imagick.Terminate() mw := imagick.NewMagickWand() mw.ReadImage("logo:") // A larger fuzz value allows more colours "near" white to be // modified. A fuzz of zero only allows an exact match with the // given colour // Set up the pixelwand containing the colour to be "targeted" // by transparency target := imagick.NewPixelWand() target.SetColor("white") // Change the transparency of all colours which match target (with // fuzz applied). In this case they are made completely transparent (0) // but you can set this to any value from 0 to 1. mw.TransparentPaintImage(target, 0, 10, false) mw.WriteImage("logo_white.png") }
但是这个方法也不是万能的,SetColor用来指定需要去处的背景色,程序会查找相似的颜色,并去掉,然后编程透明。