示例#1
0
// Paste pastes the img image to the background image at the specified position and returns the combined image.
func Paste(background, img image.Image, pos image.Point) *image.NRGBA {
	src := toNRGBA(img)
	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(src.Bounds().Size())
	pasteBounds := image.Rectangle{startPt, endPt}

	if dst.Bounds().Overlaps(pasteBounds) {
		intersectBounds := dst.Bounds().Intersect(pasteBounds)

		rowSize := intersectBounds.Dx() * 4
		numRows := intersectBounds.Dy()

		srcStartX := intersectBounds.Min.X - pasteBounds.Min.X
		srcStartY := intersectBounds.Min.Y - pasteBounds.Min.Y

		i0 := dst.PixOffset(intersectBounds.Min.X, intersectBounds.Min.Y)
		j0 := src.PixOffset(srcStartX, srcStartY)

		di := dst.Stride
		dj := src.Stride

		for row := 0; row < numRows; row++ {
			copy(dst.Pix[i0:i0+rowSize], src.Pix[j0:j0+rowSize])
			i0 += di
			j0 += dj
		}
	}

	return dst
}
示例#2
0
func ClickInner(root *Widget, p image.Point) {
	for _, w := range root.Widgets {
		q := p.Sub(root.Rect.Min)
		if q.In(w.Rect) {
			w.Click(q)
		}
	}
}
示例#3
0
文件: node.go 项目: axel-freesp/sge
// (overwrite BBoxObject default implementation)
func (n *Node) SetPosition(pos image.Point) {
	shift := pos.Sub(n.Position())
	n.positioner.SetPosition(pos)
	n.BBoxDefaultSetPosition(pos)
	for _, p := range n.ports {
		p.SetPosition(p.Position().Add(shift))
	}
}
示例#4
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)
}
示例#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
func HoverInner(root *Widget, p0 image.Point, p1 image.Point) {
	for _, w := range root.Widgets {
		q0 := p0.Sub(root.Rect.Min)
		q1 := p1.Sub(root.Rect.Min)
		if q0.In(w.Rect) || q1.In(w.Rect) {
			w.Hover(q0, q1)
		}
	}
}
示例#7
0
文件: objects.go 项目: zenoss/rog-go
func (obj *Image) SetCentre(p image.Point) {
	p = p.Sub(centreDist(obj.Bbox()))
	if p.Eq(obj.item.R.Min) {
		return
	}
	obj.backing.Atomically(func(flush FlushFunc) {
		r := obj.item.R
		obj.item.R = r.Add(p.Sub(r.Min))
		flush(r, nil)
		flush(obj.item.R, nil)
	})
}
示例#8
0
文件: draw.go 项目: h8liu/golang
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
文件: scale.go 项目: eswdd/bosun
// 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)
	}
}
示例#10
0
文件: draw.go 项目: machinaut/go
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
	}
}
示例#11
0
func (v *signalGraphView) handleDrag(pos image.Point) {
	for _, n := range v.nodes {
		if n.IsSelected() {
			box := n.BBox()
			//if !overlaps(v.nodes, box.Min.Add(pos.Sub(v.dragOffs))) {
			v.repaintNode(n)
			box = box.Add(pos.Sub(v.dragOffs))
			v.dragOffs = pos
			n.SetPosition(box.Min)
			v.repaintNode(n)
			//}
		}
	}
}
示例#12
0
文件: text.go 项目: zenoss/rog-go
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 DragInner(root *Widget, p image.Point, d image.Point) bool {
	for i := range root.Widgets {
		w := root.Widgets[len(root.Widgets)-i-1]

		q := p.Sub(root.Rect.Min)
		if !q.In(w.Rect) {
			continue
		}

		if w.Drag(q, d) {
			return true
		}
	}

	return false
}
示例#14
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
}
示例#15
0
文件: tr.view.go 项目: js-arias/jdh
func trViewNearestNode(pt image.Point, node []*trNode) *trNode {
	var trn *trNode
	best := 11
	for _, n := range node {
		dif := pt.Sub(n.pos)
		if dif.X < 0 {
			dif.X = -dif.X
		}
		if dif.Y < 0 {
			dif.Y = -dif.Y
		}
		if d := dif.X + dif.Y; d < best {
			best = d
			trn = n
		}
	}
	return trn
}
示例#16
0
func (v *platformView) handleDrag(pos image.Point) {
	for _, a := range v.arch {
		if a.IsSelected() {
			box := a.BBox()
			repaint := box
			box = box.Add(pos.Sub(v.dragOffs))
			v.dragOffs = pos
			a.SetPosition(box.Min)
			repaint = repaint.Union(box)
			for _, aa := range v.arch {
				if aa.IsLinked(a.Name()) {
					repaint = repaint.Union(aa.BBox())
				}
			}
			v.drawScene(repaint)
		}
	}
}
示例#17
0
文件: sample.go 项目: jvlmdr/go-cv
// Uses half-sample symmetry.
func Symmetric(im image.Image, p image.Point) color.Color {
	b := im.Bounds()
	// Make twice as big.
	d := image.Rectangle{b.Min, b.Max.Add(b.Size())}
	p = p.Mod(d)

	// Move to origin.
	p = p.Sub(b.Min)
	w, h := b.Dx(), b.Dy()
	if p.X > w-1 {
		p.X = 2*w - 1 - p.X
	}
	if p.Y > h-1 {
		p.Y = 2*h - 1 - p.Y
	}
	p = p.Add(b.Min)

	return im.At(p.X, p.Y)
}
示例#18
0
// 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.
//
// Usage examples:
//
//		// draw the sprite over the background at position (50, 50)
//		dstImage := imaging.Overlay(backgroundImage, spriteImage, image.Pt(50, 50), 1.0)
//
//		// blend two opaque images of the same size
//		dstImage := imaging.Overlay(imageOne, imageTwo, image.Pt(0, 0), 0.5)
//
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
}
示例#19
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
	}
}
示例#20
0
func (v *mappingView) handleDrag(pos image.Point) {
	for _, a := range v.arch {
		if a.IsSelected() {
			box := a.BBox()
			v.repaintArch(a)
			box = box.Add(pos.Sub(v.dragOffs))
			v.dragOffs = pos
			a.SetPosition(box.Min)
			v.repaintArch(a)
		}
	}
	if v.unmapped.IsSelected() {
		box := v.unmapped.BBox()
		v.repaintUnmapped(v.unmapped)
		box = box.Add(pos.Sub(v.dragOffs))
		v.dragOffs = pos
		v.unmapped.SetPosition(box.Min)
		v.repaintUnmapped(v.unmapped)
	}
	for _, n := range v.nodes {
		n.Layout()
	}
}
示例#21
0
func (c *Container) ContainerDefaultSetPosition(pos image.Point) {
	if c.selectedChild != -1 {
		child := c.Children[c.selectedChild]
		childpos := child.Position()
		offset := childpos.Sub(c.Position())
		child.SetPosition(pos.Add(offset))
		c.box = c.Layout()
	} else if c.selectedPort != -1 {
		child := c.ports[c.selectedPort]
		childpos := child.Position()
		offset := childpos.Sub(c.Position())
		newPos := pos.Add(offset)
		child.SetPosition(c.portClipPos(newPos))
	} else {
		shift := pos.Sub(c.Position())
		c.BBoxDefaultSetPosition(pos)
		for _, p := range c.Children {
			p.SetPosition(p.Position().Add(shift))
		}
		for _, p := range c.ports {
			p.SetPosition(p.Position().Add(shift))
		}
	}
}
示例#22
0
文件: draw.go 项目: h8liu/golang
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))
}
示例#23
0
文件: gen.go 项目: rsaarelm/teratogen
func (oc OffsetChunk) At(pt image.Point) (MapCell, bool) {
	if cell, ok := oc.chunk.cells[pt.Sub(oc.offset)]; ok {
		return cell, true
	}
	return spaceCell, false
}
示例#24
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)
			}
		}
	}
}
示例#25
0
// place the camera's center at pt
func (c *Camera) SetCenter(pt image.Point) {
	newpos := pt.Sub(c.SizeRect.Size().Div(2))
	c.Pos = pt
	c.Rect = image.Rect(newpos.X, newpos.Y, newpos.X+c.SizeRect.Dx(), newpos.Y+c.SizeRect.Dy())
}
示例#26
0
func (c *Camera) Transform(pt image.Point) image.Point {
	return pt.Sub(c.Rect.Min) //.Add(c.Rect.Size().Div(2))
}
示例#27
0
// HexDist returns the hexagonal distance between two points.
func HexDist(p1, p2 image.Point) int {
	return HexLength(p2.Sub(p1))
}
示例#28
0
文件: text.go 项目: zenoss/rog-go
func (t *Text) SetCentre(cp image.Point) {
	delta := cp.Sub(centre(t.Bbox()))
	t.SetPoint(t.p.Add(delta))
}
示例#29
0
func exportMatrices(filename string, config *Config) {
	fmt.Printf("Processing %s... ", filename)

	// Open image
	file, err := os.Open(filename)
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()

	// Decode image
	image_file, err := png.Decode(file)
	if err != nil {
		log.Fatal(err)
	}

	// Set up some image variables
	image_size := image_file.Bounds().Size()
	tile_size := config.getTileGeometry("size")
	tile_origin := config.getTileGeometry("origin")

	tiles_x := image_size.X / tile_size.X
	tiles_y := image_size.Y / tile_size.Y
	fmt.Printf("Sprite sheet size: %dx%d\n", tiles_x, tiles_y)

	// Set up some path variables
	luaFilename := strings.Replace(filepath.Base(filename), filepath.Ext(filename), ".lua", 1)
	outputPath := filepath.Join(filepath.Dir(filename), luaFilename)

	// Open output lua file
	output, err := os.Create(outputPath)
	if err != nil {
		log.Fatal(err)
	}
	defer output.Close()

	// Populate table_data with blank data at the appropriate size
	table_data := config.getBlankTable(image.Point{tiles_x, tiles_y})

	// Populate color data for speed
	colors := make(map[icolor.RGBA]string)
	for hex, name := range config.getColorMappings() {
		color := hexToColor(hex)
		colors[color] = name
	}

	// Loop through the image
	for y := 0; y < image_size.Y; y++ {
		for x := 0; x < image_size.X; x++ {
			r, g, b, a := image_file.At(x, y).RGBA()
			color := icolor.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)}
			name, ok := colors[color]
			if ok {
				current_tile := image.Point{
					x / tile_size.X,
					y / tile_size.Y,
				}
				current_offset := image.Point{
					x % tile_size.X,
					y % tile_size.Y,
				}
				table_data[name][current_tile.Y][current_tile.X] = current_offset.Sub(tile_origin)
			}
		}
	}

	// Write this data to disk
	n, err := fmt.Fprintln(output, "return {")
	if n == 0 || err != nil {
		log.Fatal(err)
	}
	for name, _ := range table_data {
		fmt.Fprintf(output, "  %s = {\n", name) // start table

		for y := 0; y < tiles_y; y++ {
			fmt.Fprintf(output, "    {") // start row
			for x := 0; x < tiles_x; x++ {
				point := table_data[name][y][x]
				fmt.Fprintf(output, " {%d, %d},", point.X, point.Y)
			}
			fmt.Fprintln(output, "    },") // end row
		}

		fmt.Fprintln(output, "  },\n") // End table
	}
	fmt.Fprintln(output, "}")
}
示例#30
0
func main() {
	driver.Main(func(s screen.Screen) {
		w, err := s.NewWindow(nil)
		if err != nil {
			log.Fatal(err)
		}
		defer w.Release()

		var (
			pool = &tilePool{
				screen:   s,
				drawRGBA: drawRGBA,
				m:        map[image.Point]*tilePoolEntry{},
			}
			dragging     bool
			paintPending bool
			drag         image.Point
			origin       image.Point
			sz           size.Event
		)
		for e := range w.Events() {
			switch e := e.(type) {
			case key.Event:
				if e.Code == key.CodeEscape {
					return
				}

			case mouse.Event:
				p := image.Point{X: int(e.X), Y: int(e.Y)}
				if e.Button == mouse.ButtonLeft && e.Direction != mouse.DirNone {
					dragging = e.Direction == mouse.DirPress
					drag = p
				}
				if !dragging {
					break
				}
				origin = origin.Sub(p.Sub(drag))
				drag = p
				if origin.X < 0 {
					origin.X = 0
				}
				if origin.Y < 0 {
					origin.Y = 0
				}
				if !paintPending {
					paintPending = true
					w.Send(paint.Event{})
				}

			case paint.Event:
				generation++
				var wg sync.WaitGroup
				for y := -(origin.Y & 0xff); y < sz.HeightPx; y += 256 {
					for x := -(origin.X & 0xff); x < sz.WidthPx; x += 256 {
						wg.Add(1)
						go drawTile(&wg, w, pool, origin, x, y)
					}
				}
				wg.Wait()
				w.Publish()
				paintPending = false
				pool.releaseUnused()

			case size.Event:
				sz = e

			case error:
				log.Print(e)
			}
		}
	})
}