本人宝宝出生后,特地为宝宝做了一个网站,用于上传照片、视频,想着是自己的网站,因此在前端上传的时候没有进行压缩,同时又为了提高图片加载速度,所以在后台进行了压缩。列表中看压缩图,点击看原图。然而通过苹果手机上传的照片经常会遇到压缩后照片方向发生变化的问题,而查看原图却正常,特此记录解决办法。

经过百度,发现是苹果手机拍摄的照片中带有方向信息,而压缩后就丢失了。因此在压缩前就需要读取方向信息,并做相应的方向翻转。

安装扩展库

用于读取方向信息

go get github.com/rwcarlsen/goexif/exif

完整代码main.go

package main

import (
	"image"
	"image/jpeg"
	"os"
	"github.com/rwcarlsen/goexif/exif"
)

func main() {
	src := "abc69678fae187df1b98ae5708e86583.jpeg"
	dst := "abc69678fae187df1b98ae5708e86583_thumb.jpeg"

	//通常只有 6,3,8 需要调整方向,所以不关心方向是否获取成功
	ori, _ := jpegOrientation(src)
	compress(ori, src, dst)

}

func compress(ori int, filename, dst string) error {
	sfp, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer sfp.Close()

	img, _, err := image.Decode(sfp)
	if err != nil {
		return err
	}

	dfp, err := os.Create(dst)
	if err != nil {
		return err
	}

	var finalImg image.Image
	//只有 6,3,8 需要调整方向
	switch ori {
	case 6:
		finalImg = rotate90(img)
	case 3:
		finalImg = rotate180(img)
	case 8:
		finalImg = rotate270(img)
		
	default:finalImg = img
	}

	err = jpeg.Encode(dfp, finalImg, &jpeg.Options{
		Quality: 15,
	})

	return err
}

//获取jpeg的方向信息
func jpegOrientation(src string) (int, error) {
	fp, err := os.Open(src)
	if err != nil {
		return 0, err
	}

	defer fp.Close()
	x, err := exif.Decode(fp)
	if err != nil {
		return 0, err
	}

	orientation, err := x.Get(exif.Orientation)
	if err != nil {
		return 0, err
	}

	ori, err := orientation.Int(0)
	return ori, err
}

func rotate90(m image.Image) image.Image {
	n := image.NewRGBA(image.Rect(0, 0, m.Bounds().Dy(), m.Bounds().Dx()))
	for x := m.Bounds().Min.Y; x < m.Bounds().Max.Y; x++ {
		for y := m.Bounds().Max.X - 1; y >= m.Bounds().Min.X; y-- {
			n.Set(m.Bounds().Max.Y-x, y, m.At(y, x))
		}
	}

	return n
}

// 旋转180度
func rotate180(m image.Image) image.Image {
	n := image.NewRGBA(image.Rect(0, 0, m.Bounds().Dx(), m.Bounds().Dy()))
	// 矩阵旋转
	for x := m.Bounds().Min.X; x < m.Bounds().Max.X; x++ {
		for y := m.Bounds().Min.Y; y < m.Bounds().Max.Y; y++ {
			//  设置像素点
			n.Set(m.Bounds().Max.X-x, m.Bounds().Max.Y-y, m.At(x, y))
		}
	}
	return n
}

// 旋转270度
func rotate270(m image.Image) image.Image {
	n := image.NewRGBA(image.Rect(0, 0, m.Bounds().Dy(), m.Bounds().Dx()))
	// 矩阵旋转
	for x := m.Bounds().Min.Y; x < m.Bounds().Max.Y; x++ {
		for y := m.Bounds().Max.X - 1; y >= m.Bounds().Min.X; y-- {
			// 设置像素点
			n.Set(x, m.Bounds().Max.X-y, m.At(y, x))
		}
	}
	return n
}