Files
imgproxy/options/gravity_options.go

176 lines
3.6 KiB
Go

package options
import (
"fmt"
)
type GravityType int
const (
GravityUnknown GravityType = iota
GravityCenter
GravityNorth
GravityEast
GravitySouth
GravityWest
GravityNorthWest
GravityNorthEast
GravitySouthWest
GravitySouthEast
GravitySmart
GravityFocusPoint
// Watermark gravity types
GravityReplicate
)
var gravityTypes = map[string]GravityType{
"ce": GravityCenter,
"no": GravityNorth,
"ea": GravityEast,
"so": GravitySouth,
"we": GravityWest,
"nowe": GravityNorthWest,
"noea": GravityNorthEast,
"sowe": GravitySouthWest,
"soea": GravitySouthEast,
"sm": GravitySmart,
"fp": GravityFocusPoint,
"re": GravityReplicate,
}
var gravityTypesRotationMap = map[int]map[GravityType]GravityType{
90: {
GravityNorth: GravityWest,
GravityEast: GravityNorth,
GravitySouth: GravityEast,
GravityWest: GravitySouth,
GravityNorthWest: GravitySouthWest,
GravityNorthEast: GravityNorthWest,
GravitySouthWest: GravitySouthEast,
GravitySouthEast: GravityNorthEast,
},
180: {
GravityNorth: GravitySouth,
GravityEast: GravityWest,
GravitySouth: GravityNorth,
GravityWest: GravityEast,
GravityNorthWest: GravitySouthEast,
GravityNorthEast: GravitySouthWest,
GravitySouthWest: GravityNorthEast,
GravitySouthEast: GravityNorthWest,
},
270: {
GravityNorth: GravityEast,
GravityEast: GravitySouth,
GravitySouth: GravityWest,
GravityWest: GravityNorth,
GravityNorthWest: GravityNorthEast,
GravityNorthEast: GravitySouthEast,
GravitySouthWest: GravityNorthWest,
GravitySouthEast: GravitySouthWest,
},
}
var gravityTypesFlipMap = map[GravityType]GravityType{
GravityEast: GravityWest,
GravityWest: GravityEast,
GravityNorthWest: GravityNorthEast,
GravityNorthEast: GravityNorthWest,
GravitySouthWest: GravitySouthEast,
GravitySouthEast: GravitySouthWest,
}
func (gt GravityType) String() string {
for k, v := range gravityTypes {
if v == gt {
return k
}
}
return ""
}
func (gt GravityType) MarshalJSON() ([]byte, error) {
for k, v := range gravityTypes {
if v == gt {
return []byte(fmt.Sprintf("%q", k)), nil
}
}
return []byte("null"), nil
}
func (gt GravityType) OkForCrop() bool {
return gt != GravityUnknown && gt != GravityReplicate
}
func (gt GravityType) OkForExtend() bool {
return gt.OkForCrop() && gt != GravitySmart
}
func (gt GravityType) OkForWatermark() bool {
return gt == GravityReplicate ||
(gt.OkForExtend() && gt != GravityFocusPoint)
}
type GravityOptions struct {
Type GravityType
X, Y float64
}
func (g *GravityOptions) RotateAndFlip(angle int, flip bool) {
angle %= 360
if flip {
if gt, ok := gravityTypesFlipMap[g.Type]; ok {
g.Type = gt
}
switch g.Type {
case GravityCenter, GravityNorth, GravitySouth:
g.X = -g.X
case GravityFocusPoint:
g.X = 1.0 - g.X
}
}
if angle > 0 {
if rotMap := gravityTypesRotationMap[angle]; rotMap != nil {
if gt, ok := rotMap[g.Type]; ok {
g.Type = gt
}
switch angle {
case 90:
switch g.Type {
case GravityCenter, GravityEast, GravityWest:
g.X, g.Y = g.Y, -g.X
case GravityFocusPoint:
g.X, g.Y = g.Y, 1.0-g.X
default:
g.X, g.Y = g.Y, g.X
}
case 180:
switch g.Type {
case GravityCenter:
g.X, g.Y = -g.X, -g.Y
case GravityNorth, GravitySouth:
g.X = -g.X
case GravityEast, GravityWest:
g.Y = -g.Y
case GravityFocusPoint:
g.X, g.Y = 1.0-g.X, 1.0-g.Y
}
case 270:
switch g.Type {
case GravityCenter, GravityNorth, GravitySouth:
g.X, g.Y = -g.Y, g.X
case GravityFocusPoint:
g.X, g.Y = 1.0-g.Y, g.X
default:
g.X, g.Y = g.Y, g.X
}
}
}
}
}