Is it possible to control the behavior of the canvas in vertical position?

When scaling a texture in a canvas, the behavior varies greatly across browsers.

Here is a fiddle creating a 2x1 texture (consisting of one black and one white text) and applying it to a 256x128px rectangle: https://jsfiddle.net/ozirus/x1c3m50o/

var texture = ...

var ctx = document.createElement("canvas").getContext("2d");
ctx.canvas.width = 512;
ctx.canvas.height = 512;
document.body.appendChild(ctx.canvas);
ctx.setTransform(128, 0, 0, 128, 0, 0);
ctx.fillStyle = ctx.createPattern(texture, "no-repeat");;
ctx.rect(0, 0, 2, 1);
ctx.fill("evenodd");

      

The following screenshots show the results when run in different browsers.

In Chrome:
Chrome

In Firefox:
Firefox

In IE11 / Edge:
IE / Edge

Are there any flags / options to control this behavior and make it more consistent?

The IE / Edge behavior where the last pixels are the result of wrap / repeat interpolation is the main problem I'm trying to solve.

PS: I am aware of some workarounds that could do the trick (half texel offset + scaling, transparent border on textures, ...), but I'd rather tweak this behavior if possible.

EDIT: as @Ryan pointed out in the comments, the property CanvasRenderingContext2D.imageSmoothingEnabled

can be used to match Nearest Neighbor behavior, but I want to keep smooth texture interpolation

+3


source to share


1 answer


Not.

There is no way to access code behind 2D API (CPU and GPU) from javascript. There are many holes in the standard and hence browser developers should interpret it, but it suits them.

If you use repeat, you get the same result as no-repeat on Edge in all three browsers.

On Edge, Firefox and Chrome with



ctx.fillStyle = ctx.createPattern(textureCanvas, "repeat");;

      

enter image description here

If you want the result to be as FF, use ctx.drawImage

to render a bitmap. If you need irregular shapes, then render with ctx.drawImage

then a mask with an outline and ctx.globalCompositeOperation = "destination-in"

. If you need to display existing canvas content, use a second canvas to render bitmaps and masks, and then render that canvas onto the existing content.

On Edge, Firefox and Chrome with



ctx.drawImage(textureCanvas,0,1,2,1);

      

enter image description here

If you want to get the same result as Chrome in all three browsers, you need to add a transparent border around the image and then render the center with two pixels.

Same result in Firefox, Edge and chrome in the example below (Copied and modified from your fiddle https://jsfiddle.net/ozirus/x1c3m50o/ )

var textureCanvas = document.createElement("canvas");
textureCanvas.width = 4;
textureCanvas.height = 3;
var textureContext = textureCanvas.getContext("2d");
var imgData = textureContext.createImageData(4, 3);
var i = 20;
imgData.data[i++] = 0;
imgData.data[i++] = 0;
imgData.data[i++] = 0;
imgData.data[i++] = 255;
imgData.data[i++] = 255;
imgData.data[i++] = 255;
imgData.data[i++] = 255;
imgData.data[i++] = 255;
textureContext.putImageData(imgData, 0, 0);

var ctx = document.createElement("canvas").getContext("2d");
ctx.canvas.width = 512;
ctx.canvas.height = 512;
document.body.appendChild(ctx.canvas);
ctx.setTransform(128, 0, 0, 128, 0, 0);
ctx.drawImage(textureCanvas,1,1,2,1,0,0,2,1);
      

html {
  background-color: red;
}
      

Run codeHide result


Yes.

So, I think this means that you can control this, but indirectly using different methods.

+2


source







All Articles