中文 | English
本项目基于以下开源库: imaging
About Imaging is a simple image processing package for Go
WebP decoder and encoder for Go (Zero Dependencies).
Go Graphics - 2D rendering in Go with a simple API.
Imageprocess
是一个简单的Go图像处理包。支持 WEBP,JPG,JPEG,PNG,BMP,TIFF,GIF。提供了类似阿里云oss
的图片处理能力。
包括:
参数兼容阿里云oss图片处理参数,可以用于搭建本地文件oss图片处理系统。
go get github.com/AndsGo/imageprocess
代码Api
使用示例
// 改变大小,高100px,宽300px,模式等比缩放匹配最大边
img = imageprocess.ResizeImage(img, ResizeOption{ResizeMode: Lfit, Width: 10, Height: 100)
// 将原图缩放成宽高100 px:`resize,h_100,w_100` 缩放模式fill:`m_fill`
img = imageprocess.ResizeImage(img, ResizeOption{ResizeMode: Fill, Width: 10, Height: 100)
// 将原图缩放成宽高100 px:`resize,h_100,w_100` 缩放模式pad:`m_pad`。 以红色填充:`color_FF0000`
img = imageprocess.ResizeImage(img, ResizeOption{ResizeMode: Pad, Width: 10, Height: 100 Color: &color.RGBA{R: 255, G: 0, B: 0, A: 255}})
// 将example.jpg缩略为宽高300:`resize,w_300,h_300` 水印内容为“Hello World”:`text_Hello%20World 水印文字颜色为白色、字体大小为30:`color_FFFFFF,size_30` ` 水印文字位置是右下、水平边距10、中线垂直偏移10:`g_se,x_10,y_10`
// 多模式串行处理可以使用Process或(ProcessGif)方法,你也可以全部使用Process或(ProcessGif)方法进行处理
options := make([]Option, 0)
options = append(options, Option{Resize, ResizeOption{Width: 300, Height: 300)
options = append(options, Option{Watermark, TextWatermarkOption{WatermarkOption: WatermarkOption{
Opacity: 20, Position: Center, X: 10, Y: 10,
}, Color: &color.RGBA{255, 255, 255, 1}, Size: 30, Text: "Hello World"}})
imageprocess.Process(img, file, options)
// 裁剪起点为(800,500):`crop,x_800,y_500` 裁减范围300 px*300 px:`w_300,h_300`
img = imageprocess.CropImage(img, CropOption{X:800,Y:500,Width: 300, Height: 300})
// 裁剪起点为原图右下角:`crop,g_se` 裁减范围900 px*900 px:`w_900,h_900`
img = imageprocess.CropImage(img, CropOption{Position: SouthEast,Width: 900, Height: 900})
// 原图缩放为宽100 px:`resize,w_100,h_100` 图片相对质量设置为80%:`quality,q_80`
options := make([]Option, 0)
options = append(options, Option{Resize, ResizeOption{Width: 100, Height: 100)
// 质量
options = append(options, Option{Quality, QualityOption{Quality: 80}})
// 格式转换为PNG
options = append(options, Option{FormatType, FormatOption{Format: PNG}})
imageprocess.Process(img, file, options)
// 将原图按顺时针旋转90°
img = imageprocess.AddjustRotate(img,RotateOption{Value:90})
// 将图片亮度提高50
img = imageprocess.AddjustBright(img,BrightnessOption{Value:50})
// 对原图进行锐化处理,锐化参数为100
img = imageprocess.AddjustSharpen(img,SharpenOption{Value:100})
// 对比度提高50
img = imageprocess.AddjustContrast(img,ContrastOption{Value:50})
综合代码示例请查看
process_test.go
package imageprocess
import (
"image/color"
"os"
"testing"
)
func Test_Process(t *testing.T) {
img, f, err := LoadImage("examples/example.jpg")
if err != nil {
t.Error(err)
}
file, _ := os.Create("examples/out.jpg")
options := make([]Option, 0)
// 格式转换为PNG
options = append(options, Option{FormatType, FormatOption{Format: PNG}})
// 改变大小
options = append(options, Option{Resize, ResizeOption{ResizeMode: Pad, Width: 300, Height: 300, Color: &color.RGBA{R: 255, G: 255, B: 0, A: 255}}})
// 裁剪
options = append(options, Option{Crop, CropOption{Width: 200, Height: 200, X: 0, Y: 0, Position: Center}})
// 水印
options = append(options, Option{Watermark, TextWatermarkOption{WatermarkOption: WatermarkOption{
Opacity: 100, Position: South, X: 10, Y: 10,
}, Color: &color.RGBA{111, 222, 111, 1}, Size: 40, Text: "hello watermark"}})
// 模糊
options = append(options, Option{Blur, GammaOption{Value: 5}})
// 质量
options = append(options, Option{Quality, QualityOption{Quality: 500}})
err = Process(img, file, f, options)
if err != nil {
t.Error(err)
}
}
func Test_ProcessGif(t *testing.T) {
img, err := LoadGif("examples/example.gif")
if err != nil {
t.Error(err)
}
file, _ := os.Create("examples/out.gif")
options := make([]Option, 0)
// 格式转换为GIF
options = append(options, Option{FormatType, FormatOption{Format: GIF}})
options = append(options, Option{Gamma, GammaOption{Value: 500}})
options = append(options, Option{Resize, ResizeOption{ResizeMode: Pad, Width: 300, Height: 300, Color: &color.RGBA{R: 255, G: 255, B: 255, A: 1}}})
options = append(options, Option{Crop, CropOption{Width: 200, Height: 200, X: 0, Y: 0, Position: Center}})
options = append(options, Option{Watermark, TextWatermarkOption{WatermarkOption: WatermarkOption{
Opacity: 20, Position: Center, X: 10, Y: 10,
}, Color: &color.RGBA{0, 0, 0, 1}, Size: 40, Text: "hello watermark"}})
err = ProcessGif(img, file, options)
if err != nil {
t.Error(err)
}
}
func Test_UrlOptions(t *testing.T) {
img, f, err := LoadImage("examples/example.jpg")
if err != nil {
t.Error(err)
}
file, _ := os.Create("examples/out.jpg")
// 增加水印,然后修改大小
options, err := ParseOptions("image/watermark,t_30,g_center,x_10,y_10,text_hello watermark,color_1366ec,size_200/resize,m_pad,h_100,w_100,color_FF0000")
if err != nil {
t.Error(err)
}
err = Process(img, file, f, options)
if err != nil {
t.Error(err)
}
}
url参数示例
格式转换可以在process_test中进行测试 ,测试代码如下
func Test_UrlOptions(t *testing.T) {
img, f, err := LoadImage("examples/example.jpg")
if err != nil {
t.Error(err)
}
file, _ := os.Create("examples/out.jpg")
// 增加水印,然后修改大小
options, err := ParseOptions("image/watermark,t_30,g_center,x_10,y_10,text_hello watermark,color_1366ec,size_200/resize,m_pad,h_100,w_100,color_FF0000")
if err != nil {
t.Error(err)
}
// 处理图片
err = Process(img, file, f, options)
if err != nil {
t.Error(err)
}
}
这是一个简单文件服务器的例子,代码位于examples
文件夹下
cd examples
go run example.go
访问:
结果: 400*300 65.4k
转换代码表示:
resize,w_500,h_300
转换宽500,高300
watermark,t_80,g_se,x_10,y_10,text_hello,color_FFFFFF,size_40
增加水印,水印位置位于右下,离边缘距离为10,水印内容为hello,颜色为FFFFFF,文字大小为40
format,webp
格式转换为 webp
示例代码(你测试自己的图片需要修改 fileFolders
):
package main
import (
"fmt"
"image/gif"
"io"
"net/http"
"os"
"strings"
"github.com/AndsGo/imageprocess"
)
// 文件夹,you need change it
var fileFolders = "./"
func main() {
http.HandleFunc("/file/", fileHandler)
fmt.Println("Starting server on :8080")
if err := http.ListenAndServe(":8080", nil); err != nil {
fmt.Println("Server failed:", err)
}
}
func fileHandler(w http.ResponseWriter, r *http.Request) {
// 获取文件名称
fileName := strings.TrimPrefix(r.URL.Path, "/file/")
// 打开文件
file, err := os.Open(fmt.Sprintf("%s%s", fileFolders, fileName))
if err != nil {
http.Error(w, "File not found", http.StatusNotFound)
return
}
defer file.Close()
// 获取参数
// 获取文件后缀
f, err := imageprocess.FormatFromExtension(fileName)
if err != nil {
// 将处理后的文件内容写入响应
if _, err := io.Copy(w, file); err != nil {
http.Error(w, "Failed to send file", http.StatusInternalServerError)
}
return
}
//处理处理参数
ossParams := r.URL.Query().Get("x-oss-process")
if ossParams == "" {
//无需处理
if _, err := io.Copy(w, file); err != nil {
http.Error(w, "Failed to send file", http.StatusInternalServerError)
}
return
}
options, err := imageprocess.ParseOptions(ossParams)
if err != nil {
http.Error(w, fmt.Sprintf("ParseOptions %s", err.Error()), http.StatusInternalServerError)
return
}
if len(options) == 0 {
//无需处理
if _, err := io.Copy(w, file); err != nil {
http.Error(w, "Failed to send file", http.StatusInternalServerError)
}
return
}
//处理图片
err = processImg(file, w, f, options)
if err != nil {
http.Error(w, fmt.Sprintf("processFile %s", err.Error()), http.StatusInternalServerError)
}
}
// 进行转换
func processImg(file io.Reader, w io.Writer, f imageprocess.Format, options []imageprocess.Option) error {
if f == imageprocess.GIF {
imgGif, err := gif.DecodeAll(file)
if err != nil {
return err
}
return imageprocess.ProcessGif(imgGif, w, options)
} else {
img, err := imageprocess.DecodeImage(file, f)
if err != nil {
return err
}
return imageprocess.Process(img, w, f, options)
}
}