// Computes the matrix3d that maps src points to dst.
function computeTransform(src, dst) {
// src and dst should have length 4 each
var count = 4;
var a = []; // (2*count) x 8 matrix
var b = []; // (2*count) vector
for (var i = 0; i < 2 * count; ++i) {
a.push([0, 0, 0, 0, 0, 0, 0, 0]);
b.push(0);
}
for (var i = 0; i < count; ++i) {
var j = i + count;
a[i][0] = a[j][3] = src[i][0];
a[i][1] = a[j][4] = src[i][1];
a[i][2] = a[j][5] = 1;
a[i][3] = a[i][4] = a[i][5] =
a[j][0] = a[j][1] = a[j][2] = 0;
a[i][6] = -src[i][0] * dst[i][0];
a[i][7] = -src[i][1] * dst[i][0];
a[j][6] = -src[i][0] * dst[i][1];
a[j][7] = -src[i][1] * dst[i][1];
b[i] = dst[i][0];
b[j] = dst[i][1];
}
var x = numeric.solve(a, b);
// matrix3d is homogeneous coords in column major!
// the z coordinate is unused
var m = [
x[0], x[3], 0, x[6],
x[1], x[4], 0, x[7],
0, 0, 1, 0,
x[2], x[5], 0, 1
];
var transform = "matrix3d(";
for (var i = 0; i < m.length - 1; ++i) {
transform += m[i] + ", ";
}
transform += m[15] + ")";
return transform;
}
// Collect the four corners by user clicking in the corners
var dst = [];
document.getElementById('frame').addEventListener('mousedown', function(evt) {
// Make sure the coordinates are within the target element.
var box = evt.target.getBoundingClientRect();
var point = [evt.clientX - box.left, evt.clientY - box.top];
dst.push(point);
if (dst.length == 4) {
// Once we have all corners, compute the transform.
var img = document.getElementById('img');
var w = img.width,
h = img.height;
var transform = computeTransform(
[
[0, 0],
[w, 0],
[w, h],
[0, h]
],
dst
);
document.getElementById('photo').style.visibility = 'visible';
document.getElementById('transform').style.transformOrigin = '0 0';
document.getElementById('transform').style.transform = transform;
document.getElementById('result').innerHTML = transform;
}
});
.container {
position: relative;
width: 50%;
}
#frame,
#photo {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
#photo {
visibility: hidden;
}
#frame img,
#photo img {
width: 100%
}
#photo {
opacity: 0.7;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/numeric/1.2.6/numeric.min.js"></script>
<p id="result">Click the desired top-left, top-right, bottom-right, bottom-left corners
<div class="container">
<div id="frame">
<img src="http://cdn.idesigned.cz/img/cc08acc7b9b08ab53bf935d720210f13.png" />
</div>
<div id="photo">
<div id="transform">
<img id="img" src="http://placehold.it/350x150" />
</div>
</div>
</div>