【问题标题】:How to horizontally flip images already on the canvas?如何水平翻转画布上已有的图像?
【发布时间】:2017-03-31 13:48:43
【问题描述】:

在你把我赶出去之前 - 我知道this answer,但它似乎对我不起作用。不同之处还在于,在我的例子中,图像数据的来源是 WebGL 画布——而不是 img 节点。

我正在尝试将 ImageData 像这样放在画布上:

var c = document.createElement('canvas');
c.setAttribute('width', size.width);
c.setAttribute('height', size.height);

$('body').append(c)

// p contains a Uint8ClampedArray with imagedata coming from a WebGL canvas

var i = new ImageData(p, size.width, size.height);
var ctx = c.getContext('2d');
ctx.putImageData(i, 0, 0);

然后像这样翻转它:

var d = document.createElement('canvas');
d.width = c.width; d.height = c.height;
d.getContext('2d').drawImage(c, 0, 0);

ctx.clearRect(0, 0, c.width, c.height);
ctx.scale(-1, 1);
ctx.translate(c.width, 0);

ctx.drawImage(d, 0, 0);

但这失败得很惨。

数据来自这样的 WebGL 画布:

var gl = renderer.domElement.getContext("webgl")
var pixels = new Uint8Array(gl.drawingBufferWidth * gl.drawingBufferHeight * 4);
gl.readPixels(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight, gl.RGBA, gl.UNSIGNED_BYTE, pixels);

所以我认为像素阵列上的低级操作是一种解决方案,但在我开始之前,我想我会问一下。

我有一种预感,drawImage 对变换不敏感,但那会很有趣。请不要让我使用 toDataURL()

【问题讨论】:

标签: javascript html canvas webgl


【解决方案1】:

webGL 画布可以像图像一样使用。您不需要使用慢速的gl.readPixelsctx.setImageData 方法来移动图像数据

// where canvasGL is the webGL canvas and ctx is the 2D  canvas context
ctx.setTransform(1,0,0,-1,0,canvasGL.height);
ctx.drawImage(canvasGL,0,0);

【讨论】:

    【解决方案2】:

    在使用负宽度进行翻译时对我有用 ctx.translate(-c.width, 0);

    var webglReadPixelsData;
    
    // draw some webgl
    (function(){
    var
      ctx=webgl.getContext('webgl',{preserveDrawingBuffer:true}),
      p=ctx.createProgram(),
      vs=ctx.createShader(ctx.VERTEX_SHADER),
      fs=ctx.createShader(ctx.FRAGMENT_SHADER),
      vb=ctx.createBuffer()
    ;
    ctx.shaderSource(vs,"attribute vec2 p;void main(){gl_Position=vec4(p*2.-1.,0,1);}");
    ctx.compileShader(vs);
    ctx.shaderSource(fs,"void main(){gl_FragColor=vec4(sin(gl_FragCoord.x*.2+gl_FragCoord.y*.2),0,0,1);}");
    ctx.compileShader(fs);
    ctx.attachShader(p,vs);
    ctx.attachShader(p,fs);
    ctx.linkProgram(p);
    ctx.useProgram(p);
    
    ctx.bindBuffer(ctx.ARRAY_BUFFER,vb);
    ctx.bufferData(ctx.ARRAY_BUFFER,new Float32Array([0,0,1,0,1,1,0,1]),ctx.STATIC_DRAW);
    ctx.enableVertexAttribArray(0);
    ctx.vertexAttribPointer(0,2,ctx.FLOAT,false,0,0);
    ctx.viewport(0,0,ctx.canvas.clientWidth,ctx.canvas.clientHeight);
    ctx.drawArrays(ctx.TRIANGLE_FAN,0,4);
    
    webglReadPixelsData = new Uint8Array(ctx.drawingBufferWidth * ctx.drawingBufferHeight * 4);
    
    ctx.readPixels(0, 0, ctx.drawingBufferWidth,ctx.drawingBufferHeight, ctx.RGBA, ctx.UNSIGNED_BYTE, webglReadPixelsData);
    })();
    
    // Flip image data
    (function(){
    var ctx=canvas2d.getContext('2d');
    var id=new ImageData(webgl.clientWidth, webgl.clientHeight);
    id.data.set(webglReadPixelsData);
    ctx.putImageData(id,0,0);
    
    var d = intermediate;
    d.getContext('2d').drawImage(canvas2d, 0, 0);
    ctx.clearRect(0,0,ctx.canvas.clientWidth,ctx.canvas.clientHeight);
    
    ctx.scale(-1, 1);
    ctx.translate(-ctx.canvas.clientWidth, 0);
    
    ctx.drawImage(d, 0, 0);
    })();
    #webgl {display:block;outline:1px solid #f00;}
    #canvas2d{display:block;outline:1px solid #0f0;}
    #intermediate{outline:1px solid #00f;}
    <h1>WebGL Canvas</h1>
    <canvas id="webgl"></canvas>
    <h1>Intermediate Canvas</h1>
    <canvas id="intermediate"></canvas>
    <h1>2D Canvas</h1>
    <canvas id="canvas2d"></canvas>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-22
      • 2018-01-17
      • 1970-01-01
      • 2019-11-26
      • 2011-06-09
      相关资源
      最近更新 更多