zoukankan      html  css  js  c++  java
  • golang 六宫格、九宫格头像生成

    图片示例就不传了,在原WordPress上。

    //Merge6Grid 6宫格
    //rule NO1:至少3张图 最多6张图
    // NO2:第一张大小 60*60 其他大小 28*28 间隔4px 合成图大小102*102
    // NO3:排列顺序 从左至右 从上到小 再 从右到左
    // ++|
    // ++|
    // --|
    func Merge6Grid(src []io.Reader, dst io.Writer) error {
    	defer func() {
    		if r := recover(); r != nil {
    			log.Println("Merge.recover:", r)
    		}
    	}()
    	if len(src) < 3 || len(src) > 6 {
    		panic("the pic num is between 3 and 6")
    	}
    	var err error
    	imagePoints := getXy6Grid(len(src))
    
    	//创建背景大图
    	background := image.NewRGBA(image.Rect(0, 0, 100, 100))
    	//设置背景为灰色
    	for m := 0; m < 100; m++ {
    		for n := 0; n < 100; n++ {
    			//rgba := GetRGBA(0xC8CED4)
    			background.SetRGBA(m, n, color.RGBA{127, 127, 127, 0})
    		}
    	}
    
    	//背景图矩形圆角
    	newBg, err := CreateRoundRectWithRGBA(background, 10)
    	if err != nil {
    		return err
    	}
    
    	//开始合成
    	var width int
    	for i, v := range imagePoints {
    		x := v.x
    		y := v.y
    
    		if i == 0 {
    			width = 60
    		} else {
    			width = 28
    		}
    		fOut := memory.NewWriter()
    
    		//先缩略
    		err = Scale(src[i], fOut, width, width, 100)
    		if err != nil {
    			return err
    		}
    
    		//矩形圆角
    		rgba, err := CreateRoundRectWithoutColor(fOut, 6)
    		if err != nil {
    			return err
    		}
    
    		draw.Draw(newBg, newBg.Bounds(), rgba, rgba.Bounds().Min.Sub(image.Pt(x, y)), draw.Src)
    	}
    
    	return png.Encode(dst, newBg)
    	//return jpeg.Encode(dst, newBg, nil)
    }
    
    //CreateRoundRect 创建圆角矩形 r为输入图像 r为圆角半径 color为圆角颜色
    func CreateRoundRect(rd io.Reader, r int, c *color.RGBA) (*image.RGBA, error) {
    	src, _, err := image.Decode(rd)
    	if err != nil {
    		return nil, err
    	}
    
    	b := src.Bounds()
    	x := b.Dx()
    	y := b.Dy()
    	dst := image.NewRGBA(b)
    	draw.Draw(dst, b, src, src.Bounds().Min, draw.Src)
    
    	p1 := image.Point{r, r}
    	p2 := image.Point{x - r, r}
    	p3 := image.Point{r, y - r}
    	p4 := image.Point{x - r, y - r}
    
    	for m := 0; m < x; m++ {
    		for n := 0; n < y; n++ {
    			if (p1.X-m)*(p1.X-m)+(p1.Y-n)*(p1.Y-n) > r*r && m <= p1.X && n <= p1.Y {
    				dst.Set(m, n, c)
    			} else if (p2.X-m)*(p2.X-m)+(p2.Y-n)*(p2.Y-n) > r*r && m > p2.X && n <= p2.Y {
    				dst.Set(m, n, c)
    			} else if (p3.X-m)*(p3.X-m)+(p3.Y-n)*(p3.Y-n) > r*r && m <= p3.X && n > p3.Y {
    				dst.Set(m, n, c)
    			} else if (p4.X-m)*(p4.X-m)+(p4.Y-n)*(p4.Y-n) > r*r && m > p4.X && n > p4.Y {
    				dst.Set(m, n, c)
    			}
    		}
    	}
    	return dst, nil
    }
    
    func CreateRoundRectWithoutColor(rd io.Reader, r int) (*image.RGBA, error) {
    	src, _, err := image.Decode(rd)
    	if err != nil {
    		return nil, err
    	}
    
    	b := src.Bounds()
    	x := b.Dx()
    	y := b.Dy()
    	dst := image.NewRGBA(b)
    
    	p1 := image.Point{r, r}
    	p2 := image.Point{x - r, r}
    	p3 := image.Point{r, y - r}
    	p4 := image.Point{x - r, y - r}
    
    	for m := 0; m < x; m++ {
    		for n := 0; n < y; n++ {
    			if (p1.X-m)*(p1.X-m)+(p1.Y-n)*(p1.Y-n) > r*r && m <= p1.X && n <= p1.Y {
    			} else if (p2.X-m)*(p2.X-m)+(p2.Y-n)*(p2.Y-n) > r*r && m > p2.X && n <= p2.Y {
    			} else if (p3.X-m)*(p3.X-m)+(p3.Y-n)*(p3.Y-n) > r*r && m <= p3.X && n > p3.Y {
    			} else if (p4.X-m)*(p4.X-m)+(p4.Y-n)*(p4.Y-n) > r*r && m > p4.X && n > p4.Y {
    			} else {
    				dst.Set(m, n, src.At(m, n))
    			}
    		}
    	}
    	return dst, nil
    }
    
    func CreateRoundRectWithRGBA(src *image.RGBA, r int) (*image.RGBA, error) {
    	b := src.Bounds()
    	x := b.Dx()
    	y := b.Dy()
    	dst := image.NewRGBA(b)
    
    	p1 := image.Point{r, r}
    	p2 := image.Point{x - r, r}
    	p3 := image.Point{r, y - r}
    	p4 := image.Point{x - r, y - r}
    
    	for m := 0; m < x; m++ {
    		for n := 0; n < y; n++ {
    			if (p1.X-m)*(p1.X-m)+(p1.Y-n)*(p1.Y-n) > r*r && m <= p1.X && n <= p1.Y {
    			} else if (p2.X-m)*(p2.X-m)+(p2.Y-n)*(p2.Y-n) > r*r && m > p2.X && n <= p2.Y {
    			} else if (p3.X-m)*(p3.X-m)+(p3.Y-n)*(p3.Y-n) > r*r && m <= p3.X && n > p3.Y {
    			} else if (p4.X-m)*(p4.X-m)+(p4.Y-n)*(p4.Y-n) > r*r && m > p4.X && n > p4.Y {
    			} else {
    				dst.Set(m, n, src.At(m, n))
    			}
    		}
    	}
    	return dst, nil
    }
    
    //0xC8CED4
    func GetRGBA(c int) *color.RGBA {
    	var cl color.RGBA
    	cl.R = uint8((c >> 16) & 0xFF)
    	cl.G = uint8((c >> 8) & 0xFF)
    	cl.B = uint8(c & 0xFF)
    	return &cl
    }
    func getXy6Grid(size int) []*Point {
    	s := make([]*Point, size)
    	_x, _y := 4, 4
    	s[0] = &Point{_x, _y}
    	s[1] = &Point{60 + 2*_x, _y}
    	s[2] = &Point{60 + 2*_x, 28 + 2*_y}
    	if size >= 4 {
    		s[3] = &Point{60 + 2*_x, 28*2 + 3*_y}
    	}
    	if size >= 5 {
    		s[4] = &Point{28 + 2*_x, 60 + 2*_y}
    	}
    	if size >= 6 {
    		s[5] = &Point{_x, 60 + 2*_y}
    	}
    
    	return s
    }
    
    

    以下是仿微信群头像

    
    //Merge 九宫格头像合成 固定新图大小132*132px 间隙3px
    //至少一张图片
    func Merge(src []io.Reader, dst io.Writer) error {
    	defer func() {
    		if r := recover(); r != nil {
    			log.Println("Merge.recover:", r)
    		}
    	}()
    	var err error
    	imagePoints := getXy(len(src))
    	width := getWidth(len(src))
    
    	//创建背景图
    	background := image.NewRGBA(image.Rect(0, 0, 132, 132))
    
    	//设置背景为灰色
    	for m := 0; m < 132; m++ {
    		for n := 0; n < 132; n++ {
    			background.SetRGBA(m, n, color.RGBA{127, 127, 127, 0})
    		}
    	}
    
    	for i, v := range imagePoints {
    		x := v.x
    		y := v.y
    
    		fOut := memory.NewWriter()
    
    		err = Scale(src[i], fOut, width, width, 100)
    		if err != nil {
    			return err
    		}
    
    		//file2draw, err := jpeg.Decode(fOut)
    		file2draw, _, err := image.Decode(fOut)
    		if err != nil {
    			return err
    		}
    		draw.Draw(background, background.Bounds(), file2draw, file2draw.Bounds().Min.Sub(image.Pt(x, y)), draw.Src)
    	}
    
    	return jpeg.Encode(dst, background, nil)
    }
    
    type Point struct {
    	x, y int
    }
    
    func getXy(size int) []*Point {
    	s := make([]*Point, size)
    	var _x, _y int
    
    	if size == 1 {
    		_x, _y = 6, 6
    		s[0] = &Point{_x, _y}
    	}
    	if size == 2 {
    		_x, _y = 4, 4
    		s[0] = &Point{_x, 132/2 - 60/2}
    		s[1] = &Point{60 + 2*_x, 132/2 - 60/2}
    	}
    	if size == 3 {
    		_x, _y = 4, 4
    		s[0] = &Point{132/2 - 60/2, _y}
    		s[1] = &Point{_x, 60 + 2*_y}
    		s[2] = &Point{60 + 2*_y, 60 + 2*_y}
    	}
    	if size == 4 {
    		_x, _y = 4, 4
    		s[0] = &Point{_x, _y}
    		s[1] = &Point{_x*2 + 60, _y}
    		s[2] = &Point{_x, 60 + 2*_y}
    		s[3] = &Point{60 + 2*_y, 60 + 2*_y}
    	}
    	if size == 5 {
    		_x, _y = 3, 3
    		s[0] = &Point{(132 - 40*2 - _x) / 2, (132 - 40*2 - _y) / 2}
    		s[1] = &Point{((132-40*2-_x)/2 + 40 + _x), (132 - 40*2 - _y) / 2}
    		s[2] = &Point{_x, ((132-40*2-_x)/2 + 40 + _y)}
    		s[3] = &Point{(_x*2 + 40), ((132-40*2-_x)/2 + 40 + _y)}
    		s[4] = &Point{(_x*3 + 40*2), ((132-40*2-_x)/2 + 40 + _y)}
    	}
    	if size == 6 {
    		_x, _y = 3, 3
    		s[0] = &Point{_x, ((132 - 40*2 - _x) / 2)}
    		s[1] = &Point{(_x*2 + 40), ((132 - 40*2 - _x) / 2)}
    		s[2] = &Point{(_x*3 + 40*2), ((132 - 40*2 - _x) / 2)}
    		s[3] = &Point{_x, ((132-40*2-_x)/2 + 40 + _y)}
    		s[4] = &Point{(_x*2 + 40), ((132-40*2-_x)/2 + 40 + _y)}
    		s[5] = &Point{(_x*3 + 40*2), ((132-40*2-_x)/2 + 40 + _y)}
    	}
    
    	if size == 7 {
    		_x, _y = 3, 3
    		s[0] = &Point{(132 - 40) / 2, _y}
    		s[1] = &Point{_x, (_y*2 + 40)}
    		s[2] = &Point{(_x*2 + 40), (_y*2 + 40)}
    		s[3] = &Point{(_x*3 + 40*2), (_y*2 + 40)}
    		s[4] = &Point{_x, (_y*3 + 40*2)}
    		s[5] = &Point{(_x*2 + 40), (_y*3 + 40*2)}
    		s[6] = &Point{(_x*3 + 40*2), (_y*3 + 40*2)}
    	}
    	if size == 8 {
    		_x, _y = 3, 3
    		s[0] = &Point{(132 - 80 - _x) / 2, _y}
    		s[1] = &Point{((132-80-_x)/2 + _x + 40), _y}
    		s[2] = &Point{_x, (_y*2 + 40)}
    		s[3] = &Point{(_x*2 + 40), (_y*2 + 40)}
    		s[4] = &Point{(_x*3 + 40*2), (_y*2 + 40)}
    		s[5] = &Point{_x, (_y*3 + 40*2)}
    		s[6] = &Point{(_x*2 + 40), (_y*3 + 40*2)}
    		s[7] = &Point{(_x*3 + 40*2), (_y*3 + 40*2)}
    	}
    	if size == 9 {
    		_x, _y = 3, 3
    		s[0] = &Point{_x, _y}
    		s[1] = &Point{_x*2 + 40, _y}
    		s[2] = &Point{_x*3 + 40*2, _y}
    		s[3] = &Point{_x, (_y*2 + 40)}
    		s[4] = &Point{(_x*2 + 40), (_y*2 + 40)}
    		s[5] = &Point{(_x*3 + 40*2), (_y*2 + 40)}
    		s[6] = &Point{_x, (_y*3 + 40*2)}
    		s[7] = &Point{(_x*2 + 40), (_y*3 + 40*2)}
    		s[8] = &Point{(_x*3 + 40*2), (_y*3 + 40*2)}
    	}
    	return s
    }
    
    func getWidth(size int) int {
    	var width int
    	if size == 1 {
    		width = 120
    	}
    	if size > 1 && size <= 4 {
    		width = 60
    	}
    	if size >= 5 {
    		width = 40
    	}
    	return width
    }
    
    
    
  • 相关阅读:
    关于同余最短路
    【水】关于 __attribute__
    题解【AtCoder
    一些简单图论问题
    浅谈简单动态规划
    关于博客园主题(美化博客园)
    Algebra, Topology, Differential Calculus, and Optimization Theory For Computer Science and Machine Learning 第47章 读书笔记(待更新)
    Algebra, Topology, Differential Calculus, and Optimization Theory For Computer Science and Machine Learning 第46章 读书笔记(待更新)
    Algebra, Topology, Differential Calculus, and Optimization Theory For Computer Science and Machine Learning 第45章 读书笔记(待更新)
    Algebra, Topology, Differential Calculus, and Optimization Theory For Computer Science and Machine Learning 第44章 读书笔记(待更新)
  • 原文地址:https://www.cnblogs.com/cqvoip/p/8078843.html
Copyright © 2011-2022 走看看