Plot x and y coordinates on an image using javascript - javascript

I want to plot x and y coordinates on an image by drawing a circle around the point.
I am getting the image from the server as an array buffer. After the image is displayed i need to mark the corners in the image using coordinates sent as a json from a service.
How can i do this using javascript jquery?
I was thinking of doing the same by overlaying the image with a canvas layer.
How can i implement this?
I have tried the below method but the points were getting plotted outside the image
jQuery('#plotCoordinates').on('click',function(){
jQuery.getJSON( "plot.json", function( response ) {
console.log("response >> " ,response);
var imageCanvas = $('#imageCan');
jQuery.each(response,function(i,obj){
console.log('obj >> ',obj);
point = $('<div class="plot-point"></div>');
x = obj.x,
y = obj.y;
point.css({
left: x + "px",
top: y + "px"
});
point.appendTo(imageCanvas);
});
});
});

You can certainly do it using a canvas.Do the following steps-->
Draw image on canvas as image size=canvas size.
Now, overlay another canvas with a higher z-index exactly on the previous canvas(canvas is transparent by default).
Now use the coordinates of the points you fetched using json to mark the corners in the image by plotting them on this overlayed canvas.
Then you can draw circles around these points on the upper canvas using simple context functions.
As canvas size is same as image size these coordinates will exactly coincide and you can achieve want you want :).In short you draw your circles and markings on the upper canvas and simply draw image on the lower canvas.Easy huhh??:)
Note:Both the canvases and the image itself should be of equal dimensions to exactly coincide.
Have a look at this example https://jsfiddle.net/rbrv949d/
<canvas id="c" style="z-index: 1;"></canvas>
<canvas id="cover" style="z-index: 2;"></canvas>
JS onload
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
var canover=document.getElementById('cover');
var ctxover = canvas.getContext('2d');
// Create an image element
var img = new Image();
// When the image is loaded, draw it
img.onload = function () {
ctx.drawImage(img, 0, 0);
ctxover.fillRect(0,0,10,10);
ctxover.fillRect(0,20,10,10);
}
// Specify the src to load the image
img.src = "http://www.experts-exchange.com/images/experts-exchange/experts-exchange-logo.png";
canvas.width=img.width;
canvas.height=img.height;
canover.width=img.width;
canover.height=img.height;
Here , ctxover.fillRect(xposition,yposition,widthinpixels,heightinpixels)
In your case,the xposition and yposition are the one fetched from json.
You can also draw those markings on the same canvas without using the overlayed canvas.Its upto you.Provided if you clear this canvas those markings will also get cleared unlike the other case :)

Related

How to detect transparent area click OR if user draw in transparent area in canvas?

I'm drawing an image onto a canvas using drawImage. It's a PNG that is surrounded by transparent pixels, like this:
How can I detect a drawing move path in the transparent part of that image on the canvas? I want to detect if a user draws in a transparent part.
I am trying this tutorial and I did as showing in the tutorial.
var ctx = canvas.getContext('2d'),
img = new Image;
img.onload = draw;
img.src = "http://i.stack.imgur.com/UFBxY.png";
function draw() {
// draw original image in normal mode
ctx.drawImage(img, 10, 10);
}
<canvas id=canvas width=500 height=500></canvas>
Check it out full code on Github
Check it out live demo IonCanvas
To find out is a pixel is transparent get the pixel using ctx.getImageData and look at the alpha value.
Example
// assumes ctx is defined
// returns true if pixel is fully transparent
function isTransparent(x, y) { // x, y coordinate of pixel
return ctx.getImageData(x, y, 1, 1).data[3] === 0; // 4th byte is alpha
}

How to create an image generator for combining multiple images?

