DarthSim пре 6 година
родитељ
комит
8c4a561b9e
3 измењених фајлова са 60 додато и 14 уклоњено
  1. 15 7
      process.go
  2. 30 7
      processing_options.go
  3. 15 0
      utils.go

+ 15 - 7
process.go

@@ -91,7 +91,7 @@ func shutdownVips() {
 }
 
 func randomAccessRequired(po processingOptions) int {
-	if po.Gravity == gravitySmart {
+	if po.Gravity.Type == gravitySmart {
 		return 1
 	}
 	return 0
@@ -184,22 +184,30 @@ func calcCrop(width, height int, po processingOptions) (left, top int) {
 	left = (width - po.Width + 1) / 2
 	top = (height - po.Height + 1) / 2
 
-	if po.Gravity == gravityNorth {
+	if po.Gravity.Type == gravityNorth {
 		top = 0
 	}
 
-	if po.Gravity == gravityEast {
+	if po.Gravity.Type == gravityEast {
 		left = width - po.Width
 	}
 
-	if po.Gravity == gravitySouth {
+	if po.Gravity.Type == gravitySouth {
 		top = height - po.Height
 	}
 
-	if po.Gravity == gravityWest {
+	if po.Gravity.Type == gravityWest {
 		left = 0
 	}
 
+	if po.Gravity.Type == gravityFocusPoint {
+		pointX := int(math.Round(float64(width) * po.Gravity.X))
+		pointY := int(math.Round(float64(height) * po.Gravity.Y))
+
+		left = maxInt(0, minInt(pointX-po.Width/2, width-po.Width))
+		top = maxInt(0, minInt(pointY-po.Height/2, height-po.Height))
+	}
+
 	return
 }
 
@@ -207,7 +215,7 @@ func processImage(data []byte, imgtype imageType, po processingOptions, t *timer
 	defer C.vips_cleanup()
 	defer runtime.KeepAlive(data)
 
-	if po.Gravity == gravitySmart && !vipsSupportSmartcrop {
+	if po.Gravity.Type == gravitySmart && !vipsSupportSmartcrop {
 		return nil, errors.New("Smart crop is not supported by used version of libvips")
 	}
 
@@ -311,7 +319,7 @@ func processImage(data []byte, imgtype imageType, po processingOptions, t *timer
 	}
 
 	if needToCrop(imgWidth, imgHeight, po) {
-		if po.Gravity == gravitySmart {
+		if po.Gravity.Type == gravitySmart {
 			if err = vipsImageCopyMemory(&img); err != nil {
 				return nil, err
 			}

+ 30 - 7
processing_options.go

@@ -44,6 +44,7 @@ const (
 	gravitySouth
 	gravityWest
 	gravitySmart
+	gravityFocusPoint
 )
 
 var gravityTypes = map[string]gravityType{
@@ -53,6 +54,12 @@ var gravityTypes = map[string]gravityType{
 	"so": gravitySouth,
 	"we": gravityWest,
 	"sm": gravitySmart,
+	"fp": gravityFocusPoint,
+}
+
+type gravity struct {
+	Type gravityType
+	X, Y float64
 }
 
 type resizeType int
@@ -73,7 +80,7 @@ type processingOptions struct {
 	Resize  resizeType
 	Width   int
 	Height  int
-	Gravity gravityType
+	Gravity gravity
 	Enlarge bool
 	Format  imageType
 	Blur    float32
@@ -190,16 +197,32 @@ func applyResizeOption(po *processingOptions, args []string) error {
 }
 
 func applyGravityOption(po *processingOptions, args []string) error {
-	if len(args) > 1 {
-		return fmt.Errorf("Invalid resize arguments: %v", args)
-	}
-
 	if g, ok := gravityTypes[args[0]]; ok {
-		po.Gravity = g
+		po.Gravity.Type = g
 	} else {
 		return fmt.Errorf("Invalid gravity: %s", args[0])
 	}
 
+	if po.Gravity.Type == gravityFocusPoint {
+		if len(args) != 3 {
+			return fmt.Errorf("Invalid gravity arguments: %v", args)
+		}
+
+		if x, err := strconv.ParseFloat(args[1], 64); err == nil && x >= 0 && x <= 1 {
+			po.Gravity.X = x
+		} else {
+			return fmt.Errorf("Invalid gravity X: %s", args[1])
+		}
+
+		if y, err := strconv.ParseFloat(args[2], 64); err == nil && y >= 0 && y <= 1 {
+			po.Gravity.Y = y
+		} else {
+			return fmt.Errorf("Invalid gravity Y: %s", args[2])
+		}
+	} else if len(args) > 1 {
+		return fmt.Errorf("Invalid gravity arguments: %v", args)
+	}
+
 	return nil
 }
 
@@ -333,7 +356,7 @@ func defaultProcessingOptions() (processingOptions, error) {
 		Resize:  resizeFit,
 		Width:   0,
 		Height:  0,
-		Gravity: gravityCenter,
+		Gravity: gravity{Type: gravityCenter},
 		Enlarge: false,
 		Format:  imageTypeJPEG,
 		Blur:    0,

+ 15 - 0
utils.go

@@ -0,0 +1,15 @@
+package main
+
+func maxInt(a, b int) int {
+	if a > b {
+		return a
+	}
+	return b
+}
+
+func minInt(a, b int) int {
+	if a < b {
+		return a
+	}
+	return b
+}