Пример #1
0
func NewTiledImage(img *image.RGBA, tileSize image.Point) *TiledImage {
	b := img.Bounds()
	nx := b.Dx() / tileSize.X
	ny := b.Dy() / tileSize.Y
	tiles := make([]TileInfo, nx*ny)

	for j := 0; j < ny; j++ {
		y := b.Min.Y + j*tileSize.Y
		for i := 0; i < nx; i++ {
			x := b.Min.X + i*tileSize.X
			rect := image.Rect(x, y, x+tileSize.X, y+tileSize.Y)
			k := i + j*nx
			tiles[k].subImage = img.SubImage(rect).(*image.RGBA)
			tiles[k].dist2 = math.MaxFloat32
		}
	}

	return &TiledImage{
		data: tiles,
		nx:   nx,
		ny:   ny,
		sx:   tileSize.X,
		sy:   tileSize.Y,
	}
}
Пример #2
0
func (wf *WindowFoundation) handleWindowDrawing() {

	waitingForRepaint := false
	newStuff := false

	var scrBuf *image.RGBA

	var invalidRects RectSet

	for {
		select {
		case pane := <-wf.paneCh:
			wf.setPane(pane)
		case inv := <-wf.Invalidations:
			invalidRects = append(invalidRects, inv.Bounds...)
			if waitingForRepaint {
				newStuff = true
			} else {
				waitingForRepaint = true
				newStuff = true
				time.AfterFunc(FrameDelay, func() {
					wf.doRepaintWindow <- true
				})
			}

		case <-wf.doRepaintWindow:
			waitingForRepaint = false
			if !newStuff {
				break
			}
			scr := wf.W.Screen()
			if scrBuf == nil || scr.Bounds() != scrBuf.Bounds() {
				scrBuf = image.NewRGBA(scr.Bounds())
				invalidRects = RectSet{wf.Bounds()}
			}
			// Report("window drawing starting")
			wf.Drawer.Draw(scrBuf, invalidRects)
			// Report("window drawing done")
			var srs []image.Rectangle
			for _, ir := range invalidRects {
				sr := RectangleForRect(ir)
				si := scrBuf.SubImage(sr)
				srs = append(srs, sr)
				draw.Draw(scr, scr.Bounds(), si, image.Point{}, draw.Src)
			}
			invalidRects = invalidRects[:0]

			wf.W.FlushImage(srs...)
			newStuff = false
		}
	}
}
Пример #3
0
func MakeTileInfo(img *image.RGBA, tileSize image.Point) [][]TileInfo {
	b := img.Bounds()
	nx := b.Dx() / tileSize.X
	ny := b.Dy() / tileSize.Y

	tiles := make([][]TileInfo, nx)
	for i, _ := range tiles {
		tiles[i] = make([]TileInfo, ny)
	}

	for j, y := 0, b.Min.Y; j < ny; j, y = j+1, y+tileSize.Y {
		for i, x := 0, b.Min.X; i < nx; i, x = i+1, x+tileSize.X {
			rect := image.Rect(x, y, x+tileSize.X, y+tileSize.Y)
			tiles[i][j].subImage = img.SubImage(rect).(*image.RGBA)
			tiles[i][j].dist2 = math.MaxFloat32
		}
	}

	return tiles
}
Пример #4
0
func window() {
	var wg sync.WaitGroup

	size := 500

	wg.Add(1)

	go func() {
		dw, err := wde.NewWindow(size, size)
		if err != nil {
			fmt.Println(err)
			return
		}
		dw.SetTitle("xkcd-zoom")
		dw.SetSize(size, size)
		dw.Show()

		events := dw.EventChan()

		const (
			Draw         = 1
			Redraw       = 2
			ScaleInPlace = 3
		)

		redraw := make(chan int, 1)

		redraw <- Draw

		done := make(chan bool)

		go func() {
			for {
				time.Sleep(time.Second)
				redraw <- Redraw
			}
		}()

		go func() {
		loop:
			for ei := range events {
				redrawType := 0
				runtime.Gosched()
				switch e := ei.(type) {
				case wde.MouseDownEvent:
				case wde.MouseDraggedEvent:
					switch e.Which {
					case wde.LeftButton:
						changedx := e.Where.X - e.From.X
						changedy := e.Where.Y - e.From.Y
						drawx += float64(changedx) * scale
						drawy += float64(-changedy) * scale
						redrawType = Draw
					case wde.RightButton:
						changedy := e.From.Y - e.Where.Y
						mouseScale := float64(changedy) / 100
						scale *= math.Pow(2, mouseScale)
						redrawType = ScaleInPlace
					}
				case wde.MouseUpEvent:
					if e.Which == wde.RightButton {
						scaledTiles = map[float64]map[int]map[int]chan image.Image{}
						redrawType = Draw
					}
				case wde.KeyTypedEvent:
					if e.Key == wde.KeyEscape {
						break loop
					}
				case wde.CloseEvent:
					break loop
				case wde.ResizeEvent:
					redrawType = Draw
				}
				if redrawType != 0 {
					select {
					case redraw <- redrawType:
					default:
					}
				}
			}
			dw.Close()
			done <- true
		}()

		var greyBack, screenBuffer *image.RGBA
		var grey = color.RGBA{155, 155, 155, 255}
		var bufferScale = scale
		var lastRedraw int
		for {
			select {
			case redrawType := <-redraw:
				if lastRedraw == ScaleInPlace && redrawType == Redraw {
					continue
				}
				lastRedraw = redrawType
				s := dw.Screen()
				if redrawType == Draw || redrawType == Redraw {
					width, height := dw.Size()

					tilesh := int(float64(width)/(float64(imageWidth)/scale) + 1)
					tilesv := int(float64(height)/(float64(imageHeight)/scale) + 1)

					tilecx := drawx / imageWidth
					tilecy := drawy / imageHeight

					tileMinX := int(-tilecx) - tilesh - 1
					tileMinY := int(-tilecy) - tilesv - 1
					tileMaxX := int(-tilecx) + tilesh + 1
					tileMaxY := int(-tilecy) + tilesv + 1

					if greyBack == nil || s.Bounds() != greyBack.Bounds() {
						bounds := s.Bounds()
						greyBack = image.NewRGBA(bounds)
						for x := bounds.Min.X; x <= bounds.Max.X; x++ {
							for y := bounds.Min.Y; y <= bounds.Max.Y; y++ {
								greyBack.SetRGBA(x, y, grey)
							}
						}
						screenBuffer = image.NewRGBA(bounds)
					}

					draw.Draw(screenBuffer, screenBuffer.Bounds(), greyBack, image.Point{0, 0}, draw.Src)

					for tilex := tileMinX; tilex <= tileMaxX; tilex++ {
						for tiley := tileMinY; tiley <= tileMaxY; tiley++ {
							scaledTile, ok := getScaledTile(tilex, tiley, scale)
							if !ok || scaledTile == nil {
								continue
							}

							dx, dy := mapToScreen(width, height, float64(tilex)*imageWidth, float64(tiley)*imageHeight)

							drawRect := scaledTile.Bounds()
							drawRect.Min.X += dx
							drawRect.Min.Y -= dy
							drawRect.Max.X += dx
							drawRect.Max.Y -= dy

							draw.Draw(screenBuffer, drawRect, scaledTile, image.Point{0, 0}, draw.Src)
						}
					}

					bufferScale = scale
					if xs, ok := s.(*xgraphics.Image); ok {
						copyToXGraphicsImage(xs, screenBuffer)
					} else {
						draw.Draw(s, s.Bounds(), screenBuffer, image.Point{0, 0}, draw.Src)
					}
				} else if redrawType == ScaleInPlace {
					scaleFactor := scale / bufferScale
					bufBounds := screenBuffer.Bounds()
					width := bufBounds.Max.X - bufBounds.Min.X
					height := bufBounds.Max.Y - bufBounds.Min.Y
					if scaleFactor < 1 {
						widthDiff := width - int(float64(width)*scaleFactor)
						heightDiff := height - int(float64(height)*scaleFactor)
						//bufBounds.Min.X += widthDiff / 2
						bufBounds.Max.X -= widthDiff
						//bufBounds.Min.Y += heightDiff / 2
						bufBounds.Max.Y -= heightDiff
						subBuffer := screenBuffer.SubImage(bufBounds)
						scaledBuffer := resize.Resize(subBuffer, subBuffer.Bounds(), width, height).(*image.RGBA)

						if xs, ok := s.(*xgraphics.Image); ok {
							copyToXGraphicsImage(xs, scaledBuffer)
						} else {
							draw.Draw(s, s.Bounds(), scaledBuffer, image.Point{0, 0}, draw.Src)
						}
					}
					if scaleFactor > 1 {
						scaleFactor = 1 / scaleFactor
						newWidth := int(float64(width) * scaleFactor)
						newHeight := int(float64(height) * scaleFactor)
						scaledBuffer := resize.Resize(screenBuffer, screenBuffer.Bounds(), newWidth, newHeight).(*image.RGBA)

						if xs, ok := s.(*xgraphics.Image); ok {
							copyToXGraphicsImage(xs, scaledBuffer)
						} else {
							draw.Draw(s, s.Bounds(), scaledBuffer, image.Point{0, 0}, draw.Src)
						}
					}
				}
				dw.FlushImage()
			case <-done:
				wg.Done()
				return
			}
		}
	}()

	wg.Wait()
	wde.Stop()
}
Пример #5
0
func GetImageGray(img *image.RGBA, offset image.Point) *image.Gray {
	imgGray := image.NewGray(img.Rect)
	draw.Draw(imgGray, imgGray.Rect, img.SubImage(img.Rect), offset, draw.Src)
	return imgGray
}