Browse Source

New function: Overlay

disintegration 12 years ago
parent
commit
024a9635b6
1 changed files with 44 additions and 0 deletions
  1. 44 0
      imaging.go

+ 44 - 0
imaging.go

@@ -367,6 +367,50 @@ func PasteCenter(img, src image.Image) *image.NRGBA {
 	return Paste(img, src, image.Pt(x0, y0))
 }
 
+// Overlay draws the source image over the background image at given position
+// and returns the combined image. Opacity parameter is the opacity of the source
+// image layer, used to compose the images, it must be from 0.0 to 1.0. 
+func Overlay(background, source image.Image, pos image.Point, opacity float64) *image.NRGBA {
+	opacity = math.Min(math.Max(opacity, 0.0), 1.0) // check: 0.0 <= opacity <= 1.0
+
+	src := convertToNRGBA(source)
+	srcBounds := src.Bounds()
+
+	dst := Clone(background)                    // cloned image bounds start at (0, 0)
+	startPt := pos.Sub(background.Bounds().Min) // so we should translate start point
+	endPt := startPt.Add(srcBounds.Size())
+	pasteBounds := image.Rectangle{startPt, endPt}
+
+	if dst.Bounds().Overlaps(pasteBounds) {
+		intersectBounds := dst.Bounds().Intersect(pasteBounds)
+
+		for y := intersectBounds.Min.Y; y < intersectBounds.Max.Y; y++ {
+			for x := intersectBounds.Min.X; x < intersectBounds.Max.X; x++ {
+				i := dst.PixOffset(x, y)
+				srcX := x - pasteBounds.Min.X + srcBounds.Min.X
+				srcY := y - pasteBounds.Min.Y + srcBounds.Min.Y
+				j := src.PixOffset(srcX, srcY)
+
+				a1 := float64(dst.Pix[i+3])
+				a2 := float64(src.Pix[j+3])
+
+				coef2 := opacity * a2 / 255.0
+				coef1 := (1 - coef2) * a1 / 255.0
+				coefSum := coef1 + coef2
+				coef1 /= coefSum
+				coef2 /= coefSum
+
+				dst.Pix[i+0] = uint8(float64(dst.Pix[i+0])*coef1 + float64(src.Pix[j+0])*coef2)
+				dst.Pix[i+1] = uint8(float64(dst.Pix[i+1])*coef1 + float64(src.Pix[j+1])*coef2)
+				dst.Pix[i+2] = uint8(float64(dst.Pix[i+2])*coef1 + float64(src.Pix[j+2])*coef2)
+				dst.Pix[i+3] = uint8(math.Min(a1+a2*opacity*(255.0-a1)/255.0, 255.0))
+			}
+		}
+	}
+
+	return dst
+}
+
 // Rotate90 rotates the image 90 degrees clockwise and returns the transformed image.
 func Rotate90(img image.Image) *image.NRGBA {
 	src := convertToNRGBA(img)