浏览代码

Replace WatermarkOptions.Gravity with GravityReplicate

DarthSim 1 年之前
父节点
当前提交
df75177481
共有 4 个文件被更改,包括 104 次插入19 次删除
  1. 17 0
      options/gravity_options.go
  2. 27 13
      options/processing_options.go
  3. 55 1
      options/processing_options_test.go
  4. 5 5
      processing/watermark.go

+ 17 - 0
options/gravity_options.go

@@ -19,6 +19,9 @@ const (
 	GravitySouthEast
 	GravitySmart
 	GravityFocusPoint
+
+	// Watermark gravity types
+	GravityReplicate
 )
 
 var gravityTypes = map[string]GravityType{
@@ -33,6 +36,7 @@ var gravityTypes = map[string]GravityType{
 	"soea": GravitySouthEast,
 	"sm":   GravitySmart,
 	"fp":   GravityFocusPoint,
+	"re":   GravityReplicate,
 }
 
 var gravityTypesRotationMap = map[int]map[GravityType]GravityType{
@@ -95,6 +99,19 @@ 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

+ 27 - 13
options/processing_options.go

@@ -54,11 +54,14 @@ type TrimOptions struct {
 }
 
 type WatermarkOptions struct {
-	Enabled   bool
-	Opacity   float64
-	Replicate bool
-	Gravity   GravityOptions
-	Scale     float64
+	Enabled bool
+	Opacity float64
+	Gravity GravityOptions
+	Scale   float64
+}
+
+func (wo WatermarkOptions) ShouldReplicate() bool {
+	return wo.Gravity.Type == GravityReplicate
 }
 
 type ProcessingOptions struct {
@@ -139,7 +142,7 @@ func NewProcessingOptions() *ProcessingOptions {
 		Blur:              0,
 		Sharpen:           0,
 		Dpr:               1,
-		Watermark:         WatermarkOptions{Opacity: 1, Replicate: false, Gravity: GravityOptions{Type: GravityCenter}},
+		Watermark:         WatermarkOptions{Opacity: 1, Gravity: GravityOptions{Type: GravityCenter}},
 		StripMetadata:     config.StripMetadata,
 		KeepCopyright:     config.KeepCopyright,
 		StripColorProfile: config.StripColorProfile,
@@ -264,8 +267,8 @@ func parseExtend(opts *ExtendOptions, name string, args []string) error {
 			return err
 		}
 
-		if opts.Gravity.Type == GravitySmart {
-			return fmt.Errorf("%s doesn't support smart gravity", name)
+		if !opts.Gravity.Type.OkForExtend() {
+			return fmt.Errorf("%s doesn't support %s gravity", name, opts.Gravity.Type)
 		}
 	}
 
@@ -428,7 +431,15 @@ func applyDprOption(po *ProcessingOptions, args []string) error {
 }
 
 func applyGravityOption(po *ProcessingOptions, args []string) error {
-	return parseGravity(&po.Gravity, args)
+	if err := parseGravity(&po.Gravity, args); 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
 }
 
 func applyCropOption(po *ProcessingOptions, args []string) error {
@@ -451,7 +462,12 @@ func applyCropOption(po *ProcessingOptions, args []string) error {
 	}
 
 	if len(args) > 2 {
-		return parseGravity(&po.Crop.Gravity, args[2:])
+		if err := parseGravity(&po.Crop.Gravity, args[2:]); 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
@@ -715,9 +731,7 @@ func applyWatermarkOption(po *ProcessingOptions, args []string) error {
 	}
 
 	if len(args) > 1 && len(args[1]) > 0 {
-		if args[1] == "re" {
-			po.Watermark.Replicate = true
-		} else if g, ok := gravityTypes[args[1]]; ok && g != GravityFocusPoint && g != GravitySmart {
+		if g, ok := gravityTypes[args[1]]; ok && g.OkForWatermark() {
 			po.Watermark.Gravity.Type = g
 		} else {
 			return fmt.Errorf("Invalid watermark position: %s", args[1])

+ 55 - 1
options/processing_options_test.go

@@ -236,6 +236,20 @@ func (s *ProcessingOptionsTestSuite) TestParsePathExtend() {
 	s.Require().InDelta(20.0, po.Extend.Gravity.Y, 0.0001)
 }
 
+func (s *ProcessingOptionsTestSuite) TestParsePathExtendSmartGravity() {
+	path := "/extend:1:sm/plain/http://images.dev/lorem/ipsum.jpg"
+	_, _, err := ParsePath(path, make(http.Header))
+
+	s.Require().Error(err)
+}
+
+func (s *ProcessingOptionsTestSuite) TestParsePathExtendReplicateGravity() {
+	path := "/extend:1:re/plain/http://images.dev/lorem/ipsum.jpg"
+	_, _, err := ParsePath(path, make(http.Header))
+
+	s.Require().Error(err)
+}
+
 func (s *ProcessingOptionsTestSuite) TestParsePathGravity() {
 	path := "/gravity:soea/plain/http://images.dev/lorem/ipsum.jpg"
 	po, _, err := ParsePath(path, make(http.Header))
@@ -245,7 +259,7 @@ func (s *ProcessingOptionsTestSuite) TestParsePathGravity() {
 	s.Require().Equal(GravitySouthEast, po.Gravity.Type)
 }
 
-func (s *ProcessingOptionsTestSuite) TestParsePathGravityFocuspoint() {
+func (s *ProcessingOptionsTestSuite) TestParsePathGravityFocusPoint() {
 	path := "/gravity:fp:0.5:0.75/plain/http://images.dev/lorem/ipsum.jpg"
 	po, _, err := ParsePath(path, make(http.Header))
 
@@ -256,6 +270,46 @@ func (s *ProcessingOptionsTestSuite) TestParsePathGravityFocuspoint() {
 	s.Require().InDelta(0.75, po.Gravity.Y, 0.0001)
 }
 
+func (s *ProcessingOptionsTestSuite) TestParsePathGravityReplicate() {
+	path := "/gravity:re/plain/http://images.dev/lorem/ipsum.jpg"
+	_, _, err := ParsePath(path, make(http.Header))
+
+	s.Require().Error(err)
+}
+
+func (s *ProcessingOptionsTestSuite) TestParsePathCrop() {
+	path := "/crop:100:200/plain/http://images.dev/lorem/ipsum.jpg"
+	po, _, err := ParsePath(path, make(http.Header))
+
+	s.Require().NoError(err)
+
+	s.Require().InDelta(100.0, po.Crop.Width, 0.0001)
+	s.Require().InDelta(200.0, po.Crop.Height, 0.0001)
+	s.Require().Equal(GravityUnknown, po.Crop.Gravity.Type)
+	s.Require().InDelta(0.0, po.Crop.Gravity.X, 0.0001)
+	s.Require().InDelta(0.0, po.Crop.Gravity.Y, 0.0001)
+}
+
+func (s *ProcessingOptionsTestSuite) TestParsePathCropGravity() {
+	path := "/crop:100:200:nowe:10:20/plain/http://images.dev/lorem/ipsum.jpg"
+	po, _, err := ParsePath(path, make(http.Header))
+
+	s.Require().NoError(err)
+
+	s.Require().InDelta(100.0, po.Crop.Width, 0.0001)
+	s.Require().InDelta(200.0, po.Crop.Height, 0.0001)
+	s.Require().Equal(GravityNorthWest, po.Crop.Gravity.Type)
+	s.Require().InDelta(10.0, po.Crop.Gravity.X, 0.0001)
+	s.Require().InDelta(20.0, po.Crop.Gravity.Y, 0.0001)
+}
+
+func (s *ProcessingOptionsTestSuite) TestParsePathCropGravityReplicate() {
+	path := "/crop:100:200:re/plain/http://images.dev/lorem/ipsum.jpg"
+	_, _, err := ParsePath(path, make(http.Header))
+
+	s.Require().Error(err)
+}
+
 func (s *ProcessingOptionsTestSuite) TestParsePathQuality() {
 	path := "/quality:55/plain/http://images.dev/lorem/ipsum.jpg"
 	po, _, err := ParsePath(path, make(http.Header))

+ 5 - 5
processing/watermark.go

@@ -36,7 +36,7 @@ func prepareWatermark(wm *vips.Image, wmData *imagedata.ImageData, opts *options
 		po.Height = imath.Max(imath.ScaleToEven(imgHeight, opts.Scale), 1)
 	}
 
-	if opts.Replicate {
+	if opts.ShouldReplicate() {
 		var offX, offY int
 
 		if math.Abs(opts.Gravity.X) >= 1.0 {
@@ -62,7 +62,7 @@ func prepareWatermark(wm *vips.Image, wmData *imagedata.ImageData, opts *options
 		return err
 	}
 
-	if opts.Replicate || framesCount > 1 {
+	if opts.ShouldReplicate() || framesCount > 1 {
 		// We need to copy image if we're going to replicate.
 		// Replication requires image to be read several times, and this requires
 		// random access to pixels
@@ -71,7 +71,7 @@ func prepareWatermark(wm *vips.Image, wmData *imagedata.ImageData, opts *options
 		}
 	}
 
-	if opts.Replicate {
+	if opts.ShouldReplicate() {
 		if err := wm.Replicate(imgWidth, imgHeight); err != nil {
 			return err
 		}
@@ -111,7 +111,7 @@ func applyWatermark(img *vips.Image, wmData *imagedata.ImageData, opts *options.
 
 	// If we replicated the watermark and need to apply it to an animated image,
 	// it is faster to replicate the watermark to all the image and apply it single-pass
-	if opts.Replicate && framesCount > 1 {
+	if opts.ShouldReplicate() && framesCount > 1 {
 		if err := wm.Replicate(width, height); err != nil {
 			return err
 		}
@@ -121,7 +121,7 @@ func applyWatermark(img *vips.Image, wmData *imagedata.ImageData, opts *options.
 
 	left, top := 0, 0
 
-	if !opts.Replicate {
+	if !opts.ShouldReplicate() {
 		left, top = calcPosition(width, frameHeight, wm.Width(), wm.Height(), &opts.Gravity, offsetScale, true)
 	}