Beispiel #1
0
func getScaledTile(x, y int, scale float64) (scaledTile image.Image, ok bool) {
	unscaled, ok := getTile(x, y)
	if !ok {
		return
	}
	stiles, ok := scaledTiles[scale]
	if !ok {
		stiles = map[int]map[int]chan image.Image{}
		scaledTiles[scale] = stiles
	}
	sxtiles, ok := stiles[x]
	if !ok {
		sxtiles = map[int]chan image.Image{}
		stiles[x] = sxtiles
	}
	scaledTileChan, ok := sxtiles[y]
	if !ok {
		bounds := unscaled.Bounds()
		s := bounds.Size()
		scaledTileChan = make(chan image.Image, 1)
		go func() {
			scaledTileChan <- resize.Resize(unscaled, unscaled.Bounds(), int(.5+float64(s.X)/scale), int(.5+float64(s.Y)/scale))
		}()
		sxtiles[y] = scaledTileChan
	}
	select {
	case scaledTile = <-scaledTileChan:
		scaledTileChan <- scaledTile
	default:
		ok = false
	}
	return
}
Beispiel #2
0
func Index() error {
	// Just a hardcoded path obviously needs to scan directory.
	file, err := os.Open("photos/IMG_0128.JPG")
	if err != nil {
		return err
	}
	img, err := jpeg.Decode(file)
	if err != nil {
		return err
	}
	file.Close()
	ratio := 500.0 / float32(img.Bounds().Max.X)
	new_height := int(ratio * float32(img.Bounds().Max.Y))
	resized := resize.Resize(img, img.Bounds(), 500, new_height)
	file, err = os.Create("photos/IMG_0128_THUMB.JPG")
	if err != nil {
		return err
	}
	jpeg.Encode(file, resized, &jpeg.Options{Quality: 100})
	file.Close()
	return nil
}
Beispiel #3
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()
}