go gui 序列帧图片合成
合图的工具是早些时候写的,当时是为了做传奇类游戏素材打包用的,把多张图片合成,并输出plist,其实就是做序列帧动画的,今天把这个核心的代码分享下。
工具简介
刚开始做的时候是一个nogui,命令行处理的,把要合成的目录,输出目录填进去就就可以合成,在后来用go-walk做了个gui,大概就是下面这样子,
合图思路
外观地址就是要合成的图片的目录,或者可以用拖拽把其中一张素材拖进去,就可以识别目录。
1,定义一个 10000*10000的画布
newImg := image.NewNRGBA(image.Rect(0, 0, 10000, 10000)) //创建一个新RGBA图像
2,根据图片的数量,尽量是布局成类似9宫格那样子,横竖图片数量一样,计算下x,y 方向的最大值
func getMaxCountXY(sum int) (int, int) {
f := float64(sum)
ff := math.Sqrt(f)
x := int(math.Round(ff))
y := int(ff + 1)
return x, y
}
3,把图片依次绘制到画布上,记录每一张图片的Plist信息
for i := 0; i < my; i++ {
temp_arr := make([]entity.ImgBean, mx)
if i == my-1 { //最后一行
temp_arr = img_array[0:]
} else {
temp_arr = img_array[0:mx] //每行的图片数量
img_array = img_array[mx:]
}
temp_h := 0
temp_w := 0
for k, v := range temp_arr {
v.X = temp_w * 1 //x便宜
v.Y = line_max_height * 1 //y 偏移
//拼图
draw.Draw(newImg, newImg.Bounds(), v.Img, image.Pt(v.X*-1, v.Y*-1), draw.Over)
p := &entity.Plist{v.FileName, v.X, v.Y, v.Img.Bounds().Max.X, v.Img.Bounds().Max.Y, 0, 0}
ps[i*mx+k] = p
//计算本行的最大高度
if v.Img.Bounds().Max.Y > temp_h {
temp_h = v.Img.Bounds().Max.Y
}
temp_w += v.Img.Bounds().Max.X //累计行宽
}
if temp_w > max_x { //计算最大宽度
max_x = temp_w
}
line_max_height += temp_h
}
4,最后输出图片
png.Encode(outFile, newImg.SubImage(image.Rect(0, 0, max_x, line_max_height)))
完整合图代码
func Marge_res_any(p_dir string, p_out string) []*entity.Plist {
log.Println("out file :" + p_out)
//读文件列表
fs, _ := ioutil.ReadDir(p_dir)
mx, my := getMaxCountXY(len(fs))
//图的集合
img_array := make([]entity.ImgBean, 0)
//判断输出文件是否存在
outFile, _ := os.Create(p_out)
defer outFile.Close()
//填文件,计算目标图片位置
for i, f := range fs {
if f.IsDir() {
continue
}
b := entity.ImgBean{}
b.FileName = f.Name()
b.Img = getImg(p_dir + "/" + f.Name())
b.X = i % mx
b.Y = i / mx
img_array = append(img_array, b)
//img_array[i]=b
}
ps := make([]*entity.Plist, len(img_array))
line_max_height := 0
max_x := 0
newImg := image.NewNRGBA(image.Rect(0, 0, 10000, 10000)) //创建一个新RGBA图像
for i := 0; i < my; i++ {
temp_arr := make([]entity.ImgBean, mx)
if i == my-1 { //最后一行
temp_arr = img_array[0:]
} else {
temp_arr = img_array[0:mx] //每行的图片数量
img_array = img_array[mx:]
}
temp_h := 0
temp_w := 0
for k, v := range temp_arr {
v.X = temp_w * 1 //x 偏移
v.Y = line_max_height * 1 //y 偏移
//拼图
draw.Draw(newImg, newImg.Bounds(), v.Img, image.Pt(v.X*-1, v.Y*-1), draw.Over)
p := &entity.Plist{v.FileName, v.X, v.Y, v.Img.Bounds().Max.X, v.Img.Bounds().Max.Y, 0, 0}
ps[i*mx+k] = p
//计算本行的最大高度
if v.Img.Bounds().Max.Y > temp_h {
temp_h = v.Img.Bounds().Max.Y
}
temp_w += v.Img.Bounds().Max.X //累计行宽
}
if temp_w > max_x { //计算最大宽度
max_x = temp_w
}
line_max_height += temp_h
}
//fmt.Println(max_x,line_max_height)
png.Encode(outFile, newImg.SubImage(image.Rect(0, 0, max_x, line_max_height)))
//fmt.Println("OK")
return ps
}