I am working on an image generator using HTML5 canvas and jQuery/JS. What I want to accomplish is the following.
The user can upload 2 or max 3 images (type should be png or jpg) to the canvas. The generated images should always be 1080x1920. If the hart uploads only 2 images, the images are 1080x960. If 3 images are uploaded, the size of each image should be 1080x640.
After they upload 2 or 3 images, the user can click on the download button to get the merged image, with a format of 1080x1920px.
It should make use of html canvas to get this done.
I came up with this:
HTML:
<canvas id="canvas">
Sorry, canvas not supported
</canvas><!-- /canvas.offers -->
<input id="fileInput" type="file" />
Generate
jQuery:
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
canvas.height = 400;
canvas.width = 800;
var img1 = loadImage('http://www.shsu.edu/dotAsset/0e829093-971c-4037-9c1b-864a7be1dbe8.png', main);
var img2 = loadImage('https://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/Ikea_logo.svg/266px-Ikea_logo.svg.png', main);
var minImages = 2;
var imagesLoaded = 0;
function main() {
imagesLoaded += 1;
if(imagesLoaded >= minImages) {
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.save();
ctx.drawImage(img1, 0, 0);
// ctx.translate(canvas.height/2,canvas.width/2); // move to the center of the canvas
// ctx.rotate(270*Math.PI/180); // rotate the canvas to the specified degrees
// ctx.drawImage(img2,0,canvas.height/2);
ctx.translate(-canvas.height/2,canvas.width/2); // move to the center of the canvas
ctx.rotate(90*Math.PI/180); // rotate the canvas to the specified degrees
ctx.drawImage(img2,-img2.width/2,-img2.width/2);
ctx.restore(); // restore the unrotated context
}
}
function loadImage(src, onload) {
var img = new Image();
img.onload = onload;
img.src = src;
console.log(img);
return img;
}
Above code will create the canvas and place both images (that are now hard-coded in JS) to the created canvas. It will rotate 90 degrees, but it will not position to the right corner. Also the second image should be position beside the first one.
How can I do the rotation and positioning of each image side by side?
Working Fiddle: https://jsfiddle.net/8ww1x4eq/2/
Have a look at the updated jsFiddle, is that what you wanted?
Have a look here regarding image rotation
Updated jsFiddle, drawing multiple images.
Notice:
The save script was just a lazy way to make sure I've got the
external scripts loaded before I save the merged_image...
There is no synchornisation in the sample script, notice that addToCanvas
was called on image loaded event, there could be a race condition
here (but I doubt it, since the image is loaded to memory on
client-side)
function addToCanvas(img) {
// resize canvas to fit the image
// height should be the max width of the images added, since we rotate -90 degree
// width is just a sum of all images' height
canvas.height = max(lastHeight, img.width);
canvas.width = lastWidth + img.height;
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (lastImage) {
ctx.drawImage(lastImage, 0, canvas.height - lastImage.height);
}
ctx.rotate(270 * Math.PI / 180); // rotate the canvas to the specified degrees
ctx.drawImage(img, -canvas.height, lastWidth);
lastImage = new Image();
lastImage.src = canvas.toDataURL();
lastWidth += img.height;
lastHeight = canvas.height;
imagesLoaded += 1;
}
PS: I've added some script to download the merged image, but it would fail. The error message was: "Uncaught SecurityError: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported."
I've done a quick Google search and it seemed to be related to Cross-origin resources. I assumed that it wouldn't be an issue with FileReader. I haven't had time to test that so please test it (and please let me know :) It works with FileReader!
You can use toDataURL. But in this way user must do something like Save image as...
var img = canvas.toDataURL("image/png");
And then set for example img result src:
$("#result").attr("src",img);
Canvas is already an Image.
The canvas and img are interchangeable so there is no need to add the risky step of canvas.toDataURL which can fail depending on the image source domain. Just treat the canvas as if it were and img and put it in the DOM. Converting to a jpg does not save space (actually a resource hungry operation) as the an img needs to be decoded before it can be displayed.
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
canvas.height = 400;
canvas.width = 800;
document.body.appendChild(canvas); // add to the end of the document
// or add it to a containing element
var container = document.getElementById("containerID"); // or use JQuery
if(container !== null){
container.appendChild(canvas);
}

Responsive Canvas in Bootstrap

