Exif
可交换图像文件格式(英语:Exchangeable image file format,官方简称Exif),是专门为数码相机的照片设定的文件格式,可以记录数码照片的属性信息和拍摄数据。
通过手机或者相机拍摄的照片中会携带Exif信息,而某些手机默认会携带地理位置等隐私信息,比如下面这张图片

它的Exif信息为:

可以直接看到该照片使用Redmi K30 Pro拍摄于2021:01:25 19:15:28,甚至还可以直接看到经纬度信息(手机设置中可关闭)。这种未经过处理的照片直接上传到网上之后,可能会造成隐私的泄露。
Go读取Exif信息
通过包goexif/exif,可以查看照片的全部Exif信息
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | func GetExif() error {ImgFile := "./IMG_20210125_191526.jpg"
 file, err := os.Open(ImgFile)
 if err != nil {
 fmt.Println(err)
 return err
 }
 defer file.Close()
 x, err := exif.Decode(file)
 if err != nil {
 return err
 }
 fmt.Printf("%+v", x)
 return nil
 }
 
 | 
因为没找到直接操作图片Exif的库(如果有欢迎留言告诉我),只能通过解析图片的色彩空间,然后通过此色彩空间重新生成一张新的图片因为是重新生成的图片,也就相当于抹除了Exif信息
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 
 | func CreateNewImage(f, newF *os.File) error {m, _, err := image.Decode(f)
 if err != nil {
 return err
 }
 
 width, height := m.Bounds().Max.X, m.Bounds().Max.Y
 var subImage image.Image
 img := m.(*image.YCbCr)
 subImage = img.SubImage(image.Rect(0, 0, width, height)).(*image.YCbCr)
 err = jpeg.Encode(newF, subImage, &jpeg.Options{100})
 return err
 }
 
 | 
所有代码:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 
 | package main
 import (
 "fmt"
 "image"
 _ "image/gif"
 "image/jpeg"
 _ "image/jpeg"
 _ "image/png"
 "os"
 "path"
 "strings"
 
 "github.com/rwcarlsen/goexif/exif"
 )
 
 func main() {
 ImgFile := "./IMG_20210125_191526.jpg"
 fileNameWithSuffix := path.Base(ImgFile)
 imgType := path.Ext(fileNameWithSuffix)
 fileNameOnly := strings.TrimSuffix(fileNameWithSuffix, imgType)
 newImageFile := fileNameOnly + "_no_exif" + imgType
 file, err := os.Open(ImgFile)
 if err != nil {
 fmt.Println("打开文件失败")
 return
 }
 defer file.Close()
 err = GetExif(file)
 if err != nil {
 panic(err)
 }
 
 file.Seek(0, 0)
 newFile, err := os.Create(newImageFile)
 if err != nil {
 fmt.Println("file create fail")
 panic(err)
 }
 defer newFile.Close()
 err = CreateNewImage(file, newFile)
 if err != nil {
 panic(err)
 }
 }
 
 func GetExif(file *os.File) error {
 x, err := exif.Decode(file)
 if err != nil {
 return err
 }
 fmt.Printf("%+v", x)
 
 return nil
 }
 
 func CreateNewImage(f, newF *os.File) error {
 m, _, err := image.Decode(f)
 if err != nil {
 return err
 }
 
 width, height := m.Bounds().Max.X, m.Bounds().Max.Y
 var subImage image.Image
 img := m.(*image.YCbCr)
 subImage = img.SubImage(image.Rect(0, 0, width, height)).(*image.YCbCr)
 err = jpeg.Encode(newF, subImage, &jpeg.Options{100})
 return err
 }
 
 func Create(fileName string) (*os.File, error) {
 f, err := os.Create(fileName)
 if err != nil {
 fmt.Println("file create fail")
 return nil, err
 }
 return f, nil
 }
 
 |