被分到了云平台方向,正好是leader的负责部分,所以就是他来带我,瑟瑟发抖。昨天他让我熟悉了一下go语言,今天上午上班后就来找到我,给我布置了一下这几天的任务。由于我们所有方向做图像处理都比较多,所以要熟悉go中的image库,之前水神他们上线的项目用的是imagemagick库来处理图片,现在我们打算换成用libjpeg-turbo来进行图像处理,据说这样的效率是使用imagemagick的3倍,leader需要我学习一下这三种处理方式,分别完成图像的缩放和裁剪功能,并且对比一下这三种的效率,方便日后将libjpeg-turbo库封装成go可以使用的库然后上线,再之后去学习一下gpu编程,提高图像处理效率。
内容很多,所以先完成一下对go自带的image库的学习,在网上找了个大神的代码进行学习,初步掌握了使用go中image库对图片的处理,以图片缩放为例:
1 package main 2 3 import ( 4 "strings" 5 "io" 6 "os" 7 "fmt" 8 "log" 9 "image" 10 "image/png" 11 "image/jpeg" 12 "github.com/nfnt/resize" 13 ) 14 15 var imagePath string = "/Users/zhanghaoran/Desktop/test.png" 16 var imageOutputPath string = "/Users/zhanghaoran/Desktop/test_compress.png" 17 18 func getImfomation() string { 19 tmp := strings.Split(imagePath, ".") 20 if len(tmp) != 2 { 21 return "" 22 } else { 23 return tmp[1] 24 } 25 } 26 27 func getCompressImage(getReadSizeFile func() (io.Reader, error), getDecodeFile func() (*os.File, error), to string, quality, base int, format string) bool { 28 file_origin, error := getDecodeFile() 29 defer file_origin.Close() 30 if error != nil { 31 fmt.Println("Open File Error") 32 log.Fatal(error) 33 return false 34 } 35 var origin image.Image 36 var config image.Config 37 var tmp io.Reader 38 var imagetype int 39 tmp, error = getReadSizeFile() 40 if error != nil { 41 fmt.Println("Get Size Error") 42 log.Fatal(error) 43 return false 44 } 45 format = strings.ToLower(format) 46 if format == "png" { 47 imagetype = 1 48 origin, error = png.Decode(file_origin) 49 if error != nil { 50 fmt.Println("Decode Image Error") 51 log.Fatal(error) 52 return false 53 } 54 tmp, error = getReadSizeFile() 55 if error != nil { 56 fmt.Println("Get Size Error") 57 log.Fatal(error) 58 return false 59 } 60 config, error = png.DecodeConfig(tmp) 61 if error != nil { 62 fmt.Println("Get Config Error") 63 log.Fatal(error) 64 return false 65 } 66 } else if format == "jpg" || format == "jpeg" { 67 imagetype = 0 68 origin, error = jpeg.Decode(file_origin) 69 if error != nil { 70 fmt.Println("Decode Image Error") 71 log.Fatal(error) 72 return false 73 } 74 tmp, error = getReadSizeFile() 75 if error != nil { 76 fmt.Println("Get Size Error") 77 log.Fatal(error) 78 return false 79 } 80 config, error = jpeg.DecodeConfig(tmp) 81 if error != nil { 82 fmt.Println("Get Config Error") 83 log.Fatal(error) 84 return false 85 } 86 } 87 88 width := uint(base) 89 height := uint(base * config.Height / config.Width) 90 91 canvas := resize.Thumbnail(width, height, origin, resize.Lanczos3) 92 file_out, error := os.Create(to) 93 defer file_out.Close() 94 if error != nil { 95 fmt.Println("Create File_out Error") 96 return false 97 } 98 if imagetype == 0 { 99 error = jpeg.Encode(file_out, canvas, &jpeg.Options{quality}) 100 if error != nil { 101 fmt.Println("Encode Failed") 102 return false 103 } 104 } else { 105 error = png.Encode(file_out, canvas) 106 if error != nil { 107 fmt.Println("Encode Failed") 108 return false 109 } 110 } 111 112 return true 113 } 114 115 func main() { 116 tail := getImfomation() 117 //fmt.Println(tail) 118 if !getCompressImage(func() (io.Reader, error){ return os.Open(imagePath) }, func() (*os.File, error) { return os.Open(imagePath)}, imageOutputPath, 100, 1000, tail) { 119 fmt.Println("Failed") 120 } else { 121 fmt.Println("Sucessed") 122 } 123 }
这个小Demo可以完成将图片按照设定好的比例和大小进行压缩,比如我们常用的缩略图就是这样完成的。其余两种库还有待学习。