-
Notifications
You must be signed in to change notification settings - Fork 1
/
image.go
103 lines (93 loc) · 2.33 KB
/
image.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package main
import (
"image"
"image/draw"
"log"
"runtime/debug"
"github.com/maxsupermanhd/WebChunk/chunkStorage"
"github.com/maxsupermanhd/WebChunk/primitives"
"github.com/nfnt/resize"
)
func imageGetSync(loc primitives.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 primitives.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 primitives.ImageLocation) *ttypeProviderFunc {
for tt := range ttypes {
if tt.Name == loc.Variant {
f := ttypes[tt]
return &f // TODO: fix this ugly thing
}
}
return nil
}