From e7e7a43bb625260ade4c81e700984415143dc89e Mon Sep 17 00:00:00 2001 From: DarthSim Date: Wed, 20 Nov 2024 19:42:55 +0300 Subject: [PATCH] Refactor gravity a bit --- options/gravity_options.go | 47 +++++++++++++++++++++--------- options/processing_options.go | 41 ++++++++++---------------- options/processing_options_test.go | 6 ++-- processing/watermark.go | 14 ++++----- 4 files changed, 59 insertions(+), 49 deletions(-) diff --git a/options/gravity_options.go b/options/gravity_options.go index f454d86e..7aaccd63 100644 --- a/options/gravity_options.go +++ b/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 diff --git a/options/processing_options.go b/options/processing_options.go index 71b4f8d8..c9f71e32 100644 --- a/options/processing_options.go +++ b/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]) } diff --git a/options/processing_options_test.go b/options/processing_options_test.go index dfdd7163..9a74c04a 100644 --- a/options/processing_options_test.go +++ b/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) } diff --git a/processing/watermark.go b/processing/watermark.go index dc12b780..0d51f04f 100644 --- a/processing/watermark.go +++ b/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 {