I'm trying to do a responsive canvas. All my tests has been doing with a 600x600 canvas and with that height and width it works OK and paint every line correctly. The problem is that I have tried this:
#myCanvas {
background-color: #ffffff;
border:1px solid #000000;
min-height: 600px;
height: 100%;
width: 100%;
}
Just for the record, myCanvas is inside a sm-col-8.
And it looks nice on my laptop and looks nice on my phone but (because of my draw() function, because it was thinking for a square) the draw starts more like in the down-left corner (nearby) and it should start at up-right corner.
So, I don't want to change my draw() function but what I'm looking for is to reescale the canvas size. I mean: If I'm in a laptop/tablet.. with 600x600, show it at that size, but if I'm on my phone which has 384x640 show it like 300x300? I don't know if it could be a good solution.
My draw function:
function drawLines(lines,i,table,xtotal,ytotal){
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var xIni;
var xFin;
var yIni;
var yFin;
xIni = (c.width*parseInt(lines[i][1])/xtotal);
yIni = (c.height*parseInt(lines[i][2])/ytotal);
xFin = (c.width*parseInt(lines[i][3])/xtotal);
yFin = (c.height*parseInt(lines[i][4])/ytotal);
ctx.beginPath();
ctx.moveTo(xIni,c.height-yIni);
ctx.lineTo(xFin,c.height-yFin);
ctx.lineWidth=4;
ctx.strokeStyle = colorAleatorio();
ctx.stroke();
}
With Bootstrap, use:
<canvas id="canvas" class='img-responsive' style="border: 1px solid black;"></canvas>
You can make your html Canvas responsive by using the context.scale command.
The .scale command will scale the internal coordinates system used by canvas.
This means you do not need to change any of your own drawing coordinates because canvas will automatically transform your coordinates into scaled canvas coordinates for you.
// save the original width,height used in drawLines()
var origWidth=600;
var origHeight=600;
var scale=1.00;
// reference to canvas and context
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
// call this after resizing
// send in the new maximum width,height desired
function resizeAndRedraw(newMaxWidth,newMaxHeight){
// calc the global scaling factor that fits into the new size
// and also maintains the original aspect ratio
scale=Math.min((newMaxWidth/origWidth),(newMaxHeight/origHeight))
// resize the canvas while maintaining correct aspect ratio
canvas.width=origWidth*scale;
canvas.height=origHeight*scale;
// Note: changing the canvas element's width or height will
// erase the canvas so you must reissue all your drawing commands
drawLines(lines,i,table,xtotal,ytotal);
}
// call drawLines
function drawLines(lines,i,table,xtotal,ytotal){
// scale the canvas coordinate system to the current scale
// Note: This scales the coordinates used internally
// by canvas. It does not resize the canvas element
ctx.scale(s,s);
// now do your drawing commands
// You do not need to adjust your drawing coordinates because
// the Canvas will do that for you
var xIni;
var xFin;
var yIni;
var yFin;
xIni = (c.width*parseInt(lines[i][1])/xtotal);
yIni = (c.height*parseInt(lines[i][2])/ytotal);
xFin = (c.width*parseInt(lines[i][3])/xtotal);
yFin = (c.height*parseInt(lines[i][4])/ytotal);
ctx.beginPath();
ctx.moveTo(xIni,c.height-yIni);
ctx.lineTo(xFin,c.height-yFin);
ctx.lineWidth=4;
ctx.strokeStyle = colorAleatorio();
ctx.stroke();
// restore the context to it's unscaled state
ctx.scale(-s,-s);
}

HTML5/ Javascript - Stretch image source

Hi I'm getting image from webcam and I save it on canvas, what I want to do is to stretch it by x and y cooridnates keeping same img dimensions, what I mean is, this is the original webcam picture:
and this is how I wanna it to be when stretched:
<canvas id="canvas" width="640" height="480" style="border:1px solid #d3d3d3;"></canvas>
this is the piece of code that shows source image to <img> element in html , so I have to stretch source image before to show it in html
function snap() {
if (localMediaStream) {
ctx.drawImage(video, 0, 0);
var oImg=document.createElement("img");
oImg.setAttribute('src', canvas.toDataURL());
oImg.setAttribute('alt', 'na');
oImg.setAttribute('width', '1300');
oImg.setAttribute('height', '1300');
var img = document.body.appendChild(oImg);
return img;
}
}
any idea on how to stretch the canvas.toDataUrL() source by x and y coordinates and return it stretched to the the src <img> element?
The real problem imo is how to stretch image without altering width
and height (as shown via example photos above), is this possible?
You can use the extended properties on context.drawImage that allow scaling/positioning.
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var img=new Image();
img.onload=function(){
var w=img.width;
var h=img.height;
canvas.width=w; // set the canvas size to the original image size
canvas.height=h;
ctx.drawImage(img,
0,0,w,h, // start with the image at original size
-w/4,0,w*1.25,h // widen the original image by 1.25X
// and start drawing 1/4th off the left edge of the canvas
);
}
img.src="temp18.png";

