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;
What is the best practice to do this?
I want to draw simple rectangle image to canvas. I have a four point like a;
Rendered rectangle and image are bellow;
What is the best practice to do this?
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.
With these assumptions adhered to, I get the following:
Result
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: