i am creating a image slider with html5 and jquery what i want to do is add 3 images on top of each other in one canvas and then get pixeldata of first image and remove some of it's pixels to show 2nd image through first i'm using jCanvas
Plug-in To Do This In Jquery What I've Got So Far Is
$(document).ready(function(){
function invert() {
$("canvas").setPixels({
x: 150, y: 150,
width: 100, height: 75,
// loop through each pixel
each: function(px) {
px.r = 255 - px.r;
px.g = 255 - px.g;
px.b = 255 - px.b;
px.a = 255 - px.a;
}
});
}
$("canvas")
.addLayer({
method: "drawImage",
source: "images/01.jpg",
x: 100, y: 100,
width: 480, height: 440
}).addLayer({
method: "drawImage",
source: "images/02.jpg",
x: 100, y: 100,
width: 380, height: 340
}).addLayer({
method: "drawImage",
source: "images/01.jpg",
x: 100, y: 100,
width: 280, height: 240,
load: invert
})
// Draw each layer on the canvas
.drawLayers();
});
Now What it Does Is making A hole In all the Images Means Erase all the Pixels Of That Portion Of all Images and Show the Background of canvas Is It Possible to Get Only Pixels Of Particular image or layer and Invert It is there any jquery plug-in available? any other way to do that? Any Help On this Will Be Very Useful To Me....Thanx In Advance....
Keep in mind that drawing on a canvas is like painting on paper, it doesn't remember what you drew before only what you have in the canvas right now so if you draw one image and then draw over it with another, the old picture is lost forever.
What you should do is keep all three images in three different buffers (simply load the three different images into three different image objects).
Then draw the top most image in the context.
When you wish to dissolve the first image into the second, instead of deleting pixels from the top image (which will only show the the background), simply use the same coordinates you would use to remove pixels from the first image to get the pixel data from the second image (the coordinates for deleting pixel from the top image can be used as indexes to the image data for the second image) and copy those values to the canvas, again using the same coordinates, for example:
If you algorithm leads you to first remove pixel x = 100, y = 175, use those coordinates to get the data from the buffer of the second image and copy that to the same coordinates in the canvas' image data.
Here's some code:
var width = 300;
var height = 300;
var img1 = new Image();
img1.src = "image1.png";
var img2 = new Image();
img2.src = "image2.png";
function go()
{
// Wait for the images to load
if ( !img1.complete || !img2.complete )
{
setTimeout( go, 100 );
return;
}
// Create a temporary canvas to draw the other images in the background
var tc = document.createElement( "canvas" );
tc.width = width;
tc.height = height;
var c2 = tc.getContext( "2d" );
// Draw the first image in the real canvas (change the ID to your canvas ID)
var c = document.getElementById( "myCanvas" ).getContext( "2d" );
c.drawImage( img1, 0, 0 );
var data1 = c.getImageData( 0, 0, width, height ); // Get the data for the first image
// Draw the second image in the temporary canvas (which is hidden) and get its data
c2.drawImage( img2, 0, 0 );
var data2 = c2.getImageData( 0, 0, width, height );
// Copy the data from the hidden image to the visible one
// This is where your magic comes into play, the following
// is just a very very simple example
var pix1 = data1.data;
var pix2 = data2.data;
for ( var x = 0; x < width; x++ )
{
for ( var y = 0; y < height; y++ )
{
var pos = ( ( y * width ) + x ) * 4;
pix1[ pos ] = pix2[ pos++ ];
pix1[ pos ] = pix2[ pos++ ];
pix1[ pos ] = pix2[ pos++ ];
pix1[ pos ] = pix2[ pos ];
}
}
// Redraw the visible canvas with the new data
c.putImageData( data1, 0, 0 );
}
window.onload = go;
The canvas element does not provide the ability to use layers like that. You may need to check add-ons like canvas collage or CanvasStack
Related
I need users to be able to draw a canvas element that then needs to be converted into an array of length 784 so it be can be fed into an algorithm. The array should be of pixel shade intensity, which I can find by use the ctx.getImageData() method. However, since the user needs to draw it, the canvas element is 280x280 instead of the required 28x28 meaning I need to downscale the image drawn on the 280x280 canvas, then use getImageData.
I've tried just getting every 100th value from the 280x280 image data array, but I'm not sure if that would actually work, and I've struggled to draw the resulting array so I can't verify.
var guess = document.getElementById('guess');
var canvasBig = document.getElementById('canvasBig');
var ctxBig = canvasBig.getContext('2d');
var canvasSmall= document.getElementById('canvasSmall');
var ctxSmall = canvasBig.getContext('2d');
var canvas = new fabric.Canvas('canvasBig', {
isDrawingMode: true,
});
canvas.freeDrawingBrush.width = 50;
guess.addEventListener('click', function() {
var imageData = ctx.getImageData(0,0, canvasBig.width, canvasBig.height)
var resized = []
for(var i = 0; i < imageData.length; i++){
if(i % 100 == 0){
resized.push(imageData.length)
}
}
console.log(imageData)
ctxSmall.putImageData(imageData, 0, 0)
});
You can simply draw the larger canvas itself (without having to use getImageData) onto the smaller canvas, scaling to down when you draw:
ctxSmall.drawImage(canvasBig, 0, 0, 280, 280, 0, 0, 28, 28);
So I have a function that dynamically produces a cropped section of a world map. The map has various points plotted onto it, plotted by longitude and latitude, depending on the data passed into the function from elsewhere in the script. (Don't worry about how these values are calculated, just accept they are calculated where I have put [number] in my code). I've worked out how to crop my map dynamically, but what I'm noticing is that there is a lot of transparent whitespace to the right of the image after the crop, when the image is appended to a div on the page. How do I remove this whitespace?
Please note that each crop will be of a different size. Setting overflow:hidden property on the containing div and limiting the containing div to a precise pixel width will not achieve what I want to achieve.
Thx u
-- Gaweyne
createZoomedMapImage: function(imageURL){
var imageObj = new Image();
imageObj.onload = _.bind(function(){
var canvas = document.createElement("canvas"),
context = canvas.getContext("2d"),
$canvas = $(canvas),
w = imageObj.width,
h = imageObj.height;
canvas.width = w;
canvas.height = h;
var startingX = [number]
var starting Y = [number]
var deltaWidth = [number]
deltaHeight = [number]
context.drawImage(imageObj, startingX, startingY, deltaWidth, deltaHeight, 0, 0, (deltaWidth*2), (deltaHeight*2));
var zoomedImage = canvas.toDataURL('image/png');
}, this);
imageObj.src = imageURL;
}
jsfiddle.net/Gaweyne/r0t3hoo6
The image tag looks like what is displayed in the result. I have an image of, say, 300 x 600px. But the actual graphic only takes up 300 x 300 pixels. I don't want the graphic to take up the full width of the image. I want the image to be 300 x 300 pixels. I don't want to set this explicitly with CSS because the cropped maps will differ in size depending on the data.
Try to use:
canvas.width = deltaWidth;
canvas.height = deltaHeight;
context.drawImage(imageObj, startingX, startingY, deltaWidth, deltaHeight, 0, 0, (deltaWidth*2), (deltaHeight*2));
var zoomedImage = canvas.toDataURL('image/png');
I searched for this question on the internet and the methods I found were about cropping images with CSS or cropping a rectangular shape with JavaScript. What I want is to crop a polynomial with JavaScript.
I have an Array of cartesian points Arr=[{x:x1,y:y1},{x:x2,y:y2},{x:x3,y:y3}] that makes a polynomial. The first element in the array equals the last element in the array.
Using the function crop, I want to use this array to crop a polynomial from a picture imageObj and save it in imageObj2.
var imageObj = new Image();
var imageObj2 = new Image();
var arr=[];
arr.push({x:x1,y:y1});
arr.push({x:x2,y:y2});
arr.push({x:x3,y:y3});
imageObj.src = 'link of imageObj';
crop(arr[],imageObj);
How can I build this function?
You have to use a canvas for this. It's the only way to modify an image permanently. This will also require CORS to be fulfilled.
As image loading is asynchronous that will be an aspect that needs to be dealt with either using Promises (not supported in IE) or callbacks. For the example below I'll use callbacks.
First part is the loading process as well as handling the callbacks properly.
The second part (cropImage()) show the complete process of cropping the image and ending up with a new image of the size of the crop.
It assumes the points to be scaled relative to original image size (tip: you don't need a closing point, ie. end point = first point, as fill() will automatically close the path for you).
var srcImage = new Image(); // create image object
srcImage.onload = crop; // set callback
srcImage.crossOrigin = ""; // for demo: =anonymous crossOrigin usage
srcImage.src = "http://i.imgur.com/U9X0n84.jpg";
document.body.appendChild(srcImage); // add original to DOM for comparsion
function crop() {
// - image is loaded and is represented as "this" inside this callback
// some "random" points for demo
var arr = [{x: 10, y: 90}, {x: 70, y: 10}, {x: 400, y: 200}, {x: 200, y: 220}];
// do the cropping, provide callback
cropImage(this, arr, function(img) {
// img is the cropped image - add to DOM for demo
document.body.appendChild(img);
})
}
function cropImage(image, arr, callback) {
// create a canvas element, and get 2D context for it:
var canvas = document.createElement("canvas"),
ctx = canvas.getContext("2d"),
i, minx = 10000, miny = 10000, maxx = -1, maxy = -1;
// find min max of array points here:
for(i = 0; i < arr.length; i++) {
if (arr[i].x < minx) minx = arr[i].x;
if (arr[i].x > maxx) maxx = arr[i].x;
if (arr[i].y < miny) miny = arr[i].y;
if (arr[i].y > maxy) maxy = arr[i].y;
}
// set proper size:
canvas.width = maxx - minx;
canvas.height = maxy - miny;
// translate context so corner of clip is (0,0)
ctx.translate(-minx, -miny);
// draw in image;
ctx.drawImage(image, 0, 0);
// create a clip path:
ctx.moveTo(arr[0].x, arr[0].y);
for(i = 1; i < arr.length; i++) ctx.lineTo(arr[i].x, arr[i].y);
// set comp. mode so image within path is kept:
ctx.globalCompositeOperation = "destination-atop";
ctx.fill();
// done, create an image object:
var dstImage = new Image();
dstImage.onload = function() {callback(this)};
dstImage.src = canvas.toDataURL(); // saves PNG in this case as data-uri
}
I have an image of a font I would like to draw on an HTML5 Canvas. At first I though about separating each letter into a different image but decided having a sprite sheet would be much cleaner. A problem with that though, is that not all the letters are the same size. Some are a few pixels wider than other characters.
While looking on Google, I came across one way that some people handled the problem. They added a line under each character to represent that characters length and then draw the bottom most line of the font image into an off screen canvas and analyze it pixel by pixel.
I tried to implement my own version of that idea, but was unable to get that far. Before I invest more time on that idea, I would like to know if it's a good solution or if there is any better ways of achieving the same thing.
So far I have a few small snippets i'm trying to put together, like this code:
getImagePixels: function( image, x, y, width, height )
{
var canvas = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
var ctx = canvas.getContext('2d');
ctx.drawImage( image, 0, 0, image.width, image.height );
return ctx.getImageData( x, y, width, height );
}
and this
loadFontImage: function( image )
{
// Draw the bottommost line of this font image into an offscreen canvas
// and analyze it pixel by pixel.
// A run of non-transparent pixels represents a character and its width
this.height = image.height-1;
this.widthMap = [];
this.indices = [];
var px = getImagePixels( image, 0, image.height-1, image.width, 1 );
var currentChar = 0;
var currentWidth = 0;
for( var x = 0; x < image.width; x++ )
{
var index = x * 4 + 3; // alpha component of this pixel
if( px.data[index] > 127 )
{
currentWidth++;
}
else if( px.data[index] < 128 && currentWidth )
{
this.widthMap.push( currentWidth );
this.indices.push( x-currentWidth );
currentChar++;
currentWidth = 0;
}
}
}
As I can't comment I will just write this as an answer:
You could also simply create or generate a javascript object with all the widths included:
var fontWidths = {
a: 8,
b: 8
....
};
That way the overhead doesn't happen every time you're going to write something to the canvas.
I'm developing following case.
Html canvas created by JS.
There are a star image(loaded from png with alpha=0 background) and a diamond image(also loaded from png with alpha=0 background) on canvas.
diamond image is moving toward the star image.
when diamond image is completely behind the star image, like showing star image only and diamond image is completely behind the star image, alert("Hidden");
if more than one pixel of the diamond is shown, alert should not appear.
Since the alpha value of the background of the star is 0, which means star is not a rectangle, it is difficult to detect whether the star image is fully covering the diamond image.
Is there any library or way to detect whether an image is fully covered by other?
Or, does any one know the name of this algorithm so that I can implement in JS?
Thanks for any help!
For objects with unknown shape we can check if object is behind by using pixel check.
Here is a full example on how to do this:
ONLINE DEMO HERE
(GameAlchemist provided a modified version here)
/// basic allocations
var ctx = demo.getContext('2d'),
os = document.createElement('canvas'),
octx = os.getContext('2d'),
w = os.width = demo.width,
h = os.height = demo.height,
/// the images
urlD = 'http://i.imgur.com/U72xIMZ.png',
urlS = 'http://i.imgur.com/n5rgo11.png',
imgD = new Image(),
imgS = new Image(),
cnt = 2,
/// check region (optimized)
rect = [140, 140, 180, 60];
/// load images and when ready, start show
imgD.crossOrigin = imgS.crossOrigin = 'anonymous';
imgD.onload = imgS.onload = function() {
cnt--;
if (cnt === 0) start();
}
imgD.src = urlD;
imgS.src = urlS;
The main function checks the pixels within the region defined above. To optimize we can narrow down the search area. If you need to check if image is visible on the other size the region is simply extended to check that area as well.
The function compares an off-screen canvas with just the foremost image drawn against the "live" canvas where both background and foreground are drawn.
If live canvas = off-screen canvas that means the background image is not visible.
function start() {
octx.drawImage(imgS, (w - imgS.width) * 0.5, 20);
var x = -50,
buffer1 = octx.getImageData(rect[0], rect[1], rect[2], rect[3]).data,
len = buffer1.length;
loop();
function loop() {
ctx.clearRect(0, 0, w, h);
ctx.drawImage(imgD, x, 130);
ctx.drawImage(imgS, (w - imgS.width) * 0.5, 20);
if (compare() === true) {
info.innerHTML = 'Object is behind!';
return;
}
x += 2;
if (x < w) requestAnimationFrame(loop);
}
function compare() {
var buffer2 = ctx.getImageData(rect[0], rect[1], rect[2], rect[3]).data,
i = len - 1;
while(i--) {
if (buffer1[i] !== buffer2[i]) return false
}
return true;
}
}