Exemple #1
0
// UnsharpMask sharpens the given Image using the unsharp mask technique.
// Basically the image is blurred, then subtracted from the original for
// differences above the threshold value.
func UnsharpMask(in image.Image, radius int, sigma, amount, threshold float64) image.Image {
	blurred := blur.Gaussian(in, radius, sigma, blur.IGNORE)
	bounds := in.Bounds()
	out := image.NewRGBA(bounds)

	// Absolute difference between a and b, returns float64 between 0 and 1.
	diff := func(a, b float64) float64 {
		if a > b {
			return a - b
		}
		return b - a
	}

	for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
		for x := bounds.Min.X; x < bounds.Max.X; x++ {
			ar, ag, ab, aa := utils.RatioRGBA(in.At(x, y))
			br, bg, bb, _ := utils.RatioRGBA(blurred.At(x, y))

			if diff(ar, br) >= threshold {
				ar = amount*(ar-br) + ar
			}

			if diff(ag, bg) >= threshold {
				ag = amount*(ag-bg) + ag
			}

			if diff(ab, bb) >= threshold {
				ab = amount*(ab-bb) + ab
			}

			out.Set(x, y, color.NRGBA{
				uint8(utils.Truncatef(ar * 255)),
				uint8(utils.Truncatef(ag * 255)),
				uint8(utils.Truncatef(ab * 255)),
				uint8(aa * 255),
			})
		}
	}

	return out
}
Exemple #2
0
func LinearC(value float64) utils.Composable {
	return func(c color.Color) color.Color {
		r, g, b, a := utils.RatioRGBA(c)

		r = utils.Truncatef((((r - 0.5) * value) + 0.5) * 255)
		g = utils.Truncatef((((g - 0.5) * value) + 0.5) * 255)
		b = utils.Truncatef((((b - 0.5) * value) + 0.5) * 255)
		a = a * 255

		return color.NRGBA{uint8(r), uint8(g), uint8(b), uint8(a)}
	}
}
Exemple #3
0
func SigmoidalC(factor, midpoint float64) utils.Composable {
	sigmoidal := func(x float64) float64 {
		return 1.0 / (1.0 + math.Exp(factor*(midpoint-x)))
	}

	// Pre-compute useful terms
	sig0 := sigmoidal(0.0)
	sig1 := sigmoidal(1.0)

	var scaledSigmoidal func(float64) float64

	if factor == 0 {
		scaledSigmoidal = func(x float64) float64 {
			return x
		}

	} else if factor > 0 {
		scaledSigmoidal = func(x float64) float64 {
			return (sigmoidal(x) - sig0) / (sig1 - sig0)
		}

	} else {
		scaledSigmoidal = func(x float64) float64 {
			argument := (sig1-sig0)*x + sig0
			var clamped float64
			if argument < Epsilon {
				clamped = Epsilon
			} else {
				if argument > 1-Epsilon {
					clamped = 1 - Epsilon
				} else {
					clamped = argument
				}
			}

			return midpoint - math.Log(1.0/clamped-1.0)/factor
		}
	}

	return func(c color.Color) color.Color {
		r, g, b, a := utils.RatioRGBA(c)

		r = utils.Truncatef(scaledSigmoidal(r) * 255)
		g = utils.Truncatef(scaledSigmoidal(g) * 255)
		b = utils.Truncatef(scaledSigmoidal(b) * 255)
		a = a * 255

		return color.NRGBA{uint8(r), uint8(g), uint8(b), uint8(a)}
	}
}
Exemple #4
0
Fichier : hsia.go Projet : hawx/img
func hsiaModel(c color.Color) color.Color {
	if _, ok := c.(HSIA); ok {
		return c
	}

	r, g, b, a := utils.RatioRGBA(c)

	maxi := utils.Maxf(r, g, b)
	mini := utils.Minf(r, g, b)
	chroma := maxi - mini

	// Work out hue
	hdash := 0.0
	if chroma == 0 {
		hdash = 0
	} else if maxi == r {
		hdash = math.Mod((g-b)/chroma, 6)
	} else if maxi == g {
		hdash = (b-r)/chroma + 2.0
	} else if maxi == b {
		hdash = (r-g)/chroma + 4.0
	}

	hue := hdash * 60

	if chroma == 0 {
		hue = 0
	}

	// Work out intensity
	intensity := (r + g + b) / 3

	// Work out saturation
	saturation := 0.0
	if chroma != 0 {
		saturation = 1 - mini/intensity
	}

	// prefer positive hues
	if hue < 0 {
		hue += 360
	}

	return HSIA{hue, saturation, intensity, a}
}
Exemple #5
0
Fichier : hsla.go Projet : hawx/img
func hslaModel(c color.Color) color.Color {
	if _, ok := c.(HSLA); ok {
		return c
	}

	r, g, b, a := utils.RatioRGBA(c)

	maxi := utils.Maxf(r, g, b)
	mini := utils.Minf(r, g, b)
	chroma := maxi - mini

	// Work out hue
	hdash := 0.0
	if chroma == 0 {
		hdash = 0
	} else if maxi == r {
		hdash = math.Mod((g-b)/chroma, 6)
	} else if maxi == g {
		hdash = (b-r)/chroma + 2.0
	} else if maxi == b {
		hdash = (r-g)/chroma + 4.0
	}

	hue := hdash * 60

	if chroma == 0 {
		hue = 0
	}

	// Work out lightness
	lightness := 0.5 * (maxi + mini)

	// Work out saturation
	saturation := 0.0
	if chroma != 0 {
		saturation = chroma / (1 - math.Abs(2*lightness-1))
	}

	return HSLA{hue, saturation, lightness, a}
}
Exemple #6
0
Fichier : hsva.go Projet : hawx/img
func hsvaModel(c color.Color) color.Color {
	if _, ok := c.(HSVA); ok {
		return c
	}

	r, g, b, a := utils.RatioRGBA(c)

	maxi := utils.Maxf(r, g, b)
	mini := utils.Minf(r, g, b)
	chroma := maxi - mini

	// Work out hue
	hdash := 0.0
	if chroma == 0 {
		hdash = 0
	} else if maxi == r {
		hdash = math.Mod((g-b)/chroma, 6)
	} else if maxi == g {
		hdash = (b-r)/chroma + 2.0
	} else if maxi == b {
		hdash = (r-g)/chroma + 4.0
	}

	hue := hdash * 60

	if chroma == 0 {
		hue = 0
	}

	// Work out value
	value := maxi

	// Work out saturation
	saturation := 0.0
	if chroma != 0 {
		saturation = chroma / value
	}

	return HSVA{hue, saturation, value, a}
}
Exemple #7
0
// AdjustC returns a Composable function that increases the saturation and
// decreases the lightness of unsaturated colours.
//
// Uses the same method as Darktable:
// https://github.com/darktable-org/darktable/blob/24c4a087fd020df587b5260f438bfaf494203cec/src/iop/vibrance.c
func AdjustC(amount float64) utils.Composable {
	return func(c color.Color) color.Color {
		r, g, b, a := utils.RatioRGBA(c)

		ll, la, lb := colorful.Color{r, g, b}.Lab()

		// saturation weight [0, 1]
		sw := math.Sqrt(la*la+lb*lb) / 2
		ls := 1.0 - amount*sw*0.25
		ss := 1.0 + amount*sw

		ll *= ls
		la *= ss
		lb *= ss

		f := colorful.Lab(ll, la, lb)

		fr := utils.Truncatef(f.R * 255)
		fg := utils.Truncatef(f.G * 255)
		fb := utils.Truncatef(f.B * 255)

		return color.NRGBA{uint8(fr), uint8(fg), uint8(fb), uint8(a * 255)}
	}
}
Exemple #8
0
func (_ alphaCh) Get(c color.Color) float64 {
	_, _, _, a := utils.RatioRGBA(c)
	return a
}
Exemple #9
0
func (_ blueCh) Get(c color.Color) float64 {
	_, _, b, _ := utils.RatioRGBA(c)
	return b
}
Exemple #10
0
func (_ greenCh) Get(c color.Color) float64 {
	_, g, _, _ := utils.RatioRGBA(c)
	return g
}
Exemple #11
0
func (_ redCh) Get(c color.Color) float64 {
	r, _, _, _ := utils.RatioRGBA(c)
	return r
}