util.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. package gg
  2. import (
  3. "fmt"
  4. "image"
  5. "image/draw"
  6. "image/jpeg"
  7. _ "image/jpeg"
  8. "image/png"
  9. "io/ioutil"
  10. "math"
  11. "os"
  12. "strings"
  13. "github.com/golang/freetype/truetype"
  14. "golang.org/x/image/font"
  15. "golang.org/x/image/math/fixed"
  16. )
  17. func Radians(degrees float64) float64 {
  18. return degrees * math.Pi / 180
  19. }
  20. func Degrees(radians float64) float64 {
  21. return radians * 180 / math.Pi
  22. }
  23. func LoadImage(path string) (image.Image, error) {
  24. file, err := os.Open(path)
  25. if err != nil {
  26. return nil, err
  27. }
  28. defer file.Close()
  29. im, _, err := image.Decode(file)
  30. return im, err
  31. }
  32. func LoadPNG(path string) (image.Image, error) {
  33. file, err := os.Open(path)
  34. if err != nil {
  35. return nil, err
  36. }
  37. defer file.Close()
  38. return png.Decode(file)
  39. }
  40. func SavePNG(path string, im image.Image) error {
  41. file, err := os.Create(path)
  42. if err != nil {
  43. return err
  44. }
  45. defer file.Close()
  46. return png.Encode(file, im)
  47. }
  48. func LoadJPG(path string) (image.Image, error) {
  49. file, err := os.Open(path)
  50. if err != nil {
  51. return nil, err
  52. }
  53. defer file.Close()
  54. return jpeg.Decode(file)
  55. }
  56. func SaveJPG(path string, im image.Image, quality int) error {
  57. file, err := os.Create(path)
  58. if err != nil {
  59. return err
  60. }
  61. defer file.Close()
  62. var opt jpeg.Options
  63. opt.Quality = quality
  64. return jpeg.Encode(file, im, &opt)
  65. }
  66. func imageToRGBA(src image.Image) *image.RGBA {
  67. bounds := src.Bounds()
  68. dst := image.NewRGBA(bounds)
  69. draw.Draw(dst, bounds, src, bounds.Min, draw.Src)
  70. return dst
  71. }
  72. func parseHexColor(x string) (r, g, b, a int) {
  73. x = strings.TrimPrefix(x, "#")
  74. a = 255
  75. if len(x) == 3 {
  76. format := "%1x%1x%1x"
  77. fmt.Sscanf(x, format, &r, &g, &b)
  78. r |= r << 4
  79. g |= g << 4
  80. b |= b << 4
  81. }
  82. if len(x) == 6 {
  83. format := "%02x%02x%02x"
  84. fmt.Sscanf(x, format, &r, &g, &b)
  85. }
  86. if len(x) == 8 {
  87. format := "%02x%02x%02x%02x"
  88. fmt.Sscanf(x, format, &r, &g, &b, &a)
  89. }
  90. return
  91. }
  92. func fixp(x, y float64) fixed.Point26_6 {
  93. return fixed.Point26_6{fix(x), fix(y)}
  94. }
  95. func fix(x float64) fixed.Int26_6 {
  96. return fixed.Int26_6(x * 64)
  97. }
  98. func unfix(x fixed.Int26_6) float64 {
  99. const shift, mask = 6, 1<<6 - 1
  100. if x >= 0 {
  101. return float64(x>>shift) + float64(x&mask)/64
  102. }
  103. x = -x
  104. if x >= 0 {
  105. return -(float64(x>>shift) + float64(x&mask)/64)
  106. }
  107. return 0
  108. }
  109. // LoadFontFace is a helper function to load the specified font file with
  110. // the specified point size. Note that the returned `font.Face` objects
  111. // are not thread safe and cannot be used in parallel across goroutines.
  112. // You can usually just use the Context.LoadFontFace function instead of
  113. // this package-level function.
  114. func LoadFontFace(path string, points float64) (font.Face, error) {
  115. fontBytes, err := ioutil.ReadFile(path)
  116. if err != nil {
  117. return nil, err
  118. }
  119. f, err := truetype.Parse(fontBytes)
  120. if err != nil {
  121. return nil, err
  122. }
  123. face := truetype.NewFace(f, &truetype.Options{
  124. Size: points,
  125. // Hinting: font.HintingFull,
  126. })
  127. return face, nil
  128. }