Пример #1
0
func traverseTiles(Style style, Area area) (image.Image, error) {
	m := image.NewRGBA(image.Rect(-Margins, -Margins, Area.TileRange.Dx()*TileSize+Margins, Area.TileRange.Dy()*TileSize+Margins))

	whiteColor := color.RGBA{255, 255, 255, 255}
	draw.Draw(m, m.Bounds(), &image.Uniform{whiteColor}, image.ZP, draw.Src)

	frameColor := color.RGBA{50, 50, 50, 255}
	draw.Draw(m, image.Rect(-Frame, -Frame, Area.TileRange.Dx()*TileSize+Frame, Area.TileRange.Dy()*TileSize+Frame), &image.Uniform{frameColor}, image.ZP, draw.Src)

	position := image.Rectangle{image.ZP, image.Point{X: TileSize, Y: TileSize}}
	for y := Area.TileRange.Min.Y; y < Area.TileRange.Max.Y; y++ {
		for x := Area.TileRange.Min.X; x < Area.TileRange.Max.X; x++ {
			img, err := readTile(Style.Mapid, Area.Z, uint(x), uint(y))
			if err != nil {
				fmt.Printf("no luck reading this tile: z:%v, %vx %v \n", Area.Z, x, y)
				fmt.Println(err)
				break
			}
			fmt.Printf("...adding %vx%v \n", x, y)
			draw.Draw(m, position, img, image.ZP, draw.Src)
			position = position.Add(image.Point{X: TileSize, Y: 0})
		}
		position = image.Rectangle{image.Point{X: 0, Y: (y - Area.TileRange.Min.Y + 1) * TileSize}, image.Point{X: TileSize, Y: (y - Area.TileRange.Min.Y + 2) * TileSize}}
	}
	fmt.Println("Great success!")
	return m, nil
}
Пример #2
0
// Copy copies the part of the source image defined by src and sr and writes to
// the part of the destination image defined by dst and the translation of sr
// so that sr.Min translates to dp.
func Copy(dst Image, dp image.Point, src image.Image, sr image.Rectangle, opts *Options) {
	mask, mp, op := image.Image(nil), image.Point{}, Over
	if opts != nil {
		// TODO: set mask, mp and op.
	}
	dr := sr.Add(dp.Sub(sr.Min))
	DrawMask(dst, dr, src, sr.Min, mask, mp, op)
}
Пример #3
0
func (m *mover) Draw(img draw.Image, clipr image.Rectangle) {
	//debugp("mover draw clipr %v; centre %v; delta %v\n", clipr, centre(m.item.Bbox()), m.delta)
	clipr = clipr.Add(m.delta)
	i := SliceImage(clipr.Max.X, clipr.Max.Y, clipr, img, m.delta)
	//debugp("item draw clipr %v; delta %v; bbox %v\n", clipr, m.delta, m.item.Bbox())
	m.item.Draw(i, clipr)
	//debugp("item drawn\n")
}
Пример #4
0
// ToImageRect converts a point in the feature pyramid to a rectangle in the image.
func (pyr *Generator) ToImageRect(level int, pt image.Point, interior image.Rectangle) image.Rectangle {
	// Translate interior by position (scaled by rate) and subtract margin offset.
	rate := pyr.Transform.Rate()
	offset := pyr.Pad.Margin.TopLeft()
	scale := pyr.Image.Scales[level]
	rect := interior.Add(pt.Mul(rate)).Sub(offset)
	return scaleRect(1/scale, rect)
}
Пример #5
0
// Copy copies the part of the source image defined by src and sr and writes to
// the part of the destination image defined by dst and the translation of sr
// so that sr.Min translates to dp.
func Copy(dst Image, dp image.Point, src image.Image, sr image.Rectangle, opts *Options) {
	var o Options
	if opts != nil {
		o = *opts
	}
	dr := sr.Add(dp.Sub(sr.Min))
	// TODO: honor o.DstMask and o.SrcMask.
	DrawMask(dst, dr, src, sr.Min, nil, image.Point{}, o.Op)
}
Пример #6
0
// initLayout constructs two masks for drawing the battery and the remaining
// energy as well as sets the pixel bounds for drawing energy capacity.  the
// masks allow for simplified space-fills and reduced chance of pixel gaps.
func (app *App) initLayout() {
	var zeropt image.Point

	rectOutTop := image.Rectangle{Min: app.Layout.battRect.Min, Max: app.Layout.battRect.Min.Add(image.Point{2, 2})}
	rectOutBottom := rectOutTop.Add(image.Point{Y: app.Layout.battRect.Size().Y - rectOutTop.Size().Y})
	capRect := image.Rectangle{
		Min: image.Point{X: rectOutTop.Min.X, Y: rectOutTop.Max.Y},
		Max: image.Point{X: rectOutBottom.Max.X, Y: rectOutBottom.Min.Y},
	}
	bodyRect := app.Layout.battRect
	bodyRect.Min.X = capRect.Max.X

	// energy will be drawn under the battery shell.  The only place where it
	// is not safe to draw energy is outside the battery on the positive end.
	energyMask := image.NewAlpha(app.Layout.battRect)
	draw.Draw(energyMask, app.Layout.battRect, opaque, zeropt, draw.Over)
	draw.Draw(energyMask, rectOutTop, transparent, zeropt, draw.Src)
	draw.Draw(energyMask, rectOutBottom, transparent, zeropt, draw.Src)
	app.maskEnergy = energyMask

	// the body uses the same mask as the energy with additional transparency
	// inside the battery's shell.  the mask construction is complex because
	// area inside the cap may be exposed.
	bodyMask := image.NewAlpha(app.Layout.battRect)
	draw.Draw(bodyMask, app.Layout.battRect, energyMask, app.Layout.battRect.Min, draw.Over)
	bodyMaskRect := shrinkRect(bodyRect, app.Layout.thickness)
	draw.Draw(bodyMask, bodyMaskRect, transparent, zeropt, draw.Src)
	capMaskRect := shrinkRect(capRect, app.Layout.thickness)
	capMaskRect.Max.X += 2 * app.Layout.thickness
	draw.Draw(bodyMask, capMaskRect, transparent, zeropt, draw.Src)
	app.maskBattery = bodyMask

	// create a freetype.Context to render text.  each time the context is used
	// it must have its SetDst method called.
	app.tt = freetype.NewContext()
	app.tt.SetSrc(black)
	app.tt.SetClip(app.Layout.textRect)
	app.tt.SetDPI(app.Layout.DPI)
	app.tt.SetFont(app.Layout.font)
	app.tt.SetFontSize(app.Layout.fontSize)
	ttopt := &truetype.Options{
		Size: app.Layout.fontSize,
		DPI:  app.Layout.DPI,
	}
	ttface := truetype.NewFace(app.Layout.font, ttopt)
	app.font = &font.Drawer{
		Src:  black,
		Face: ttface,
	}

	// the rectangle in which energy is drawn needs to account for thickness to
	// make the visible percentage more accurate.  after adjustment reduce the
	// energy rect to account for the account of energy drained.  the energy
	// mask makes computing Y bounds largely irrelevant.
	app.minEnergy = capMaskRect.Min.X
	app.maxEnergy = bodyMaskRect.Max.X
}
Пример #7
0
// Copy copies the part of the source image defined by src and sr and writes
// the result of a Porter-Duff composition to the part of the destination image
// defined by dst and the translation of sr so that sr.Min translates to dp.
func Copy(dst Image, dp image.Point, src image.Image, sr image.Rectangle, op Op, opts *Options) {
	var o Options
	if opts != nil {
		o = *opts
	}
	dr := sr.Add(dp.Sub(sr.Min))
	if o.DstMask == nil {
		DrawMask(dst, dr, src, sr.Min, o.SrcMask, o.SrcMaskP.Add(sr.Min), op)
	} else {
		NearestNeighbor.Scale(dst, dr, src, sr, op, opts)
	}
}
Пример #8
0
func drawRGBA(dst *image.RGBA, r image.Rectangle, src image.Image, sp image.Point, mask image.Image, mp image.Point, op Op) {
	x0, x1, dx := r.Min.X, r.Max.X, 1
	y0, y1, dy := r.Min.Y, r.Max.Y, 1
	if image.Image(dst) == src && r.Overlaps(r.Add(sp.Sub(r.Min))) {
		if sp.Y < r.Min.Y || sp.Y == r.Min.Y && sp.X < r.Min.X {
			x0, x1, dx = x1-1, x0-1, -1
			y0, y1, dy = y1-1, y0-1, -1
		}
	}

	sy := sp.Y + y0 - r.Min.Y
	my := mp.Y + y0 - r.Min.Y
	sx0 := sp.X + x0 - r.Min.X
	mx0 := mp.X + x0 - r.Min.X
	sx1 := sx0 + (x1 - x0)
	i0 := dst.PixOffset(x0, y0)
	di := dx * 4
	for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy {
		for i, sx, mx := i0, sx0, mx0; sx != sx1; i, sx, mx = i+di, sx+dx, mx+dx {
			ma := uint32(m)
			if mask != nil {
				_, _, _, ma = mask.At(mx, my).RGBA()
			}
			sr, sg, sb, sa := src.At(sx, sy).RGBA()
			if op == Over {
				dr := uint32(dst.Pix[i+0])
				dg := uint32(dst.Pix[i+1])
				db := uint32(dst.Pix[i+2])
				da := uint32(dst.Pix[i+3])

				// dr, dg, db and da are all 8-bit color at the moment, ranging in [0,255].
				// We work in 16-bit color, and so would normally do:
				// dr |= dr << 8
				// and similarly for dg, db and da, but instead we multiply a
				// (which is a 16-bit color, ranging in [0,65535]) by 0x101.
				// This yields the same result, but is fewer arithmetic operations.
				a := (m - (sa * ma / m)) * 0x101

				dst.Pix[i+0] = uint8((dr*a + sr*ma) / m >> 8)
				dst.Pix[i+1] = uint8((dg*a + sg*ma) / m >> 8)
				dst.Pix[i+2] = uint8((db*a + sb*ma) / m >> 8)
				dst.Pix[i+3] = uint8((da*a + sa*ma) / m >> 8)

			} else {
				dst.Pix[i+0] = uint8(sr * ma / m >> 8)
				dst.Pix[i+1] = uint8(sg * ma / m >> 8)
				dst.Pix[i+2] = uint8(sb * ma / m >> 8)
				dst.Pix[i+3] = uint8(sa * ma / m >> 8)
			}
		}
		i0 += dy * dst.Stride
	}
}
Пример #9
0
func drawRGBA(dst *image.RGBA, r image.Rectangle, src image.Image, sp image.Point, mask image.Image, mp image.Point, op Op) {
	x0, x1, dx := r.Min.X, r.Max.X, 1
	y0, y1, dy := r.Min.Y, r.Max.Y, 1
	if image.Image(dst) == src && r.Overlaps(r.Add(sp.Sub(r.Min))) {
		if sp.Y < r.Min.Y || sp.Y == r.Min.Y && sp.X < r.Min.X {
			x0, x1, dx = x1-1, x0-1, -1
			y0, y1, dy = y1-1, y0-1, -1
		}
	}

	sy := sp.Y + y0 - r.Min.Y
	my := mp.Y + y0 - r.Min.Y
	sx0 := sp.X + x0 - r.Min.X
	mx0 := mp.X + x0 - r.Min.X
	i0 := (y0 - dst.Rect.Min.Y) * dst.Stride
	for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy {
		dpix := dst.Pix[i0:]
		for x, sx, mx := x0, sx0, mx0; x != x1; x, sx, mx = x+dx, sx+dx, mx+dx {
			ma := uint32(m)
			if mask != nil {
				_, _, _, ma = mask.At(mx, my).RGBA()
			}
			sr, sg, sb, sa := src.At(sx, sy).RGBA()
			var dr, dg, db, da uint32
			if op == Over {
				rgba := dpix[x-dst.Rect.Min.X]
				dr = uint32(rgba.R)
				dg = uint32(rgba.G)
				db = uint32(rgba.B)
				da = uint32(rgba.A)
				// dr, dg, db and da are all 8-bit color at the moment, ranging in [0,255].
				// We work in 16-bit color, and so would normally do:
				// dr |= dr << 8
				// and similarly for dg, db and da, but instead we multiply a
				// (which is a 16-bit color, ranging in [0,65535]) by 0x101.
				// This yields the same result, but is fewer arithmetic operations.
				a := (m - (sa * ma / m)) * 0x101
				dr = (dr*a + sr*ma) / m
				dg = (dg*a + sg*ma) / m
				db = (db*a + sb*ma) / m
				da = (da*a + sa*ma) / m
			} else {
				dr = sr * ma / m
				dg = sg * ma / m
				db = sb * ma / m
				da = sa * ma / m
			}
			dpix[x-dst.Rect.Min.X] = image.RGBAColor{uint8(dr >> 8), uint8(dg >> 8), uint8(db >> 8), uint8(da >> 8)}
		}
		i0 += dy * dst.Stride
	}
}
Пример #10
0
// Check if the selected object would overlap with any other
// if we move it to p coordinates:
func overlaps(list []graph.NodeIf, p image.Point) bool {
	var box image.Rectangle
	for _, n := range list {
		if n.IsSelected() {
			box = n.BBox()
			break
		}
	}
	newBox := box.Add(p.Sub(box.Min))
	for _, n := range list {
		if !n.IsSelected() && newBox.Overlaps(n.BBox()) {
			return true
		}
	}
	return false
}
Пример #11
0
func (a *area) Repaint(r image.Rectangle) {
	var hscroll, vscroll C.int
	var rect C.RECT

	C.SendMessageW(a.hwnd, C.msgAreaGetScroll, C.WPARAM(uintptr(unsafe.Pointer(&hscroll))), C.LPARAM(uintptr(unsafe.Pointer(&vscroll))))
	r = r.Add(image.Pt(int(hscroll), int(vscroll))) // adjust by scroll position
	r = image.Rect(0, 0, a.width, a.height).Intersect(r)
	if r.Empty() {
		return
	}
	rect.left = C.LONG(r.Min.X)
	rect.top = C.LONG(r.Min.Y)
	rect.right = C.LONG(r.Max.X)
	rect.bottom = C.LONG(r.Max.Y)
	C.SendMessageW(a.hwnd, C.msgAreaRepaint, 0, C.LPARAM(uintptr(unsafe.Pointer(&rect))))
}
Пример #12
0
func anchor(r image.Rectangle, flags Anchor, p image.Point) image.Rectangle {
	var dp image.Point
	switch flags & (E | W) {
	case E:
		dp.X = r.Dx()
	case E | W, 0:
		dp.X = r.Dx() / 2
	}
	switch flags & (N | S) {
	case S:
		dp.Y = r.Dy()
	case S | N, 0:
		dp.Y = r.Dy() / 2
	}
	return r.Add(p.Sub(r.Min).Sub(dp))
}
Пример #13
0
func setpiece(p *Piece) {
	bb.Draw(bb.R, display.White, nil, image.ZP)
	bbmask.Draw(bb.R, display.Transparent, nil, image.ZP)
	br = image.Rect(0, 0, 0, 0)
	br2 = br
	piece = p
	if p == nil {
		return
	}
	var op image.Point
	var r image.Rectangle
	r.Min = bb.R.Min
	for i, pt := range p.d {
		r.Min.X += pt.X * pcsz
		r.Min.Y += pt.Y * pcsz
		r.Max.X = r.Min.X + pcsz
		r.Max.Y = r.Min.Y + pcsz
		if i == 0 {
			bb.Draw(r, display.Black, nil, image.ZP)
			bb.Draw(r.Inset(1), tx[piece.tx], nil, image.ZP)
			bbmask.Draw(r, display.Opaque, nil, image.ZP)
			op = r.Min
		} else {
			bb.Draw(r, bb, nil, op)
			bbmask.Draw(r, bbmask, nil, op)
		}
		if br.Max.X < r.Max.X {
			br.Max.X = r.Max.X
		}
		if br.Max.Y < r.Max.Y {
			br.Max.Y = r.Max.Y
		}
	}
	br.Max = br.Max.Sub(bb.R.Min)
	delta := image.Pt(0, DY)
	br2.Max = br.Max.Add(delta)
	r = br.Add(bb2.R.Min)
	r2 := br2.Add(bb2.R.Min)
	bb2.Draw(r2, display.White, nil, image.ZP)
	bb2.Draw(r.Add(delta), bb, nil, bb.R.Min)
	bb2mask.Draw(r2, display.Transparent, nil, image.ZP)
	bb2mask.Draw(r, display.Opaque, bbmask, bb.R.Min)
	bb2mask.Draw(r.Add(delta), display.Opaque, bbmask, bb.R.Min)
}
Пример #14
0
func testYCbCr(t *testing.T, r image.Rectangle, subsampleRatio image.YCbCrSubsampleRatio, delta image.Point) {
	// Create a YCbCr image m, whose bounds are r translated by (delta.X, delta.Y).
	r1 := r.Add(delta)
	img := image.NewYCbCr(r1, subsampleRatio)

	// Initialize img's pixels. For 422 and 420 subsampling, some of the Cb and Cr elements
	// will be set multiple times. That's OK. We just want to avoid a uniform image.
	for y := r1.Min.Y; y < r1.Max.Y; y++ {
		for x := r1.Min.X; x < r1.Max.X; x++ {
			yi := img.YOffset(x, y)
			ci := img.COffset(x, y)
			img.Y[yi] = uint8(16*y + x)
			img.Cb[ci] = uint8(y + 16*x)
			img.Cr[ci] = uint8(y + 16*x)
		}
	}

	m := imageYCbCrToYCC(img)

	// Make various sub-images of m.
	for y0 := delta.Y + 3; y0 < delta.Y+7; y0++ {
		for y1 := delta.Y + 8; y1 < delta.Y+13; y1++ {
			for x0 := delta.X + 3; x0 < delta.X+7; x0++ {
				for x1 := delta.X + 8; x1 < delta.X+13; x1++ {
					subRect := image.Rect(x0, y0, x1, y1)
					sub := m.SubImage(subRect).(*ycc)

					// For each point in the sub-image's bounds, check that m.At(x, y) equals sub.At(x, y).
					for y := sub.Rect.Min.Y; y < sub.Rect.Max.Y; y++ {
						for x := sub.Rect.Min.X; x < sub.Rect.Max.X; x++ {
							color0 := m.At(x, y).(color.YCbCr)
							color1 := sub.At(x, y).(color.YCbCr)
							if color0 != color1 {
								t.Errorf("r=%v, subsampleRatio=%v, delta=%v, x=%d, y=%d, color0=%v, color1=%v",
									r, subsampleRatio, delta, x, y, color0, color1)
								return
							}
						}
					}
				}
			}
		}
	}
}
Пример #15
0
func setpiece(p *Piece) {
	draw.Draw(bb, bbr, image.White, image.ZP)
	draw.Draw(bbmask, bbr, image.Transparent, image.ZP)
	br = image.Rect(0, 0, 0, 0)
	br2 = br
	piece = p
	if p == nil {
		return
	}
	var op image.Point
	var r image.Rectangle
	r.Min = bbr.Min
	for i, pt := range p.d {
		r.Min.X += pt.X * pcsz
		r.Min.Y += pt.Y * pcsz
		r.Max.X = r.Min.X + pcsz
		r.Max.Y = r.Min.Y + pcsz
		if i == 0 {
			draw.Draw(bb, r, image.Black, image.ZP)
			draw.Draw(bb, r.Inset(1), txpix[piece.tx], image.ZP)
			draw.Draw(bbmask, r, image.Opaque, image.ZP)
			op = r.Min
		} else {
			draw.Draw(bb, r, bb, op)
			draw.Draw(bbmask, r, bbmask, op)
		}
		if br.Max.X < r.Max.X {
			br.Max.X = r.Max.X
		}
		if br.Max.Y < r.Max.Y {
			br.Max.Y = r.Max.Y
		}
	}
	br.Max = br.Max.Sub(bbr.Min)
	delta := image.Pt(0, DY)
	br2.Max = br.Max.Add(delta)
	r = br.Add(bb2r.Min)
	r2 := br2.Add(bb2r.Min)
	draw.Draw(bb2, r2, image.White, image.ZP)
	draw.Draw(bb2, r.Add(delta), bb, bbr.Min)
	draw.Draw(bb2mask, r2, image.Transparent, image.ZP)
	draw.DrawMask(bb2mask, r, image.Opaque, bbr.Min, bbmask, image.ZP, draw.Over)
	draw.DrawMask(bb2mask, r.Add(delta), image.Opaque, bbr.Min, bbmask, image.ZP, draw.Over)
}
Пример #16
0
func fitted(into image.Rectangle, size image.Point) image.Rectangle {
	ratio := float64(size.X) / float64(size.Y)

	if size.X > into.Dx() {
		size.X = into.Dx()
		size.Y = int(float64(into.Dx()) / ratio)
	}

	if size.Y > into.Dy() {
		size.X = int(float64(into.Dy()) * ratio)
		size.Y = into.Dy()
	}

	r := image.Rectangle{
		Min: into.Min,
		Max: into.Min.Add(size),
	}
	r = r.Add(image.Point{into.Dx() / 2, into.Dy() / 2}).
		Sub(image.Point{size.X / 2, size.Y / 2})

	return r
}
Пример #17
0
func (t *textureImpl) Upload(dp image.Point, src screen.Buffer, sr image.Rectangle) {
	buf := src.(*bufferImpl)
	buf.preUpload()

	// src2dst is added to convert from the src coordinate space to the dst
	// coordinate space. It is subtracted to convert the other way.
	src2dst := dp.Sub(sr.Min)

	// Clip to the source.
	sr = sr.Intersect(buf.Bounds())

	// Clip to the destination.
	dr := sr.Add(src2dst)
	dr = dr.Intersect(t.Bounds())
	if dr.Empty() {
		return
	}

	// Bring dr.Min in dst-space back to src-space to get the pixel buffer offset.
	pix := buf.rgba.Pix[buf.rgba.PixOffset(dr.Min.X-src2dst.X, dr.Min.Y-src2dst.Y):]

	t.w.glctxMu.Lock()
	defer t.w.glctxMu.Unlock()

	t.w.glctx.BindTexture(gl.TEXTURE_2D, t.id)

	width := dr.Dx()
	if width*4 == buf.rgba.Stride {
		t.w.glctx.TexSubImage2D(gl.TEXTURE_2D, 0, dr.Min.X, dr.Min.Y, width, dr.Dy(), gl.RGBA, gl.UNSIGNED_BYTE, pix)
		return
	}
	// TODO: can we use GL_UNPACK_ROW_LENGTH with glPixelStorei for stride in
	// ES 3.0, instead of uploading the pixels row-by-row?
	for y, p := dr.Min.Y, 0; y < dr.Max.Y; y++ {
		t.w.glctx.TexSubImage2D(gl.TEXTURE_2D, 0, dr.Min.X, y, width, 1, gl.RGBA, gl.UNSIGNED_BYTE, pix[p:])
		p += buf.rgba.Stride
	}
}
Пример #18
0
func processBackward(dst Image, r image.Rectangle, src image.Image, sp image.Point) bool {
	return image.Image(dst) == src &&
		r.Overlaps(r.Add(sp.Sub(r.Min))) &&
		(sp.Y < r.Min.Y || (sp.Y == r.Min.Y && sp.X < r.Min.X))
}
Пример #19
0
// DrawMask aligns r.Min in dst with sp in src and mp in mask and then replaces the rectangle r
// in dst with the result of a Porter-Duff composition. A nil mask is treated as opaque.
func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mask image.Image, mp image.Point, op Op) {
	clip(dst, &r, src, &sp, mask, &mp)
	if r.Empty() {
		return
	}

	// Fast paths for special cases. If none of them apply, then we fall back to a general but slow implementation.
	if dst0, ok := dst.(*image.RGBA); ok {
		if op == Over {
			if mask == nil {
				switch src0 := src.(type) {
				case *image.ColorImage:
					drawFillOver(dst0, r, src0)
					return
				case *image.RGBA:
					drawCopyOver(dst0, r, src0, sp)
					return
				case *image.NRGBA:
					drawNRGBAOver(dst0, r, src0, sp)
					return
				case *ycbcr.YCbCr:
					drawYCbCr(dst0, r, src0, sp)
					return
				}
			} else if mask0, ok := mask.(*image.Alpha); ok {
				switch src0 := src.(type) {
				case *image.ColorImage:
					drawGlyphOver(dst0, r, src0, mask0, mp)
					return
				}
			}
		} else {
			if mask == nil {
				switch src0 := src.(type) {
				case *image.ColorImage:
					drawFillSrc(dst0, r, src0)
					return
				case *image.RGBA:
					drawCopySrc(dst0, r, src0, sp)
					return
				case *image.NRGBA:
					drawNRGBASrc(dst0, r, src0, sp)
					return
				case *ycbcr.YCbCr:
					drawYCbCr(dst0, r, src0, sp)
					return
				}
			}
		}
		drawRGBA(dst0, r, src, sp, mask, mp, op)
		return
	}

	x0, x1, dx := r.Min.X, r.Max.X, 1
	y0, y1, dy := r.Min.Y, r.Max.Y, 1
	if image.Image(dst) == src && r.Overlaps(r.Add(sp.Sub(r.Min))) {
		// Rectangles overlap: process backward?
		if sp.Y < r.Min.Y || sp.Y == r.Min.Y && sp.X < r.Min.X {
			x0, x1, dx = x1-1, x0-1, -1
			y0, y1, dy = y1-1, y0-1, -1
		}
	}

	var out *image.RGBA64Color
	sy := sp.Y + y0 - r.Min.Y
	my := mp.Y + y0 - r.Min.Y
	for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy {
		sx := sp.X + x0 - r.Min.X
		mx := mp.X + x0 - r.Min.X
		for x := x0; x != x1; x, sx, mx = x+dx, sx+dx, mx+dx {
			ma := uint32(m)
			if mask != nil {
				_, _, _, ma = mask.At(mx, my).RGBA()
			}
			switch {
			case ma == 0:
				if op == Over {
					// No-op.
				} else {
					dst.Set(x, y, zeroColor)
				}
			case ma == m && op == Src:
				dst.Set(x, y, src.At(sx, sy))
			default:
				sr, sg, sb, sa := src.At(sx, sy).RGBA()
				if out == nil {
					out = new(image.RGBA64Color)
				}
				if op == Over {
					dr, dg, db, da := dst.At(x, y).RGBA()
					a := m - (sa * ma / m)
					out.R = uint16((dr*a + sr*ma) / m)
					out.G = uint16((dg*a + sg*ma) / m)
					out.B = uint16((db*a + sb*ma) / m)
					out.A = uint16((da*a + sa*ma) / m)
				} else {
					out.R = uint16(sr * ma / m)
					out.G = uint16(sg * ma / m)
					out.B = uint16(sb * ma / m)
					out.A = uint16(sa * ma / m)
				}
				dst.Set(x, y, out)
			}
		}
	}
}
Пример #20
0
// Converts the position of a detection in a feature image to a rectangle in the intensity image.
//
// Additional arguments are:
// the integer downsample rate of the feature transform,
// the margin which was added to the image before taking the feature transform,
// the rectangular region within the window which corresponds to the annotation.
func featPtToImRect(pt image.Point, rate int, margin feat.Margin, interior image.Rectangle) image.Rectangle {
	return interior.Add(pt.Mul(rate)).Sub(margin.TopLeft())
}
Пример #21
0
// Converts a point in the feature pyramid to a rectangle in the image.
func (pyr *Pyramid) ToImageRect(pt imgpyr.Point, interior image.Rectangle) image.Rectangle {
	// Translate interior by position (scaled by rate) and subtract margin offset.
	rect := interior.Add(pt.Pos.Mul(pyr.Rate)).Sub(pyr.Margin.TopLeft())
	// Scale rectangle.
	return scaleRect(1/pyr.Scale(pt.Level), rect)
}