Copy image from GraphicsContext to sprite

Hi everyone! Do you know how to copy any image content from canvas’s GraphicsContext into any Image() or Sprite() object. There is no getPixel in gc and no getImage in gc. And when I tried to replicate paths/fills with app.useTool() it showed it can’t draw with “polygon” tool properly, which requires multiple strokes, using app.useTool()… :frowning: What do you think?

The beta branch introduced a context property to Image.

I’ve not tried this myself. The first issue I’d anticipate is I thought that gc’s were RGB24, no transparency, but hard to say until it releases.

I tried using contour instead of polygon for filled shapes in the past, but had to disable it. Not sure why it worked on one computer and not another, but it wasn’t consistent.

1 Like

Tried to switch to beta now, but image.context is not yet available to me. Hmmmph.

For anyone who needs polygon-drawing (convex only) functionality not bound by GraphicsContext only (just replace gc:fillRect with your scanline func and sh and RH with your max heights in frows):

  local fxn,fyn = math.max(sw, RW),math.max(sh, RH)
  local fyl,fyh,fxl,fxh,fxp,fyp,fxs,fys = 0,-1,{},{},nil,nil,0,0
  function fadd(y, x)
    if y < 0 or y > fyn then return end
    if fyl > fyh then fxl[y],fxh[y],fyl,fyh = x,x,y,y return end
    if y < fyl then for cy=y,fyl-1 do fxl[cy],fxh[cy]=fxn,-1 end; fyl,fxl[y],fxh[y] = y,x,x; return end
    if y > fyh then for cy=fyh+1,y do fxl[cy],fxh[cy]=fxn,-1 end; fyh,fxl[y],fxh[y] = y,x,x; return end
    if x < fxl[y] then fxl[y] = x end
    if x > fxh[y] then fxh[y] = x end
  end
  function fbegin(x, y) fyl,fyh,fxp,fyp,fxs,fys = 0,-1,x,y,x,y end
  function fpoint(x, y)
    local xp,yp = fxp,fyp; fxp,fyp = x,y
    local y1,y2 = math.floor(yp + 0.5),math.floor(y + 0.5)
    if y1 == y2 then fadd(yp, xp); fadd(yp, x); return end
    local n = math.abs(y2-y1)
    local xx,sx = xp+0.5,(x-xp)/n;
    local yy,sy = y1, y1 < y2 and 1 or -1
    for i=1,n do fadd(yy, xx); xx = xx + sx; yy = yy + sy end
  end
  function ffill1(gc, cc)
    gc.color = cc
    fpoint(fxs,fys); for y=fyl,fyh do local x1,x2 = fxl[y],fxh[y]; if x1 ~= nil and x1 <= x2 then
      gc:fillRect(Rectangle( x1, y, x2 - x1 + 1, 1 ))
    end; end
  end
  local fbr=Brush{type=BrushType.SQUARE, size=1}
  function ffill2(cc)
    fpoint(fxs,fys); for y=fyl,fyh do local x1,x2 = fxl[y],fxh[y]; if x1 ~= nil and x1 <= x2 then
      app.useTool{ tool="pencil", color=cc, brush=fbr, points={ Point(x1, y), Point(x2, y) },
                   layer=app.activeLayer, frame=app.activeFrame, ink=Ink.SIMPLE, opacity=255,
                   button=MouseButton.LEFT }
    end; end
  end
  function ffill(gc, ci)
    local cc = palet:getColor(ci)
    if gc ~= nil then ffill1(gc, cc) else ffill2(cc) end
  end

And usage example:

  fbegin(100, 50)
  fpoint(150, 25)
  fpoint(160, 35)
  ffill(nil, 10)