当前位置:网站首页>Golang多图生成gif
Golang多图生成gif
2022-07-01 02:57:00 【Asimov__】
package image
import (
"fmt"
"github.com/golang/freetype"
"golang.org/x/image/font"
"image"
"image/color"
"image/color/palette"
"image/draw"
"image/gif"
"image/png"
"io/ioutil"
"log"
"os"
"sync"
"testing"
"time"
)
func isInPalette(p color.Palette, c color.Color) int {
ret := -1
for i, v := range p {
if v == c {
return i
}
}
return ret
}
// 获取每张图片的调色板
func getPalette(m image.Image) color.Palette {
p := color.Palette{color.RGBA{0x00, 0x00, 0x00, 0x00}}
p9 := color.Palette(palette.Plan9)
b := m.Bounds()
black := false
for y := b.Min.Y; y < b.Max.Y; y++ {
for x := b.Min.X; x < b.Max.X; x++ {
// At返回像素At (x, y)的颜色。
c := m.At(x, y)
// Convert返回欧氏R,G,B空间中最接近c的调色板颜色。
cc := p9.Convert(c)
if cc == p9[0] {
black = true
}
if isInPalette(p, cc) == -1 {
p = append(p, cc)
}
}
}
if len(p) < 256 && black == true {
p[0] = color.RGBA{0x00, 0x00, 0x00, 0x00} // transparent
p = append(p, p9[0])
}
return p
}
// pool
type WaitGroup struct {
workChan chan int
wg sync.WaitGroup
}
func NewPool(coreNum int) *WaitGroup {
ch := make(chan int, coreNum)
return &WaitGroup{
workChan: ch,
wg: sync.WaitGroup{},
}
}
func (ap *WaitGroup) Add(num int) {
for i := 0; i < num; i++ {
ap.workChan <- i
ap.wg.Add(1)
}
}
func (ap *WaitGroup) Done() {
LOOP:
for {
select {
case <-ap.workChan:
break LOOP
}
}
ap.wg.Done()
}
func (ap *WaitGroup) Wait() {
ap.wg.Wait()
}
// 写入
func writeLabel(img image.Image, label string, x, y int, fontColor color.Color, size float64, fontPath string) (image.Image, error) {
bound := img.Bounds()
// 创建一个新的图片
rgba := image.NewRGBA(image.Rect(0, 0, bound.Dx(), bound.Dy()))
// 读取字体
fontBytes, err := ioutil.ReadFile(fontPath)
if err != nil {
return rgba, err
}
myFont, err := freetype.ParseFont(fontBytes)
if err != nil {
return rgba, err
}
draw.Draw(rgba, rgba.Bounds(), img, bound.Min, draw.Src)
c := freetype.NewContext()
c.SetDPI(72)
c.SetFont(myFont)
c.SetFontSize(size)
c.SetClip(rgba.Bounds())
c.SetDst(rgba)
uni := image.NewUniform(fontColor)
c.SetSrc(uni)
c.SetHinting(font.HintingNone)
// 在指定的位置显示
pt := freetype.Pt(x, y+int(c.PointToFixed(size)>>6))
if _, err := c.DrawString(label, pt); err != nil {
return rgba, err
}
return rgba, nil
}
func TestGif(t *testing.T) {
var disposals []byte
var images []*image.Paletted
var delays []int
work := NewPool(100)
for i := 1; i < 501; i++ {
work.Add(1)
go func(i interface{}, wg *WaitGroup) {
defer wg.Done()
var src string
src = fmt.Sprintf("./PNGS/图层 %d.png", i)
file, err := os.Open(src)
if err != nil {
fmt.Println(err)
}
defer func() { _ = file.Close() }()
g, err := png.Decode(file)
// 写入文字
writeimage, err := writeLabel(g, "NO.9988", 56, 56, color.RGBA{234, 178, 16, 255}, 60, "./PingFang Heavy.ttf")
if err != nil {
fmt.Println(err)
}
cp := getPalette(writeimage)
// cp := append(palette.WebSafe, color.Transparent)
// 透明图片需要设置
disposals = append(disposals, gif.DisposalBackground)
// 返回一个给定宽度,高度和面板。
p := image.NewPaletted(image.Rect(0, 0, 1200, 1200), cp)
draw.Draw(p, p.Bounds(), writeimage, image.ZP, draw.Src)
images = append(images, p)
delays = append(delays, 4)
//time.Sleep(time.Second * 1)
}(i, work)
}
log.Println("waiting...")
work.Wait()
log.Println("done")
g := &gif.GIF{
Image: images,
Delay: delays,
//LoopCount为0表示永远循环
LoopCount: 0,
//处理是连续的处理方法,每帧一个
Disposal: disposals,
}
f, err := os.Create("test1.gif")
if err != nil {
fmt.Println(err)
}
defer func() { _ = f.Close() }()
gif.EncodeAll(f, g)
}
边栏推荐
- 8 pits of redis distributed lock
- 鼠标悬停效果七
- Huawei operator level router configuration example | configuration static VPLS example
- SSH configuration password free login error: /usr/bin/ssh copy ID: error: no identities found solution
- 几行事务代码,让我赔了16万
- Chapitre 03 Bar _ Gestion des utilisateurs et des droits
- Example of Huawei operator level router configuration | example of configuring optionc mode cross domain LDP VPLS
- 【微信小程序開發】樣式匯總
- 如何校验两个文件内容是否相同
- If I am in Beijing, where is a better place to open an account? In addition, is it safe to open a mobile account?
猜你喜欢
![[applet project development -- JD mall] uni app commodity classification page (Part 2)](/img/f3/752f41f5b5cc16c8a71498ea9cabb5.png)
[applet project development -- JD mall] uni app commodity classification page (Part 2)

Metadata in NFT
![[linear DP] longest common subsequence](/img/47/c3172422e997009facbada929adb1a.jpg)
[linear DP] longest common subsequence

Completely solve the lost connection to MySQL server at 'reading initial communication packet

xxl-job使用指南

lavaweb【初识后续问题的解决】

Cloud native annual technology inventory is released! Ride the wind and waves at the right time

Dell server restart Idrac method

Redis分布式锁的8大坑

Huawei operator level router configuration example | BGP VPLS and LDP VPLS interworking example
随机推荐
产业互联网中,「小」程序有「大」作为
Mouse over effect VI
POI导出excel,按照父子节点进行分级显示
Restcloud ETL data realizes incremental data synchronization through timestamp
安装VCenter6.7【VCSA6.7(vCenter Server Appliance 6.7) 】
mybati sql 语句打印
Poj-3486-computers[dynamic planning]
Multithreaded printing
性能测试常见面试题
Restcloud ETL practice data row column conversion
Mouse over effect V
Huawei operator level router configuration example | configuration static VPLS example
鼠标悬停效果九
The operation efficiency of the park is improved, and the application platform management of applet container technology is accelerated
Best used trust automation script (shell)
STM32——一线协议之DS18B20温度采样
How to open a stock account? Also, is it safe to open an account online?
【EXSI】主机间传输文件
lavaweb【初识后续问题的解决】
Sampling Area Lights