6

I have a canvas for showing medical image and I have another canvas for annotating images by draw shape or line.

when I draw a line on canvas#2 I want to copy drawn line on canvas#1 something like this:

  var context = canvas1.getContext('2d');
  context.drawImage(canvas2,0,0);

but because my canvas#1 has a getContext('webgl') I can't do that.

I mean how to simulate

  drawImage() for getcontext('webgl')?

I really appreciate any help or advice.

Regards;

Zohreh

radical7
  • 8,957
  • 3
  • 24
  • 33
Zohreh
  • 71
  • 1
  • 5

3 Answers3

1

Well, you could just use the toDataURL method of the webgl canvas to convert it into an image. Then draw it on the 2d context.

ctx2D.drawImage(webGLCanvas.toDataURL("image/png"), 0, 0);

In this case I believe you might have to set the preserveDrawingBuffer propertie of the webgl canvas to true when initializing it.

...getContext("webgl", {preserveDrawingBuffer: true});
Delta
  • 4,308
  • 2
  • 29
  • 37
  • thanks for your answer but I need completely Vice Versa. I want to copy image to canvas with contex('webgl'). – Zohreh Oct 31 '13 at 11:37
  • Sorry I got it all wrong then. It's a bit more complicated, in this case you'd have to get the 2D canvas image through toDataURL and use it as a texture on a square plane and draw it on the openGL context maybe using an ortho projection matrix. But I'm not into OpenGL stuff so I can't really help you with that =/ – Delta Nov 01 '13 at 22:27
  • I got empty image when try copy webgl to 2d. – CodeBy May 01 '18 at 07:54
1

You could use a 2D canvas as the on-screen canvas, and draw the WebGL canvas to it when updating the WebGL canvas before drawing whatever annotations on.

drawWebGLStuff(webGLCtx);

// Copy image data of WebGL canvas to 2D canvas.
// This should be done right after WebGL rendering,
// unless preserveDrawingBuffer: true is passed during WebGL context creation,
// since WebGL will swap buffers by default, leaving no image in the drawing buffer,
// which is what we want to copy.
ctx2D.drawImage(webGLCanvas, 0, 0);

drawAnnotations(ctx2D);

(The annotations could be rendered each frame from a list of shapes or drawn to another offscreen canvas, which is then drawn to the main (on-screen) canvas similar to the WebGL canvas.)

Or you can simply layer the canvases on the page with absolute positioning and z-index:

<div style="position: relative;">
   <canvas id="layer1" width="100" height="100" 
       style="position: absolute; left: 0; top: 0; z-index: 0;"></canvas>
   <canvas id="layer2" width="100" height="100" 
       style="position: absolute; left: 0; top: 0; z-index: 1;"></canvas>
</div>
1j01
  • 3,714
  • 2
  • 29
  • 30
1

I had a similar problem with Emscripten, needed to copy WebGL canvas to another empty canvas. I used this code but got empty screen.

var sourceCanvasWebGL = document.getElementById( "canvas" );
var destinationCanvas = document.getElementById( "canvasCopy" );
var destinationCanvasContext = destinationCanvas.getContext('2d');
destinationCanvasContext.drawImage(sourceCanvasWebGL, 0, 0);

After some googling (Saving canvas to image via canvas.toDataURL results in black rectangle) I figured out that because WebGL is using 2 buffers while drawing I am copying the old buffer with empty content.

Problem was solved by setting preserveDrawingBuffer: true in the code used to make WebGL drawing.

sourceCanvasWebGL.getContext("webgl2", { preserveDrawingBuffer: true })

P.S. As an alternative you could make an image copy right after rendering the canvas. If so you do not need preserveDrawingBuffer.

Michael Klishevich
  • 1,774
  • 1
  • 17
  • 17