发送前调整图像大小
Resize image before sending
我想要一个带有 gin 的路由,它将发送图像 (jpeg) 作为响应,但我不想发送保存到磁盘的原始图像,而是想先调整它的大小(缩略图大小)。
到目前为止,我可以使用 c.File(filepath string)
发送图像,但这不允许我调整图像的大小。有什么方法可以做到这一点而不必在磁盘上创建新文件吗?
是的,您可以使用内置包 "image" 调整它的大小,我刚刚为您构建了它,具有不同的调整大小选项和字节/纯图像输出,选择您想要的。我过去没有使用过这个特定的包,所以欢迎对这段代码进行任何更正/建议。代码:
package main
import (
"bytes"
"image"
"image/color"
"image/draw"
"image/jpeg"
"io/ioutil"
"log"
"math"
"os"
)
func main() {
f, err := os.Open("resources/image.jpg")
if err != nil {
log.Fatal(err)
}
//encoding message is discarded, because OP wanted only jpg, else use encoding in resize function
img, _, err := image.Decode(f)
if err != nil {
log.Fatal(err)
}
//this is the resized image
resImg := resize(img, 20, 20)
//this is the resized image []bytes
imgBytes := imgToBytes(resImg)
//optional written to file
err = ioutil.WriteFile("resources/test.jpg", imgBytes, 0777)
if err != nil {
log.Fatal(err)
}
}
func resize(img image.Image, length int, width int) image.Image {
//truncate pixel size
minX := img.Bounds().Min.X
minY := img.Bounds().Min.Y
maxX := img.Bounds().Max.X
maxY := img.Bounds().Max.Y
for (maxX-minX)%length != 0 {
maxX--
}
for (maxY-minY)%width!= 0 {
maxY--
}
scaleX := (maxX - minX) / length
scaleY := (maxY - minY) / width
imgRect := image.Rect(0, 0, length, width)
resImg := image.NewRGBA(imgRect)
draw.Draw(resImg, resImg.Bounds(), &image.Uniform{C: color.White}, image.ZP, draw.Src)
for y := 0; y < width; y += 1 {
for x := 0; x < length; x += 1 {
averageColor := getAverageColor(img, minX+x*scaleX, minX+(x+1)*scaleX, minY+y*scaleY, minY+(y+1)*scaleY)
resImg.Set(x, y, averageColor)
}
}
return resImg
}
func getAverageColor(img image.Image, minX int, maxX int, minY int, maxY int) color.Color {
var averageRed float64
var averageGreen float64
var averageBlue float64
var averageAlpha float64
scale := 1.0 / float64((maxX-minX)*(maxY-minY))
for i := minX; i < maxX; i++ {
for k := minY; k < maxY; k++ {
r, g, b, a := img.At(i, k).RGBA()
averageRed += float64(r) * scale
averageGreen += float64(g) * scale
averageBlue += float64(b) * scale
averageAlpha += float64(a) * scale
}
}
averageRed = math.Sqrt(averageRed)
averageGreen = math.Sqrt(averageGreen)
averageBlue = math.Sqrt(averageBlue)
averageAlpha = math.Sqrt(averageAlpha)
averageColor := color.RGBA{
R: uint8(averageRed),
G: uint8(averageGreen),
B: uint8(averageBlue),
A: uint8(averageAlpha)}
return averageColor
}
func imgToBytes(img image.Image) []byte {
var opt jpeg.Options
opt.Quality = 80
buff := bytes.NewBuffer(nil)
err := jpeg.Encode(buff, img, &opt)
if err != nil {
log.Fatal(err)
}
return buff.Bytes()
}
我想要一个带有 gin 的路由,它将发送图像 (jpeg) 作为响应,但我不想发送保存到磁盘的原始图像,而是想先调整它的大小(缩略图大小)。
到目前为止,我可以使用 c.File(filepath string)
发送图像,但这不允许我调整图像的大小。有什么方法可以做到这一点而不必在磁盘上创建新文件吗?
是的,您可以使用内置包 "image" 调整它的大小,我刚刚为您构建了它,具有不同的调整大小选项和字节/纯图像输出,选择您想要的。我过去没有使用过这个特定的包,所以欢迎对这段代码进行任何更正/建议。代码:
package main
import (
"bytes"
"image"
"image/color"
"image/draw"
"image/jpeg"
"io/ioutil"
"log"
"math"
"os"
)
func main() {
f, err := os.Open("resources/image.jpg")
if err != nil {
log.Fatal(err)
}
//encoding message is discarded, because OP wanted only jpg, else use encoding in resize function
img, _, err := image.Decode(f)
if err != nil {
log.Fatal(err)
}
//this is the resized image
resImg := resize(img, 20, 20)
//this is the resized image []bytes
imgBytes := imgToBytes(resImg)
//optional written to file
err = ioutil.WriteFile("resources/test.jpg", imgBytes, 0777)
if err != nil {
log.Fatal(err)
}
}
func resize(img image.Image, length int, width int) image.Image {
//truncate pixel size
minX := img.Bounds().Min.X
minY := img.Bounds().Min.Y
maxX := img.Bounds().Max.X
maxY := img.Bounds().Max.Y
for (maxX-minX)%length != 0 {
maxX--
}
for (maxY-minY)%width!= 0 {
maxY--
}
scaleX := (maxX - minX) / length
scaleY := (maxY - minY) / width
imgRect := image.Rect(0, 0, length, width)
resImg := image.NewRGBA(imgRect)
draw.Draw(resImg, resImg.Bounds(), &image.Uniform{C: color.White}, image.ZP, draw.Src)
for y := 0; y < width; y += 1 {
for x := 0; x < length; x += 1 {
averageColor := getAverageColor(img, minX+x*scaleX, minX+(x+1)*scaleX, minY+y*scaleY, minY+(y+1)*scaleY)
resImg.Set(x, y, averageColor)
}
}
return resImg
}
func getAverageColor(img image.Image, minX int, maxX int, minY int, maxY int) color.Color {
var averageRed float64
var averageGreen float64
var averageBlue float64
var averageAlpha float64
scale := 1.0 / float64((maxX-minX)*(maxY-minY))
for i := minX; i < maxX; i++ {
for k := minY; k < maxY; k++ {
r, g, b, a := img.At(i, k).RGBA()
averageRed += float64(r) * scale
averageGreen += float64(g) * scale
averageBlue += float64(b) * scale
averageAlpha += float64(a) * scale
}
}
averageRed = math.Sqrt(averageRed)
averageGreen = math.Sqrt(averageGreen)
averageBlue = math.Sqrt(averageBlue)
averageAlpha = math.Sqrt(averageAlpha)
averageColor := color.RGBA{
R: uint8(averageRed),
G: uint8(averageGreen),
B: uint8(averageBlue),
A: uint8(averageAlpha)}
return averageColor
}
func imgToBytes(img image.Image) []byte {
var opt jpeg.Options
opt.Quality = 80
buff := bytes.NewBuffer(nil)
err := jpeg.Encode(buff, img, &opt)
if err != nil {
log.Fatal(err)
}
return buff.Bytes()
}