Browse Source

AdjustSigmoid function added

disintegration 11 years ago
parent
commit
848fdcb93f
3 changed files with 66 additions and 8 deletions
  1. 11 3
      README.md
  2. 50 5
      adjust.go
  3. 5 0
      helpers.go

+ 11 - 3
README.md

@@ -124,7 +124,6 @@ dstImage = imaging.Sharpen(srcImage, 3.0)
 Gamma parameter must be positive. Gamma = 1.0 gives the original image.
 Gamma less than 1.0 darkens the image and gamma greater than 1.0 lightens it.
 
-
 ```go
 dstImage = imaging.AdjustGamma(srcImage, 0.7)
 ```
@@ -132,7 +131,6 @@ dstImage = imaging.AdjustGamma(srcImage, 0.7)
 **AdjustBrightness** changes the brightness of the image using the percentage parameter and returns the adjusted image. The percentage must be in range (-100, 100).
 The percentage = 0 gives the original image. The percentage = -100 gives solid black image. The percentage = 100 gives solid white image. 
 
-
 ```go
 dstImage = imaging.AdjustBrightness(srcImage, -15) // decrease image brightness by 15%
 dstImage = imaging.AdjustBrightness(srcImage, 10) // increase image brightness by 10%
@@ -141,12 +139,22 @@ dstImage = imaging.AdjustBrightness(srcImage, 10) // increase image brightness b
 **AdjustContrast** changes the contrast of the image using the percentage parameter and returns the adjusted image. The percentage must be in range (-100, 100).
 The percentage = 0 gives the original image. The percentage = -100 gives solid grey image.
 
-
 ```go
 dstImage = imaging.AdjustContrast(srcImage, -10) // decrease image contrast by 10%
 dstImage = imaging.AdjustContrast(srcImage, 20) // increase image contrast by 20%
 ```
 
+**AdjustSigmoid** changes the contrast of the image using a sigmoidal function and returns the adjusted image.
+It's a non-linear contrast change useful for photo adjustments as it preserves highlights and shadows details.
+The midpoint parameter is the midpoint of contrast that must be between 0 and 1, typically 0.5.
+The factor parameter indicates how much to increase or decrease the contrast, typically in range (-10, 10).
+If the factor parameter is positive the image contrast is increased otherwise the contrast is decreased.
+
+```go
+dstImage = imaging.AdjustSigmoid(srcImage, 0.5, 3.0) // increase the contrast
+dstImage = imaging.AdjustSigmoid(srcImage, 0.5, -3.0) // decrease the contrast
+```
+
 **Grayscale** produces grayscale version of the image.
 
 ```go

+ 50 - 5
adjust.go

@@ -36,11 +36,6 @@ func applyColorMapping(img image.Image, fn func(c color.NRGBA) color.NRGBA) *ima
 	return dst
 }
 
-// clamp & round float64 to uint8 (0..255)
-func clamp(v float64) uint8 {
-	return uint8(math.Min(math.Max(v, 0.0), 255.0) + 0.5)
-}
-
 // AdjustGamma performs a gamma correction on the image and returns the adjusted image.
 // Gamma parameter must be positive. Gamma = 1.0 gives the original image.
 // Gamma less than 1.0 darkens the image and gamma greater than 1.0 lightens it.
@@ -64,6 +59,56 @@ func AdjustGamma(img image.Image, gamma float64) *image.NRGBA {
 	return applyColorMapping(img, fn)
 }
 
+func sigmoid(a, b, x float64) float64 {
+	return 1 / (1 + math.Exp(b*(a-x)))
+}
+
+// AdjustSigmoid changes the contrast of the image using a sigmoidal function and returns the adjusted image.
+// It's a non-linear contrast change useful for photo adjustments as it preserves highlight and shadow detail.
+// The midpoint parameter is the midpoint of contrast that must be between 0 and 1, typically 0.5.
+// The factor parameter indicates how much to increase or decrease the contrast, typically in range (-10, 10).
+// If the factor parameter is positive the image contrast is increased otherwise the contrast is decreased.
+//
+// Examples:
+//
+//	dstImage = imaging.AdjustSigmoid(srcImage, 0.5, 3.0) // increase the contrast
+//	dstImage = imaging.AdjustSigmoid(srcImage, 0.5, -3.0) // decrease the contrast
+//
+func AdjustSigmoid(img image.Image, midpoint, factor float64) *image.NRGBA {
+	if factor == 0 {
+		return Clone(img)
+	}
+
+	lut := make([]uint8, 256)
+	a := math.Min(math.Max(midpoint, 0.0), 1.0)
+	b := math.Abs(factor)
+	sig0 := sigmoid(a, b, 0)
+	sig1 := sigmoid(a, b, 1)
+	e := 1.0e-6
+
+	if factor > 0 {
+		for i := 0; i < 256; i++ {
+			x := float64(i) / 255.0
+			sigX := sigmoid(a, b, x)
+			f := (sigX - sig0) / (sig1 - sig0)
+			lut[i] = clamp(f * 255.0)
+		}
+	} else {
+		for i := 0; i < 256; i++ {
+			x := float64(i) / 255.0
+			arg := math.Min(math.Max((sig1-sig0)*x+sig0, e), 1.0-e)
+			f := a - math.Log(1.0/arg-1.0)/b
+			lut[i] = clamp(f * 255.0)
+		}
+	}
+
+	fn := func(c color.NRGBA) color.NRGBA {
+		return color.NRGBA{lut[c.R], lut[c.G], lut[c.B], c.A}
+	}
+
+	return applyColorMapping(img, fn)
+}
+
 // AdjustContrast changes the contrast of the image using the percentage parameter and returns the adjusted image.
 // The percentage must be in range (-100, 100). The percentage = 0 gives the original image.
 // The percentage = -100 gives solid grey image.

+ 5 - 0
helpers.go

@@ -105,3 +105,8 @@ func toNRGBA(img image.Image) *image.NRGBA {
 	}
 	return Clone(img)
 }
+
+// clamp & round float64 to uint8 (0..255)
+func clamp(v float64) uint8 {
+	return uint8(math.Min(math.Max(v, 0.0), 255.0) + 0.5)
+}