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, } }
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 } } }
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 }
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() }
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 }