github.com/nevalang/neva@v0.23.1-0.20240507185603-7696a9bb8dda/internal/runtime/funcs/image_new.go (about) 1 package funcs 2 3 import ( 4 "context" 5 "image" 6 7 "github.com/nevalang/neva/internal/runtime" 8 ) 9 10 type imageNew struct{} 11 12 func (imageNew) Create(io runtime.FuncIO, _ runtime.Msg) (func(ctx context.Context), error) { 13 pixelsIn, err := io.In.Port("pixels") 14 if err != nil { 15 return nil, err 16 } 17 18 imgOut, err := io.Out.Port("img") 19 if err != nil { 20 return nil, err 21 } 22 23 errOut, err := io.Out.Port("err") 24 if err != nil { 25 return nil, err 26 } 27 28 return func(ctx context.Context) { 29 for { 30 im := make(map[pixelMsg]struct{}) 31 var ( 32 width int64 33 height int64 34 ) 35 stream: 36 for { 37 select { 38 case m := <-pixelsIn: 39 var pix pixelStreamMsg 40 pix.decode(m) 41 if pix.x < 0 || pix.y < 0 { 42 select { 43 case errOut <- runtime.NewMapMsg(map[string]runtime.Msg{ 44 "text": runtime.NewStrMsg("image.New: Pixel out of bounds"), 45 }): 46 case <-ctx.Done(): 47 return 48 } 49 } 50 if pix.x >= width { 51 width = pix.x + 1 52 } 53 if pix.y >= height { 54 height = pix.y + 1 55 } 56 im[pix.pixelMsg] = struct{}{} 57 if pix.last { 58 break stream 59 } 60 case <-ctx.Done(): 61 return 62 } 63 } 64 img := image.NewRGBA(image.Rect(0, 0, int(width), int(height))) 65 for pix := range im { 66 img.Set(int(pix.x), int(pix.y), pix.color.color()) 67 } 68 var i imageMsg 69 i.decodeImage(img) 70 select { 71 case imgOut <- i.encode(): 72 case <-ctx.Done(): 73 return 74 } 75 } 76 }, nil 77 }