gravity.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. package processing
  2. import (
  3. "github.com/imgproxy/imgproxy/v3/options"
  4. "github.com/imgproxy/imgproxy/v3/options/keys"
  5. )
  6. var gravityTypesRotationMap = map[int]map[GravityType]GravityType{
  7. 90: {
  8. GravityNorth: GravityWest,
  9. GravityEast: GravityNorth,
  10. GravitySouth: GravityEast,
  11. GravityWest: GravitySouth,
  12. GravityNorthWest: GravitySouthWest,
  13. GravityNorthEast: GravityNorthWest,
  14. GravitySouthWest: GravitySouthEast,
  15. GravitySouthEast: GravityNorthEast,
  16. },
  17. 180: {
  18. GravityNorth: GravitySouth,
  19. GravityEast: GravityWest,
  20. GravitySouth: GravityNorth,
  21. GravityWest: GravityEast,
  22. GravityNorthWest: GravitySouthEast,
  23. GravityNorthEast: GravitySouthWest,
  24. GravitySouthWest: GravityNorthEast,
  25. GravitySouthEast: GravityNorthWest,
  26. },
  27. 270: {
  28. GravityNorth: GravityEast,
  29. GravityEast: GravitySouth,
  30. GravitySouth: GravityWest,
  31. GravityWest: GravityNorth,
  32. GravityNorthWest: GravityNorthEast,
  33. GravityNorthEast: GravitySouthEast,
  34. GravitySouthWest: GravityNorthWest,
  35. GravitySouthEast: GravitySouthWest,
  36. },
  37. }
  38. var gravityTypesFlipMap = map[GravityType]GravityType{
  39. GravityEast: GravityWest,
  40. GravityWest: GravityEast,
  41. GravityNorthWest: GravityNorthEast,
  42. GravityNorthEast: GravityNorthWest,
  43. GravitySouthWest: GravitySouthEast,
  44. GravitySouthEast: GravitySouthWest,
  45. }
  46. type GravityOptions struct {
  47. Type GravityType
  48. X, Y float64
  49. }
  50. // NewGravityOptions builds a new [GravityOptions] instance.
  51. // It fills the [GravityOptions] struct with the options values under the given prefix.
  52. // If the gravity type is not set in the options,
  53. // it returns a [GravityOptions] with the provided default type.
  54. func NewGravityOptions(o *options.Options, prefix string, defType GravityType) GravityOptions {
  55. gr := GravityOptions{
  56. Type: options.Get(o, prefix+keys.SuffixType, defType),
  57. X: o.GetFloat(prefix+keys.SuffixXOffset, 0.0),
  58. Y: o.GetFloat(prefix+keys.SuffixYOffset, 0.0),
  59. }
  60. return gr
  61. }
  62. func (g *GravityOptions) RotateAndFlip(angle int, flip bool) {
  63. angle %= 360
  64. if flip {
  65. if gt, ok := gravityTypesFlipMap[g.Type]; ok {
  66. g.Type = gt
  67. }
  68. switch g.Type {
  69. case GravityCenter, GravityNorth, GravitySouth:
  70. g.X = -g.X
  71. case GravityFocusPoint:
  72. g.X = 1.0 - g.X
  73. }
  74. }
  75. if angle > 0 {
  76. if rotMap := gravityTypesRotationMap[angle]; rotMap != nil {
  77. if gt, ok := rotMap[g.Type]; ok {
  78. g.Type = gt
  79. }
  80. switch angle {
  81. case 90:
  82. switch g.Type {
  83. case GravityCenter, GravityEast, GravityWest:
  84. g.X, g.Y = g.Y, -g.X
  85. case GravityFocusPoint:
  86. g.X, g.Y = g.Y, 1.0-g.X
  87. default:
  88. g.X, g.Y = g.Y, g.X
  89. }
  90. case 180:
  91. switch g.Type {
  92. case GravityCenter:
  93. g.X, g.Y = -g.X, -g.Y
  94. case GravityNorth, GravitySouth:
  95. g.X = -g.X
  96. case GravityEast, GravityWest:
  97. g.Y = -g.Y
  98. case GravityFocusPoint:
  99. g.X, g.Y = 1.0-g.X, 1.0-g.Y
  100. }
  101. case 270:
  102. switch g.Type {
  103. case GravityCenter, GravityNorth, GravitySouth:
  104. g.X, g.Y = -g.Y, g.X
  105. case GravityFocusPoint:
  106. g.X, g.Y = 1.0-g.Y, g.X
  107. default:
  108. g.X, g.Y = g.Y, g.X
  109. }
  110. }
  111. }
  112. }
  113. }