天增的博客
首页
博客
  • 分布式解决方案
  • Java并发工具包
  • redis
  • LeetCode
  • 系统设计
  • JVM体系
Github (opens new window)
Rss (opens new window)
  • zh-CN
  • en-US
首页
博客
  • 分布式解决方案
  • Java并发工具包
  • redis
  • LeetCode
  • 系统设计
  • JVM体系
Github (opens new window)
Rss (opens new window)
  • zh-CN
  • en-US
  • posts
  • 七牛云自定义处理图片
2022-04-21

七牛云自定义处理图片

# 七牛云自定义处理图片

由于七牛云提供的图片处理服务无法满足业务需求,因此是需要,自定义数据处理服务,对图片进行处理。 目前支持两种类型的处理:

  • 将图片置灰 /grey
  • png图片加上背景颜色 /background/<颜色16进制代码>
package main

import (
	"bytes"
	"fmt"
	"image"
	_ "image"
	"image/color"
	"image/draw"
	"image/png"
	_ "image/png"
	"io/ioutil"
	"log"
	"net/http"
	url2 "net/url"
	"os"
	"strings"
)

// HTTPGetMaxSize 最大处理的文件长度
const HTTPGetMaxSize = 2 * 1024 * 1024

func httpGet(url string) (body []byte, err error, res *http.Response) {
	res, err = http.Get(url)
	if err != nil {
		return nil, fmt.Errorf("httpGet error: %s", err), res
	}
	defer res.Body.Close()
	body, err = ioutil.ReadAll(http.MaxBytesReader(nil, res.Body, HTTPGetMaxSize))
	if err != nil {
		return nil, fmt.Errorf("httpGet read body error: %s", err), res
	}
	return
}

func handler(rw http.ResponseWriter, req *http.Request) {
	log.Println("获取到请求", req.URL.RawQuery)
	println("获取到请求", req.URL.RawQuery)
	var err error
	defer func() {
		if err != nil {
			http.Error(rw, err.Error(), 500)
		}
	}()

	defer req.Body.Close()
	var body []byte
	var res *http.Response

	cmd, _ := url2.QueryUnescape(req.URL.Query().Get("cmd"))
	op := strings.Split(cmd, "/")

	url := req.URL.Query().Get("url")
	if url != "" {
		body, err, res = httpGet(url)
		if err != nil {
			log.Println("handler http get error:", err.Error())
		}
	} else {
		body, err = ioutil.ReadAll(req.Body)
		if err != nil {
			log.Printf("handler body read error: %s\n", err.Error())
			return
		}
	}

	img, err := png.Decode(bytes.NewReader(body))
	switch op[1] {
	// handler/grey
	case "grey":
		img = greyImage(img)
		break
	// handler/background
	case "background":
		img = backGroundImage(img, op[2])
		break

	}
	write(rw, img, res)

}

/**
 * 给图片增加背景颜色
 */
func backGroundImage(srcImage image.Image, color string) image.Image {
	bounds := srcImage.Bounds()
	newRgba := image.NewRGBA(bounds)
	c, _ := ParseHexColor(color)
	for x := 0; x < newRgba.Bounds().Dx(); x++ { // 将背景图涂黑
		for y := 0; y < newRgba.Bounds().Dy(); y++ {
			newRgba.Set(x, y, c)
		}
	}
	// 在中间贴图
	draw.Draw(newRgba, newRgba.Bounds(), srcImage, image.Pt(0, 0), draw.Over)
	return newRgba
}
func ParseHexColor(s string) (c color.RGBA, err error) {
	c.A = 0xff
	switch len(s) {
	case 6:
		_, err = fmt.Sscanf(s, "%02x%02x%02x", &c.R, &c.G, &c.B)
	case 3:
		_, err = fmt.Sscanf(s, "%1x%1x%1x", &c.R, &c.G, &c.B)
		// Double the hex digits:
		c.R *= 17
		c.G *= 17
		c.B *= 17
	case 5:
		s = "0" + s
		_, err = fmt.Sscanf(s, "%02x%02x%02x", &c.R, &c.G, &c.B)
	default:
		err = fmt.Errorf("invalid length, must be 7 or 4")

	}
	return
}

/**
 * 图片灰化处理
 */
func greyImage(m image.Image) *image.RGBA {
	bounds := m.Bounds()
	dx := bounds.Dx()
	dy := bounds.Dy()
	newRgba := image.NewRGBA(bounds)
	for i := 0; i < dx; i++ {
		for j := 0; j < dy; j++ {
			colorRgb := m.At(i, j)
			_, g, _, a := colorRgb.RGBA()
			gUint8 := uint8(g >> 8)
			aUint8 := uint8(a >> 8)
			newRgba.SetRGBA(i, j, color.RGBA{R: gUint8, G: gUint8, B: gUint8, A: aUint8})
		}
	}
	return newRgba
}
func write(rw http.ResponseWriter, img image.Image, res *http.Response) {
	if res != nil {
		rw.Header().Set("content-type", res.Header.Get("content-type"))
		rw.Header().Set("Content-Disposition", res.Header.Get("Content-Disposition"))
	}
	png.Encode(rw, img)
}

func health(rw http.ResponseWriter, req *http.Request) {
	rw.Write([]byte("ok"))
}

func main() {
	port := os.Getenv("PORT_HTTP")
	if port == "" {
		port = "9100"
	}
	http.HandleFunc("/handler", handler)
	http.HandleFunc("/health", health)
	log.Fatalln(http.ListenAndServe("0.0.0.0:"+port, nil))
}

github: https://github.com/zxcvbnmzsedr/ufop-golang-demo

最近更新
01
GitLab 配置CORS访问
11-12
02
在国内网络环境下部署 Langfuse 到 K3s 的完整实践
10-31
03
VibeCode
10-24
更多文章>
Theme by Vdoing | Copyright © 2015-2026 天增 | 苏ICP备16037388号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式