golang图片属性orientation在image.Decode后丢失,导致图片上传后旋转

通常图片web上传后,会进行image.Decode() 解码、resize.Reszie()图片压缩、jpeg.Encode()编码保存等处理。

但部分图片在处理过后,图片显示会被旋转。通常在于苹果手机拍出的照片,而安卓手机正常。

这是苹果手机等设备拍照后,图片文件上带有orientation方向属性,系统打开显示时会自动根据方向属性进行调整,让我们看起来是正常的。

而后台处理后,orientation方向属性丢失(类似安卓手机拍的照片),导致保存后的新图片被旋转。

可以通过 github.com/rwcarlsen/goexif 包获取图片文件orientation方向属性,再处理期间进行图片旋转

以下为相关处理函数

注:个人感觉目前图片旋转处理方法效率不是很高,期待有人可以优化一下

import "github.com/rwcarlsen/goexif/exif"

//方向判断
func ReadOrientation(filename string) int {
   file, err := os.Open(filename)
   if err != nil {
      fmt.Println("failed to open file, err: ", err)
      return 0
   }
   defer file.Close()

   x, err := exif.Decode(file)
   if err != nil {
      fmt.Println("failed to decode file, err: ", err)
      return 0
   }

   orientation, err := x.Get(exif.Orientation)
   if err != nil {
      fmt.Println("failed to get orientation, err: ", err)
      return 0
   }
   orientVal, err := orientation.Int(0)
   if err != nil {
      fmt.Println("failed to convert type of orientation, err: ", err)
      return 0
   }

   fmt.Println("the value of photo orientation is :", orientVal)
   return orientVal
}


// 旋转90度
func  rotate90(m image.Image) image.Image {
	rotate90 := 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-- {
			//  设置像素点
			rotate90.Set(m.Bounds().Max.Y-x, y, m.At(y, x))
		}
	}
	return rotate90
}

// 旋转180度
func rotate180(m image.Image) image.Image {
	rotate180 := 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++ {
			//  设置像素点
			rotate180.Set(m.Bounds().Max.X-x, m.Bounds().Max.Y-y, m.At(x, y))
		}
	}
	return rotate180
}

// 旋转270度
func rotate270(m image.Image) image.Image {
	rotate270 := 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-- {
			// 设置像素点
			rotate270.Set(x, m.Bounds().Max.X-y, m.At(y, x))
		}
	}
	return rotate270
}

ReadOrientation方法会获取orientation的值,总共有0~8这几种情况

    orientationUnspecified = 0
	orientationNormal      = 1
	orientationFlipH       = 2
	orientationRotate180   = 3
	orientationFlipV       = 4
	orientationTranspose   = 5
	orientationRotate270   = 6
	orientationTransverse  = 7
	orientationRotate90    = 8

实用参考例子

import "github.com/nfnt/resize"

//压缩图片
func MakeThumbnail(imagePath, savePath string) error {
	ori := ReadOrientation(imagePath)
	file, _ := os.Open(imagePath)
	defer file.Close()

	img, _, err := image.Decode(file)
	if err != nil {
		return err
	}
	//苹果手机拍照的图片,会有方向属性Orientation,
	//经过Decode和Encode,编码处理后,方向属性会丢失,导致图片被旋转
	switch ori {
	case 6://90度图片旋转
		img = rotate90(img)
	case 3:
		img = rotate180(img)
	case 8:
		img = rotate270(img)
	}

	w := 900
    h := 1200

	// 调用resize库进行图片缩放
	m := resize.Resize(uint(w), uint(h), img, resize.Lanczos3)

	// 需要保存的文件
	imgfile, _ := os.Create(savePath)
	defer imgfile.Close()

	// 以jepg格式保存文件
	err = jpeg.Encode(imgfile, m, &jpeg.Options{70})
	if err != nil {
		return err
	}

	return nil
}

func main(){
    MakeThumbnail("原图.jpg","新图.jpg")
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值