Golang图片操作:学习如何进行图片的缩放和旋转

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类型的基本元素,并实现了图片缩放和旋转的完整代码,这些代码在实际应用中具有很大的实用价值。

后端开发标签