2

I want to draw simple rectangle image to canvas. I have a four point like a;

  • (0) 345,223
  • (1) 262,191
  • (2) 262,107
  • (3) 347,77

Rendered rectangle and image are bellow;

render image

What is the best practice to do this?

Omer Faruk Zorlu
  • 371
  • 1
  • 18

1 Answers1

2

Well that was some fun. Haven't done software texture mapping in over 10 years. Nostalgia is great, but openGL is better. :D

Basically, the idea is to draw vertical slices of the image. The ctx only lets us draw images or parts of them with vertical or horizontal stretching. So, to get around this, we divide the image up into vertical slices, stretching each of them to fill a rectangle 1 pixel wide and from the top edge to the bottom edge.

First, we calculate the slope of the top and bottom edges. This corresponds to the amount that the edge rises (or falls) for each pixel travelled in the +X direction. Next, since the image may be larger or smaller than the are it will be draw onto, we must calculate how wide the strips are that correspond to 1 pixel in the X direction in the canvas.

Note, it isn't perspective-correct. Each step to the right on the canvas represents a step of the same width slice on the image - perspective correct mapping would step by varying amounts across the width of the image. Less as the image got closer, more as the image was further away from us.

Finally, it should be noted that there are a few assumptions made about the entered coordinates.

  1. The coords appear as pairs of x and y
  2. The coords list starts with the top-left corner
  3. The coords must be listed in a clockwise direction
  4. The left-edge and the right-edge must be vertical.

With these assumptions adhered to, I get the following:

Result enter image description here

Code:

<!DOCTYPE html>
<html>
<head>
<script>
function byId(e){return document.getElementById(e);}
function newEl(tag){return document.createElement(tag);}

window.addEventListener('load', onDocLoaded, false);

function onDocLoaded()
{
    var mImg = newEl('img');
    mImg.onload = function() { stretchImage(this, quadPoints, byId('tgtCanvas') ); }
    mImg.src = imgSrc;
}

var quadPoints = [ [262,107], [347,77], [347,223], [262,191]  ];
var imgSrc = "img/rss128.png";

function stretchImage(srcImgElem, points, canvasElem)
{
    var ctx = canvasElem.getContext('2d');

    var yTopStart = points[0][1];
    var yTopEnd = points[1][1];
    var tgtWidth = points[1][0] - points[0][0];
    var dX = tgtWidth;
    var topDy = (yTopEnd-yTopStart) / dX;

    var yBotStart = points[3][1];
    var yBotEnd = points[2][1];
    tgtWidth = points[2][0] - points[3][0];
    dX = tgtWidth;
    var botDy = (yBotEnd-yBotStart) / dX;

    var imgW, imgH, imgDx;
    imgW = srcImgElem.naturalWidth;
    imgH = srcImgElem.naturalHeight;
    imgDx = imgW / dX;

    var curX, curYtop, curYbot, curImgX;
    var i = 0;
//  ctx.beginPath();
    for (curX=points[0][0]; curX<points[1][0]; curX++)
    {
        curYtop = yTopStart + (i * topDy);
        curYbot = yBotStart + (i * botDy);

        curImgX = i * imgDx;

//      ctx.moveTo(curX, curYtop);
//      ctx.lineTo(curX, curYbot);

        var sliceHeight = curYbot - curYtop;
//      console.log(sliceHeight);
        ctx.drawImage(srcImgElem, curImgX, 0, 1,imgH, curX, curYtop, imgDx, sliceHeight);

        i++;
    }
//  ctx.closePath();
//  ctx.stroke();
}

</script>
<style>
canvas
{
    border: solid 1px black;
}
</style>
</head>
<body>
    <canvas width=512 height=512 id='tgtCanvas'></canvas>
</body>
</html>

Src image: enter image description here

enhzflep
  • 12,927
  • 2
  • 32
  • 51
  • its corrects for that points. How can i do this in other rectangles. please check following link to see my sample http://zor.lu/lab1/domino1/cube_2.html – Omer Faruk Zorlu Jul 14 '14 at 09:59
  • Huh. Funny, I'd thought the mention of persepctive-correctness would be entirely irelevant, but wanted to makes sure. Well, in your case, you need to interpolate the screen position's Y _and_ X coordinates, also the texture U,V coords (x and y for the texture). You'll need to find/port different code for what is essentially a different question. These two links may be of interest: http://tulrich.com/geekstuff/canvas/perspective.html and http://learningwebgl.com/blog/?p=507 – enhzflep Jul 14 '14 at 10:06
  • Also check out http://stackoverflow.com/questions/4097688/draw-distorted-image-on-html5s-canvas/30088700#30088700 – Andy Poes May 21 '15 at 02:47