Add click event to canvas or make area map

I write this html code :
<div id="container">
<canvas id="imageView" width="1181" height="1181">
<p>Unfortunately, your browser is currently unsupported by our web
application.</p>
</canvas>
<script type="text/javascript">
window.onload = function() {
var c = document.getElementById('imageView');
var cxt = c.getContext('2d');
var img = new Image();
img.src = "map.jpg";
cxt.drawImage(img, 0, 0);
};
</script>
</div>
And write this javascript :
this.mousemove = function(ev) {
if (!tool.started) {
return;
}
var x = Math.min(ev._x, tool.x0),
y = Math.min(ev._y, tool.y0),
w = Math.abs(ev._x - tool.x0),
h = Math.abs(ev._y - tool.y0);
context.clearRect(0, 0, canvas.width, canvas.height);
if (!w || !h) {
return;
}
context.clearRect(x, y, w, h);
context.strokeRect(x, y, w, h);
this code is make a rectangle . I want change this rectangle to a area map , that when I click on the area do something , (for example open google.com) .
If I understand you correctly you want to invoke a function when you hit a pixel on the actual map - not just in the map area.
Method 1
You can check a map click in more than one way. You can simply check for the pixel value at the click point to check if it is inside the area you want it to be by comparing the map color value.
I provided an example below for this method.
Method 2
You can pre-define a polygon which traces the outline of the map area you want to check.
Then build a path (ctx.beginPath(); and ctx.lineTo(..); etc.) to allow the use of the method:
if (ctx.isPointInPath(x, y)) { ... };
This is a good method if you have small regions to check.
Method 3
Store a separate image of the map containing only a matte (sort of an alpha map), That is usually black (or transparent) for non-clickable areas, white for clickable areas.
This is useful if your map is complex color-wise and a simple pixel value check is not trivial.
And speaking of which: you can even provide different solid color values for different areas so that you can define red color = USA, blue = Argentina, etc. As these are not visible to the user the only thing that matters is that the color value can be recognized (for this reason don't save images for this use with an ICC color profile).
Then project the mouse position from the click onto the matte image (which is basically an off-screen canvas where the matte image is drawn into) and check for the color (white or other color).
Example for method 1
This is a simple example, but in any case there are a couple of things you need to know in advance:
That the image is loaded from same server as the page or from a domain that allow cross-origin use. Or else you cannot grab a pixel from the map due to security reasons.
You need to know what color or alpha value to check for. If the map is solid and everything is transparent you just need to check for alpha value above zero (as in this example), and if not just check the RGB value of the region you want to trigger an action with.
ONLINE DEMO HERE
HTML:
<canvas width=725 height=420 id="demo"></canvas>
JavaScript:
var ctx = demo.getContext('2d'),
img = new Image();
/// we need to wait for the image to actually load:
img.onload = function() {
/// image is loaded and we can raw it onto canvas
ctx.drawImage(this, 0, 0);
/// enable mouse click
demo.onclick = function(e) {
/// adjust mouse position to be relative to canvas
var rect = demo.getBoundingClientRect(),
x = e.clientX - rect.left,
y = e.clientY - rect.top;
/// grab a pixel
var data = ctx.getImageData(x, y, 1, 1).data;
/// check it's alpha value to see if we're in a map point
/// this of course assumes the map has transparent areas.
/// if not just check for the color values instead.
if (data[3] > 0) alert('We hit map');
}
}
/// we need crossOrigin allowed image or we can't grab pixel later
img.crossOrigin = 'anonymous';
img.src = 'http://i.imgur.com/x8Ap3ij.png';
Just replace the alert with:
window.open('http://google.com/');
if you want it to open a new window/tab.
You can turn canvas into an anchor link by using addEventListener to listen for clicks on the canvas.
Then you can use window.open to open google in a new browser tab.
Also, you need to use image.onload to give your image time to load before using drawing it.
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var img=new Image();
img.onload=function(){
ctx.drawImage(img,0,0);
canvas.addEventListener("click",function(){
window.open("http://google.com");
});
}
img.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/google.jpg";

Categories