1. Golang图片操作简介
Go语言是现代化的编程语言,适用于编写高效且安全的系统级代码,包括开发像网络服务这样的底层技术,也包括编写像图片处理这样的应用程序。
Golang中提供了image包用来进行图片的操作,作为一个强大的编程语言,Golang可以非常容易的实现图片的缩放和旋转等操作。接下来我们将讲解如何实现图片的缩放和旋转。
2. 图片缩放的实现
2.1 image包中的Image类型
在Golang中,用于表示图片的是Image类型,这个类型定义如下:
type Image interface {
ColorModel() color.Model
Bounds() Rectangle
At(x, y int) color.Color
}
其中ColorModel()函数返回用于表示图片色彩模型的color.Model类型;Bounds()函数返回一个表示图片边界框的Rectangle类型;At(x, y int)函数返回图片中指定坐标处的color.Color类型的值。
2.2 图片缩放的实现
图片缩放就是把图片变大或者变小,可以通过修改图片像素点坐标来实现缩放。
首先,我们需要读取要缩放的图片文件,并将其转化为Image类型。
img, err := os.Open("example.jpg")
if err != nil {
log.Fatal(err)
}
defer img.Close()
pic, _, err := image.Decode(img)
if err != nil {
log.Fatal(err)
}
这里用到了image包中的Decode()函数来将图片文件转化为Image类型的数据。
接下来,我们需要指定缩放后的新图片大小,通过计算比例来计算新图片的大小:
width := pic.Bounds().Max.X
height := pic.Bounds().Max.Y
newWidth := 200
newHeight := int(float64(height) / float64(width) * float64(newWidth))
scaled := image.NewRGBA(image.Rect(0, 0, newWidth, newHeight))
在上面的代码中,我们通过计算图片的宽高比,得到了缩放后的新图片的大小,然后使用image包中的NewRGBA()函数,来创建一个新的RGBA类型的Image,并传入新的图片大小。
最后,我们需要将原图片的像素点缩小或放大,并将缩放后的像素点放到新的图片上:
for y := 0; y < newHeight; y++ {
for x := 0; x < newWidth; x++ {
newX := int(float64(x) / float64(newWidth) * float64(width))
newY := int(float64(y) / float64(newHeight) * float64(height))
r, g, b, a := pic.At(newX, newY).RGBA()
col := color.RGBA{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)}
scaled.SetRGBA(x, y, col)
}
}
在上面的代码中,我们使用两个for循环来遍历新图片的每个像素点,然后通过计算原图片中该像素点的坐标,来得到原图片中的像素点,并将其放到新图片中。
最终,我们将新图片保存到文件中:
scaledFile, err := os.Create("scaled.jpg")
if err != nil {
log.Fatal(err)
}
defer scaledFile.Close()
jpeg.Encode(scaledFile, scaled, &jpeg.Options{Quality: 100})
完整的缩放代码如下:
package main
import (
"image"
"image/color"
"image/jpeg"
"log"
"os"
)
func main() {
img, err := os.Open("example.jpg")
if err != nil {
log.Fatal(err)
}
defer img.Close()
pic, _, err := image.Decode(img)
if err != nil {
log.Fatal(err)
}
width := pic.Bounds().Max.X
height := pic.Bounds().Max.Y
newWidth := 200
newHeight := int(float64(height) / float64(width) * float64(newWidth))
scaled := image.NewRGBA(image.Rect(0, 0, newWidth, newHeight))
for y := 0; y < newHeight; y++ {
for x := 0; x < newWidth; x++ {
newX := int(float64(x) / float64(newWidth) * float64(width))
newY := int(float64(y) / float64(newHeight) * float64(height))
r, g, b, a := pic.At(newX, newY).RGBA()
col := color.RGBA{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)}
scaled.SetRGBA(x, y, col)
}
}
scaledFile, err := os.Create("scaled.jpg")
if err != nil {
log.Fatal(err)
}
defer scaledFile.Close()
jpeg.Encode(scaledFile, scaled, &jpeg.Options{Quality: 100})
}
3. 图片旋转的实现
图片旋转是指将图片按照一定的角度旋转,可以通过旋转图片坐标来实现。
首先,我们还是需要读取要旋转的图片文件,并将其转化为Image类型:
img, err := os.Open("example.jpg")
if err != nil {
log.Fatal(err)
}
defer img.Close()
pic, _, err := image.Decode(img)
if err != nil {
log.Fatal(err)
}
然后,我们需要指定旋转后的新图片大小和旋转的角度:
width := pic.Bounds().Max.X
height := pic.Bounds().Max.Y
angle := 45.0
sin := math.Sin(angle * math.Pi / 180)
cos := math.Cos(angle * math.Pi / 180)
newWidth := int(float64(width)*math.Abs(cos) + float64(height)*math.Abs(sin))
newHeight := int(float64(width)*math.Abs(sin) + float64(height)*math.Abs(cos))
rotated := image.NewRGBA(image.Rect(0, 0, newWidth, newHeight))
在上面的代码中,我们使用math包中的Sin()和Cos()函数,来得到旋转角度的正弦和余弦值,然后根据旋转角度和图片大小,来计算新图片的大小,并使用image包中的NewRGBA()函数,来创建一个新的RGBA类型的Image,并传入新的图片大小。
接着,我们需要将原图片的像素点按照旋转后的角度进行旋转,并将旋转后的像素点放到新的图片上:
for y := 0; y < newHeight; y++ {
for x := 0; x < newWidth; x++ {
centerX := float64(width) / 2
centerY := float64(height) / 2
qx := float64(x) - centerX
qy := float64(y) - centerY
rotatedX := int(qx*cos - qy*sin + centerX)
rotatedY := int(qx*sin + qy*cos + centerY)
if rotatedX >= 0 && rotatedX < width && rotatedY >= 0 && rotatedY < height {
r, g, b, a := pic.At(rotatedX, rotatedY).RGBA()
col := color.RGBA{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)}
rotated.SetRGBA(x, y, col)
}
}
}
在上面的代码中,我们使用两个for循环来遍历新图片的每个像素点,然后计算原图片中对应的旋转后的像素点,并将其放到新图片中。
注意,在计算旋转后的像素点坐标时,我们需要先将像素点坐标平移到原点处,进行角度旋转后,再平移回去。
最终,我们将新图片保存到文件中:
rotatedFile, err := os.Create("rotated.jpg")
if err != nil {
log.Fatal(err)
}
defer rotatedFile.Close()
jpeg.Encode(rotatedFile, rotated, &jpeg.Options{Quality: 100})
完整的旋转代码如下:
package main
import (
"image"
"image/color"
"image/jpeg"
"log"
"math"
"os"
)
func main() {
img, err := os.Open("example.jpg")
if err != nil {
log.Fatal(err)
}
defer img.Close()
pic, _, err := image.Decode(img)
if err != nil {
log.Fatal(err)
}
width := pic.Bounds().Max.X
height := pic.Bounds().Max.Y
angle := 45.0
sin := math.Sin(angle * math.Pi / 180)
cos := math.Cos(angle * math.Pi / 180)
newWidth := int(float64(width)*math.Abs(cos) + float64(height)*math.Abs(sin))
newHeight := int(float64(width)*math.Abs(sin) + float64(height)*math.Abs(cos))
rotated := image.NewRGBA(image.Rect(0, 0, newWidth, newHeight))
for y := 0; y < newHeight; y++ {
for x := 0; x < newWidth; x++ {
centerX := float64(width) / 2
centerY := float64(height) / 2
qx := float64(x) - centerX
qy := float64(y) - centerY
rotatedX := int(qx*cos - qy*sin + centerX)
rotatedY := int(qx*sin + qy*cos + centerY)
if rotatedX >= 0 && rotatedX < width && rotatedY >= 0 && rotatedY < height {
r, g, b, a := pic.At(rotatedX, rotatedY).RGBA()
col := color.RGBA{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)}
rotated.SetRGBA(x, y, col)
}
}
}
rotatedFile, err := os.Create("rotated.jpg")
if err != nil {
log.Fatal(err)
}
defer rotatedFile.Close()
jpeg.Encode(rotatedFile, rotated, &jpeg.Options{Quality: 100})
}
4. 总结
通过本文的介绍,我们学习了如何在Golang中使用image包来进行图片的缩放和旋转操作。在这个过程中,我们了解了Image类型的基本元素,并实现了图片缩放和旋转的完整代码,这些代码在实际应用中具有很大的实用价值。