Browse Source

Background option

DarthSim 6 years ago
parent
commit
2840994719
3 changed files with 72 additions and 9 deletions
  1. 20 1
      process.go
  2. 44 8
      processing_options.go
  3. 8 0
      vips.h

+ 20 - 1
process.go

@@ -239,6 +239,8 @@ func processImage(data []byte, imgtype imageType, po processingOptions, t *timer
 		}
 	}
 
+	hasAlpha := vipsImageHasAlpha(img)
+
 	if needToScale(imgWidth, imgHeight, po) {
 		scale := calcScale(imgWidth, imgHeight, po)
 
@@ -259,7 +261,7 @@ func processImage(data []byte, imgtype imageType, po processingOptions, t *timer
 		premultiplied := false
 		var bandFormat C.VipsBandFormat
 
-		if vipsImageHasAlpha(img) {
+		if hasAlpha {
 			if bandFormat, err = vipsPremultiply(&img); err != nil {
 				return nil, err
 			}
@@ -336,6 +338,12 @@ func processImage(data []byte, imgtype imageType, po processingOptions, t *timer
 		t.Check()
 	}
 
+	if hasAlpha && po.Flatten {
+		if err = vipsFlatten(&img, po.Background); err != nil {
+			return nil, err
+		}
+	}
+
 	if po.Blur > 0 {
 		if err = vipsBlur(&img, po.Blur); err != nil {
 			return nil, err
@@ -472,6 +480,17 @@ func vipsSmartCrop(img **C.struct__VipsImage, width, height int) error {
 	return nil
 }
 
+func vipsFlatten(img **C.struct__VipsImage, bg color) error {
+	var tmp *C.struct__VipsImage
+
+	if C.vips_flatten_go(*img, &tmp, C.double(bg.R), C.double(bg.G), C.double(bg.B)) != 0 {
+		return vipsError()
+	}
+	C.swap_and_clear(img, tmp)
+
+	return nil
+}
+
 func vipsBlur(img **C.struct__VipsImage, sigma float32) error {
 	var tmp *C.struct__VipsImage
 

+ 44 - 8
processing_options.go

@@ -76,15 +76,19 @@ var resizeTypes = map[string]resizeType{
 	"crop": resizeCrop,
 }
 
+type color struct{ R, G, B uint8 }
+
 type processingOptions struct {
-	Resize  resizeType
-	Width   int
-	Height  int
-	Gravity gravity
-	Enlarge bool
-	Format  imageType
-	Blur    float32
-	Sharpen float32
+	Resize     resizeType
+	Width      int
+	Height     int
+	Gravity    gravity
+	Enlarge    bool
+	Format     imageType
+	Flatten    bool
+	Background color
+	Blur       float32
+	Sharpen    float32
 }
 
 func (it imageType) String() string {
@@ -249,6 +253,34 @@ func applyGravityOption(po *processingOptions, args []string) error {
 	return nil
 }
 
+func applyBackgroundOption(po *processingOptions, args []string) error {
+	if len(args) != 3 {
+		return fmt.Errorf("Invalid background arguments: %v", args)
+	}
+
+	if r, err := strconv.ParseUint(args[0], 10, 8); err == nil && r >= 0 && r <= 255 {
+		po.Background.R = uint8(r)
+	} else {
+		return fmt.Errorf("Invalid background red channel: %s", args[1])
+	}
+
+	if g, err := strconv.ParseUint(args[1], 10, 8); err == nil && g >= 0 && g <= 255 {
+		po.Background.G = uint8(g)
+	} else {
+		return fmt.Errorf("Invalid background green channel: %s", args[1])
+	}
+
+	if b, err := strconv.ParseUint(args[2], 10, 8); err == nil && b >= 0 && b <= 255 {
+		po.Background.B = uint8(b)
+	} else {
+		return fmt.Errorf("Invalid background blue channel: %s", args[2])
+	}
+
+	po.Flatten = true
+
+	return nil
+}
+
 func applyBlurOption(po *processingOptions, args []string) error {
 	if len(args) > 1 {
 		return fmt.Errorf("Invalid blur arguments: %v", args)
@@ -344,6 +376,10 @@ func applyProcessingOption(po *processingOptions, name string, args []string) er
 		if err := applyGravityOption(po, args); err != nil {
 			return err
 		}
+	case "background":
+		if err := applyBackgroundOption(po, args); err != nil {
+			return err
+		}
 	case "blur":
 		if err := applyBlurOption(po, args); err != nil {
 			return err

+ 8 - 0
vips.h

@@ -190,6 +190,14 @@ vips_sharpen_go(VipsImage *in, VipsImage **out, double sigma) {
   return vips_sharpen(in, out, "sigma", sigma, NULL);
 }
 
+int
+vips_flatten_go(VipsImage *in, VipsImage **out, double r, double g, double b) {
+  VipsArrayDouble *bg = vips_array_double_newv(3, r, g, b);
+  int res = vips_flatten(in, out, "background", bg, NULL);
+  vips_area_unref((VipsArea *)bg);
+  return res;
+}
+
 int
 vips_extract_area_go(VipsImage *in, VipsImage **out, int left, int top, int width, int height) {
   return vips_extract_area(in, out, left, top, width, height, NULL);