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  }