zoukankan      html  css  js  c++  java
  • 关于imagic拼接透明背景图片的问题

    目标:

    为了做图片水印,需要水平拼接多个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用来指定需要去处的背景色,程序会查找相似的颜色,并去掉,然后编程透明。

  • 相关阅读:
    跟我一起来学ORACLE开发系列之三sql语法篇 老猫
    浅谈Oracle DBlink搭建 老猫
    一个合格的Oracle DBA的速成法摘录 老猫
    Oracle数据库设计要做到五戒 老猫
    Oracle分析函数参考手册一 老猫
    Oracle10G常用维护语句 老猫
    数据库设计中的敏捷方法 老猫
    oracle数据字典总结 老猫
    DBA 1.0与DBA眼中的DBA 2.0时代 老猫
    海水的绘制 szlongman
  • 原文地址:https://www.cnblogs.com/zhangqingping/p/5741801.html
Copyright © 2011-2022 走看看