Browse Source

Refactor gravity a bit

DarthSim 5 months ago
parent
commit
e7e7a43bb6

+ 34 - 13
options/gravity_options.go

@@ -39,6 +39,40 @@ var gravityTypes = map[string]GravityType{
 	"re":   GravityReplicate,
 }
 
+var commonGravityTypes = []GravityType{
+	GravityCenter,
+	GravityNorth,
+	GravityEast,
+	GravitySouth,
+	GravityWest,
+	GravityNorthWest,
+	GravityNorthEast,
+	GravitySouthWest,
+	GravitySouthEast,
+}
+
+var cropGravityTypes = append(
+	[]GravityType{
+		GravitySmart,
+		GravityFocusPoint,
+	},
+	commonGravityTypes...,
+)
+
+var extendGravityTypes = append(
+	[]GravityType{
+		GravityFocusPoint,
+	},
+	commonGravityTypes...,
+)
+
+var watermarkGravityTypes = append(
+	[]GravityType{
+		GravityReplicate,
+	},
+	commonGravityTypes...,
+)
+
 var gravityTypesRotationMap = map[int]map[GravityType]GravityType{
 	90: {
 		GravityNorth:     GravityWest,
@@ -99,19 +133,6 @@ func (gt GravityType) MarshalJSON() ([]byte, error) {
 	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

+ 15 - 26
options/processing_options.go

@@ -54,14 +54,14 @@ type TrimOptions struct {
 }
 
 type WatermarkOptions struct {
-	Enabled bool
-	Opacity float64
-	Gravity GravityOptions
-	Scale   float64
+	Enabled  bool
+	Opacity  float64
+	Position GravityOptions
+	Scale    float64
 }
 
 func (wo WatermarkOptions) ShouldReplicate() bool {
-	return wo.Gravity.Type == GravityReplicate
+	return wo.Position.Type == GravityReplicate
 }
 
 type ProcessingOptions struct {
@@ -142,7 +142,7 @@ func NewProcessingOptions() *ProcessingOptions {
 		Blur:              0,
 		Sharpen:           0,
 		Dpr:               1,
-		Watermark:         WatermarkOptions{Opacity: 1, Gravity: GravityOptions{Type: GravityCenter}},
+		Watermark:         WatermarkOptions{Opacity: 1, Position: GravityOptions{Type: GravityCenter}},
 		StripMetadata:     config.StripMetadata,
 		KeepCopyright:     config.KeepCopyright,
 		StripColorProfile: config.StripColorProfile,
@@ -217,14 +217,14 @@ func isGravityOffcetValid(gravity GravityType, offset float64) bool {
 	return gravity != GravityFocusPoint || (offset >= 0 && offset <= 1)
 }
 
-func parseGravity(g *GravityOptions, args []string) error {
+func parseGravity(g *GravityOptions, args []string, allowedTypes []GravityType) error {
 	nArgs := len(args)
 
 	if nArgs > 3 {
 		return fmt.Errorf("Invalid gravity arguments: %v", args)
 	}
 
-	if t, ok := gravityTypes[args[0]]; ok {
+	if t, ok := gravityTypes[args[0]]; ok && slices.Contains(allowedTypes, t) {
 		g.Type = t
 	} else {
 		return fmt.Errorf("Invalid gravity: %s", args[0])
@@ -263,13 +263,9 @@ func parseExtend(opts *ExtendOptions, name string, args []string) error {
 	opts.Enabled = parseBoolOption(args[0])
 
 	if len(args) > 1 {
-		if err := parseGravity(&opts.Gravity, args[1:]); err != nil {
+		if err := parseGravity(&opts.Gravity, args[1:], extendGravityTypes); err != nil {
 			return err
 		}
-
-		if !opts.Gravity.Type.OkForExtend() {
-			return fmt.Errorf("%s doesn't support %s gravity", name, opts.Gravity.Type)
-		}
 	}
 
 	return nil
@@ -431,14 +427,10 @@ func applyDprOption(po *ProcessingOptions, args []string) error {
 }
 
 func applyGravityOption(po *ProcessingOptions, args []string) error {
-	if err := parseGravity(&po.Gravity, args); err != nil {
+	if err := parseGravity(&po.Gravity, args, cropGravityTypes); err != nil {
 		return err
 	}
 
-	if !po.Gravity.Type.OkForCrop() {
-		return fmt.Errorf("%s gravity type is not applicable to gravity", po.Gravity.Type)
-	}
-
 	return nil
 }
 
@@ -462,12 +454,9 @@ func applyCropOption(po *ProcessingOptions, args []string) error {
 	}
 
 	if len(args) > 2 {
-		if err := parseGravity(&po.Crop.Gravity, args[2:]); err != nil {
+		if err := parseGravity(&po.Crop.Gravity, args[2:], cropGravityTypes); err != nil {
 			return err
 		}
-		if !po.Crop.Gravity.Type.OkForCrop() {
-			return fmt.Errorf("%s gravity type is not applicable to crop", po.Crop.Gravity.Type)
-		}
 	}
 
 	return nil
@@ -731,8 +720,8 @@ func applyWatermarkOption(po *ProcessingOptions, args []string) error {
 	}
 
 	if len(args) > 1 && len(args[1]) > 0 {
-		if g, ok := gravityTypes[args[1]]; ok && g.OkForWatermark() {
-			po.Watermark.Gravity.Type = g
+		if g, ok := gravityTypes[args[1]]; ok && slices.Contains(watermarkGravityTypes, g) {
+			po.Watermark.Position.Type = g
 		} else {
 			return fmt.Errorf("Invalid watermark position: %s", args[1])
 		}
@@ -740,7 +729,7 @@ func applyWatermarkOption(po *ProcessingOptions, args []string) error {
 
 	if len(args) > 2 && len(args[2]) > 0 {
 		if x, err := strconv.ParseFloat(args[2], 64); err == nil {
-			po.Watermark.Gravity.X = x
+			po.Watermark.Position.X = x
 		} else {
 			return fmt.Errorf("Invalid watermark X offset: %s", args[2])
 		}
@@ -748,7 +737,7 @@ func applyWatermarkOption(po *ProcessingOptions, args []string) error {
 
 	if len(args) > 3 && len(args[3]) > 0 {
 		if y, err := strconv.ParseFloat(args[3], 64); err == nil {
-			po.Watermark.Gravity.Y = y
+			po.Watermark.Position.Y = y
 		} else {
 			return fmt.Errorf("Invalid watermark Y offset: %s", args[3])
 		}

+ 3 - 3
options/processing_options_test.go

@@ -397,9 +397,9 @@ func (s *ProcessingOptionsTestSuite) TestParsePathWatermark() {
 	s.Require().NoError(err)
 
 	s.Require().True(po.Watermark.Enabled)
-	s.Require().Equal(GravitySouthEast, po.Watermark.Gravity.Type)
-	s.Require().InDelta(10.0, po.Watermark.Gravity.X, 0.0001)
-	s.Require().InDelta(20.0, po.Watermark.Gravity.Y, 0.0001)
+	s.Require().Equal(GravitySouthEast, po.Watermark.Position.Type)
+	s.Require().InDelta(10.0, po.Watermark.Position.X, 0.0001)
+	s.Require().InDelta(20.0, po.Watermark.Position.Y, 0.0001)
 	s.Require().InDelta(0.6, po.Watermark.Scale, 0.0001)
 }
 

+ 7 - 7
processing/watermark.go

@@ -39,16 +39,16 @@ func prepareWatermark(wm *vips.Image, wmData *imagedata.ImageData, opts *options
 	if opts.ShouldReplicate() {
 		var offX, offY int
 
-		if math.Abs(opts.Gravity.X) >= 1.0 {
-			offX = imath.RoundToEven(opts.Gravity.X * offsetScale)
+		if math.Abs(opts.Position.X) >= 1.0 {
+			offX = imath.RoundToEven(opts.Position.X * offsetScale)
 		} else {
-			offX = imath.ScaleToEven(imgWidth, opts.Gravity.X)
+			offX = imath.ScaleToEven(imgWidth, opts.Position.X)
 		}
 
-		if math.Abs(opts.Gravity.Y) >= 1.0 {
-			offY = imath.RoundToEven(opts.Gravity.Y * offsetScale)
+		if math.Abs(opts.Position.Y) >= 1.0 {
+			offY = imath.RoundToEven(opts.Position.Y * offsetScale)
 		} else {
-			offY = imath.ScaleToEven(imgHeight, opts.Gravity.Y)
+			offY = imath.ScaleToEven(imgHeight, opts.Position.Y)
 		}
 
 		po.Padding.Enabled = true
@@ -124,7 +124,7 @@ func applyWatermark(img *vips.Image, wmData *imagedata.ImageData, opts *options.
 	wmHeight := wm.Height()
 
 	if !opts.ShouldReplicate() {
-		left, top = calcPosition(width, frameHeight, wmWidth, wmHeight, &opts.Gravity, offsetScale, true)
+		left, top = calcPosition(width, frameHeight, wmWidth, wmHeight, &opts.Position, offsetScale, true)
 	}
 
 	if left >= width || top >= height || -left >= wmWidth || -top >= wmHeight {