I have an ImageData object which holds the screenshot of all monitors, so it is one huge ImageData. I want to now draw one monitor per time. I have all the monitor dimensions.
So I'm trying to use ctx.putImageData(myImgDat, topLeftMonX, topLeftMonY, monWidth, monHeight) but its not working, I dont think I understand the dirty concept so well as seen in docs: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/putImageData#Understanding_putImageData
Is it possible to draw portion of imgaedata to canvas?
Yes, it's possible, it doesn't work on your code is because your arugments passed is not met the format of the function.
As MDN CanvasRenderingContext2D.putImageData() describes, it accepts 3 or 7 arguments, you have to pass either 3 or 7, otherwise, in your example, monWidth and monHeight will be used as dirtyX and dirtyY instead of dirtyWidth and dirtyHeighy. You code would probably do
Copy the rect(monWidth, monHeight, IMAGEDATA_WIDTH, IMAGEDATA_HEIGHT).
Put it on canvas's rect(topLeftMonX + monWidth, topLeftMonY + monHeight, IMAGEDATA_WIDTH, IMAGEDATA_HEIGHT).
So, and it's somehow not very straight to put the target region to (0,0) of the target canvas, to achieve by your give condition, you may have to do:
First move imageData's (0,0) to target canvas's (-topLeftMonX,
-topLeftMonY).
Then start to put imageData at imageData's (topLeftMonX, topLeftMonY) which now is at the position (0, 0) of canvas.
The rectangle size will be topLeftMonX x topLeftMonY.
ctx.putImageData(myImgDat,-topLeftMonX, -topLeftMonY, topLeftMonX, topLeftMonY, monWidth, monHeight);
Code above will copy the rect(topLeftMonX, topLeftMonY, monWidth, monHeight) on myImgDat to: rect(0, 0, monWidth, monHeight) on canvas.
You can take a look at how it works from the snippet below.
var canvas = document.getElementById('bigCanvas')
,ctx = canvas.getContext('2d');
var tcanvas = document.getElementById('testCanvas')
,tctx = tcanvas.getContext('2d');
var grd = tctx.createRadialGradient(150, 100, 10, 150, 110, 150);
grd.addColorStop(0, "black");
grd.addColorStop(0.15, "blue");
grd.addColorStop(0.3, "cyan");
grd.addColorStop(0.5, "green");
grd.addColorStop(0.7, "yellow");
grd.addColorStop(0.85, "orange");
grd.addColorStop(1, "red");
tctx.fillStyle = grd;
tctx.fillRect(0, 0, 300, 200);
var imageData = tctx.getImageData(0, 0, 300, 200);
// Move imagedata's origin to (-150, -100) on canvas,
// start to put data on canvas at imgae data's (150, 100) and size is 150x100
// => copy rect(150, 100, 150, 100) to canvas' s rect (0, 0, 150, 100)
ctx.putImageData(imageData, -150, -100, 150, 100, 150, 100);
// Move imagedata's origin to (150, 100) on canvas,
//start to put data on canvas at imgae data's (0, 0) and and size is 150x100
// => copy rect(0, 0, 150, 100) to canvas' s rect (150, 100, 150, 100)
ctx.putImageData(imageData, 150, 100, 0, 0, 150, 100);
// Move imagedata's origin to (150, -100) on canvas,
// start to put data on canvas at imgae data's (0, 100) and size is 150x100
// => copy rect(0, 100, 150, 100) to canvas' s rect (150, 0, 150, 100)
ctx.putImageData(imageData, 150, -100, 0, 100, 150, 100);
// Move imagedata's origin to (-150, 100) on canvas,
// start to put data on canvas at imgae data's (200, 0) and size is 100x100
// => copy rect(200, 0, 150, 100) to canvas' s rect (50, 100, 150, 100)
ctx.putImageData(imageData, -150, 100, 200, 0, 100, 100);
<div>Canvas for put ImageData:</div>
<canvas id="bigCanvas" width="300" height="200"></canvas>
<hr/>
<div>Canvas for get ImageData:</div>
<canvas id="testCanvas" width="300" height="200"></canvas>
This is another solution:
var iref = imagedata.data;
// start - because took a single screenshot of alllll put togather, lets portion out the imagedata
console.time('portion out image data');
for (var i=0; i<collMonInfos.length; i++) {
var screenUseW = collMonInfos[i].w;
var screenUseH = collMonInfos[i].h;
var screnImagedata = new ImageData(screenUseW, screenUseH);
var siref = screnImagedata.data;
var si = 0;
for (var y=collMonInfos[i].y; y<collMonInfos[i].y+screenUseH; y++) {
for (var x=collMonInfos[i].x; x<collMonInfos[i].x+screenUseW; x++) {
var pix1 = (fullWidth*y*4) + (x * 4);
var B = iref[pix1];
siref[si] = iref[pix1+2];
siref[si+1] = iref[pix1+1];
siref[si+2] = B;
siref[si+3] = 255;
si += 4;
}
}
collMonInfos[i].screenshot = screnImagedata;
}
console.timeEnd('portion out image data');
I crop to square and draw an image to canvas
if(img.height >= img.width) {
ctx.drawImage(img, 0, 0, 110, 110 * img.height / img.width);
} else {
ctx.drawImage(img, 0 , 0, 110 * img.width / img.height, 110);
}
After the image is drawn, I convert to base64 using canvas.toDataURL(); and POST to server.
However before I convert and POST I would like to allow the user the ability to rotate the image 90 degrees before it's converted to base64.
I have a test setup HERE
Here's how to rotate your cropped image on a temporary canvas:
Then you can do tempCanvas.toDataURL for your POST.
create a temporary offscreen canvas
resize the temp canvas to fit resized+rotated image
translate to the middle of the temp canvas
rotate by 90 degrees
draw the resized image on the temp canvas
Demo: http://jsfiddle.net/m1erickson/VrV38/
Sample code:
// create a temporary canvas
var tempCanvas=document.createElement('canvas');
var tempCtx=tempCanvas.getContext('2d');
// resize the tempCanvas
tempCanvas.width=h;
tempCanvas.height=w;
// translate+rotate and draw the resized image to tempCanvas
tempCtx.translate(h/2,w/2);
tempCtx.rotate(Math.PI/2);
tempCtx.drawImage(canvas, 0,0,w,h, -w/2,-h/2,w,h);
I am trying to clip and display a very large image inside a canvas div.
Using basic calculations and drawImage I managed to clip the image around the pixel I want and display the clipped image.
An example is here on JSFiddle (displaying image arround eye of the person)
I would like to add an arc which will be over the image around the pixel (the sx, sy pixel I use in the example in drawImage), how should I adjust the coordinates ?
var canvas = document.getElementById('test-canvas');
canvas.width = 500;
canvas.height = 285;
var context = canvas.getContext('2d');
var imageObj = new Image();
imageObj.onload = function () {
//context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);
context.drawImage(imageObj, 1324 - 250, 1228 - 142.5, 500, 285, 0, 0, 500, 285);
};
imageObj.src = "http://upload.wikimedia.org/wikipedia/en/b/b3/Edvard_Munch_-_Self-Portrait_-_Google_Art_Project.jpg";
An arc is part of a path, which can be either filled or stroke. In order to get your desired result, you need to move to a point on your circle*, create the arc, and then use stroke() (fiddle):
function strokeCircle(ctx, midx, midy, radius){
ctx.moveTo(midx + radius, midy);
ctx.arc(midx, midy, radius, 0, 2 * Math.PI, false);
ctx.stroke();
}
imageObj.onload = function () {
context.drawImage(imageObj, 1324 - 250, 1228 - 142.5, 500, 285, 0, 0, 500, 285);
strokeCircle(context, 250, 142.5, 30);
};
* The correct coordinate depends on your polar coordinates used for the circle. If you draw from 0 to Math.PI, you need to start on the right-most point.
Is there a way to position a rectangle in Raphael.js based on the center coordinates (much like positioning a circle)?
You can do it by simply creating your own custom element, here is an example on how it can be done :
Raphael.fn.MyRect = function( cx, cy, width, height ) {
var xLeftTop = cx - (width / 2);
var yLeftTop = cy - (height / 2);
this.rectObj = paper.rect( xLeftTop, yLeftTop, width, height );
return this;
};
var paper = Raphael(10, 50, 320, 200);
paper.MyRect( 95, 35, 50, 50 ); // 95 is the center in x and 35 the center in y
A live example : http://jsfiddle.net/7QMbH/
This way, you can create as many rectangle you want, and it makes your code understandable.
The easiest way is to create your rectangle with coordinates x - rect_width/2 and y - rect_heigth/2:
Example:
var rect_w = 180,
rect_h = 80;
var paper = Raphael(10, 10, 500, 500);
paper.rect(100 - rect_w/2, 100 - rect_h/2, rect_w, rect_h, 5);
// The last 5 gives curved edges to you rectangle (if you need it of course).
Basically, instead of 100,100 for top-left, you give 10,60. Good Luck
I found this code to type on an arc in a Canvas element. I've modified it basically to what I need, but I'm not sure how to change the "starting point" of it?
I've got a demo here
circle = {
x: cnv.width / 2, // x coordinate of center
y: cnv.height / 2, // y coordinate of center
r: 150,
lw: 75
};
for example, giving as given below will plot it at the origin of the canvas
circle = {
x: 0, // x coordinate of center
y: 0, // y coordinate of center
r: 150,
lw: 75
};