Skip to content

Commit

Permalink
That's kinda working
Browse files Browse the repository at this point in the history
  • Loading branch information
maxsupermanhd committed Nov 26, 2023
1 parent 0ef66ec commit 825869d
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 85 deletions.
185 changes: 101 additions & 84 deletions image.go
Original file line number Diff line number Diff line change
@@ -1,86 +1,103 @@
package main

// type imagingTask struct {
// target imagecache.ImageLocation
// in chan imagecache.ImageCache
// out chan *image.RGBA
// }

// var (
// imageScaleProcess = make(chan imagingTask, 256)
// )

// func imagingWorker(tasks <-chan imagingTask) {
// for t := range tasks {
// if t.target.S < imageCacheStorageLevel {
// from := <-t.in
// t.out <- imageScaleGetWithin(from.img, t.target)
// } else {
// log.Println("Unimplemented scaler > imageCacheStorageLevel")
// }
// }
// }

// func imagingProcessor(ctx context.Context) {
// var wg sync.WaitGroup

// sn := cfg.GetDSInt(4, "imaging_workers")
// wg.Add(sn)
// for i := 0; i < sn; i++ {
// go func() {
// imagingWorker(imageScaleProcess)
// wg.Done()
// }()
// }

// <-ctx.Done()
// log.Println("Image worker shutting down")
// close(imageScaleProcess)

// wg.Wait()
// log.Println("Image worker shutdown")
// }

// // gets subsection from image based in icIN
// func imageScaleGetWithin(from *image.RGBA, target imagecache.ImageLocation) *image.RGBA {
// // target image size
// is := powarr16[target.S]

// // TODO: probably reuse buffers with sync.Pool
// ret := image.NewRGBA(image.Rectangle{image.Point{0, 0}, image.Point{is, is}})

// // absolute position of the target
// ax, az := target.X*powarr[target.S], target.Z*powarr[target.S]

// // input relative position of the target
// ix, iz := icIN(ax, az)

// pt := image.Point{(ix / powarr[target.S]) * is, (iz / powarr[target.S]) * is}
// draw.Draw(ret, ret.Rect, from, pt, draw.Over)

// return ret
// }

// // stitches multiple images together
// func imageScaleGetFrom(from <-chan imageTask, target imagecache.ImageLocation) *image.RGBA {
// // TODO: probably reuse buffers with sync.Pool
// is := powarr16[target.S]

// ret := image.NewRGBA(image.Rectangle{image.Point{0, 0}, image.Point{is, is}})

// // TODO: scale down images
// return ret
// }

// func imageGetSync(loc imagecache.ImageLocation, ignoreCache bool, doDrawing bool) (*image.RGBA, error) {
// if !ignoreCache {
// i := imageCacheGetBlockingLoc(loc)
// if i != nil {
// return i, nil
// }
// }
// if doDrawing {

// }
// return nil, nil
// }
import (
"image"
"image/draw"
"log"
"runtime/debug"

"github.com/maxsupermanhd/WebChunk/chunkStorage"
imagecache "github.com/maxsupermanhd/WebChunk/imageCache"
"github.com/nfnt/resize"
)

func imageGetSync(loc imagecache.ImageLocation, ignoreCache bool) (*image.RGBA, error) {
if !ignoreCache {
i := imageCacheGetBlockingLoc(loc)
if i != nil {
return i, nil
}
}
img, err := renderTile(loc)
if err != nil {
return img, err
}
if img != nil {
imageCacheSaveLoc(img, loc)
}
return img, err
}

func renderTile(loc imagecache.ImageLocation) (*image.RGBA, error) {

f := findTTypeProviderFunc(loc)
if f == nil {
log.Printf("Image variant %q was not found", loc.Variant)
return nil, nil
}
ff := *f

_, s, err := chunkStorage.GetWorldStorage(storages, loc.World)
if err != nil {
return nil, nil
}
getter, painter := ff(s)

scale := 1
if loc.S > 0 {
scale = int(2 << (loc.S - 1)) // because math.Pow is very slow (43.48 vs 0.1881 ns/op)
}

imagesize := scale * 16
if imagesize > 512 {
imagesize = 512
}

img := image.NewRGBA(image.Rect(0, 0, int(imagesize), int(imagesize)))
imagescale := int(imagesize / scale)
offsetx := loc.X * scale
offsety := loc.Z * scale
cc, err := getter(loc.World, loc.Dimension, loc.X*scale, loc.Z*scale, loc.X*scale+scale, loc.Z*scale+scale)
if err != nil {
return nil, err
}
if len(cc) == 0 {
return nil, nil
}
for _, c := range cc {
// TODO: break on cancel
placex := int(c.X - offsetx)
placey := int(c.Z - offsety)
var chunk *image.RGBA
chunk = func(d interface{}) *image.RGBA {
defer func() {
if err := recover(); err != nil {
log.Println(loc.X, loc.Z, err) // TODO: pass error outwards
debug.PrintStack()
}
chunk = nil
}()
var ret *image.RGBA
ret = nil
ret = painter(d)
return ret
}(c.Data)
if chunk == nil {
continue
}
tile := resize.Resize(uint(imagescale), uint(imagescale), chunk, resize.NearestNeighbor)
draw.Draw(img, image.Rect(placex*int(imagescale), placey*int(imagescale), placex*int(imagescale)+imagescale, placey*int(imagescale)+imagescale),
tile, image.Pt(0, 0), draw.Over)
}
return img, nil
}

func findTTypeProviderFunc(loc imagecache.ImageLocation) *ttypeProviderFunc {
for tt := range ttypes {
if tt.Name == loc.Variant {
f := ttypes[tt]
return &f // TODO: fix this ugly thing
}
}
return nil
}
15 changes: 14 additions & 1 deletion ws.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,20 @@ func wsClientHandler(w http.ResponseWriter, r *http.Request, ctx context.Context
subbedTiles := map[imagecache.ImageLocation]bool{}

asyncTileRequestor := func(loc imagecache.ImageLocation) {
ret := marshalBinaryTileUpdate(loc, imageCacheGetBlockingLoc(loc))
img, err := imageGetSync(loc, false)
if err != nil {
b, _ := json.Marshal(map[string]any{
"Action": "message",
"Data": fmt.Sprintf("Error rendering tile %s: %s", loc.String(), err),
})
wQ <- wsmessage{
msgType: websocket.TextMessage,
msgData: b,
}
return
}
// TODO: fix time of check time of use
ret := marshalBinaryTileUpdate(loc, img)
if !wQdidClose.Load() {
wQ <- wsmessage{
msgType: websocket.BinaryMessage,
Expand Down

0 comments on commit 825869d

Please sign in to comment.