I would like to paint several seamless images side by side with Raphael. This works in Chrome but not in firefox. For some reason firefox paint the images with small space between them.
You can see that in the fiddle: http://jsfiddle.net/bxK4b/4/
var paper = Raphael(0,0, 200, 200);
var x = 0;
var y = 0;
var size = 10;
var url = "http://us.123rf.com/400wm/400/400/alliedcomputergraphics/alliedcomputergraphics1206/alliedcomputergraphics120600904/14063568-ground-cover-seamless-texture-tile.jpg";
for (x = 0; x < 10; x++) {
for (y = 0; y < 10; y++) {
rect = paper.image(url, x * size, y * size , size, size);
}
}
Sometimes it is possible to paint the images with no space, but if you try to put them in a set and scale the complete set 2 or 3 times, the space between the images comes appears again.
What am I doing wrong? Any help would be appreciated!
Adding 0.5 to the x co-ordinate does it for me:
rect = paper.image(url, x * size + .5, y * size , size, size);
not sure why adding .5 to y is unnecessary but the concept is from here.
Related
In this example we use math functions to create a blurred copy of an image. The way we will blur the image is by scrambling pixels that are near each other.
We begin by creating a blank image and writing the loop to let us color each pixel in the image. For each pixel we will do one of two things: half the time, we will simply copy the pixel from the old picture into the new picture without changing anything. The other half of the time we will find a pixel nearby and copy that one instead.
Now we must figure out how to find a "nearby" pixel. We will define some value for how far away the new pixel will be (we used 10 pixels) and then we write a function that will give a (x,y) point that is a random amount between 0 and 10 pixels away in each direction. Before we use the new (x,y) point, we must check to be sure it is still a valid pixel position in the image. For example, we may be at a pixel that is on the very top of the image. Our random point generator tells us to go up by 3 pixels, but since we are on the top of the image (y = 0) we cannot very well go up by three pixels (y would be -3)! If the random number is too big (larger than the dimension -1) or too small (less than 0) then we will just use the closest number that is valid.
Once we have a valid pixel that is some amount away we use its red, green, and blue values as the new pixel's values.
function nearby(image, x, y) {
var newX = x + Math.random() * 10 - 5;
if (newX > image1.getWidth()) {
newX = newX - 5;
}
if (newX < 0) {
newX = newX + 5;
} else {
newX = newX;
}
var newY = y + Math.random() * 10 - 5;
if (newY > image1.getHeight()) {
newY = newY - 5;
}
if (newY < 0) {
newY = newY + 5;
} else {
newY = newY;
}
return image.getPixel(newX, newY);
}
function blur(image) {
for (var pixel of image.values()) {
x = pixel.getX();
y = pixel.getY();
var orgPixel = image.getPixel(x, y);
if (Math.random() < 0.5) {
var other = nearby(image, x, y);
output.setPixel(x, y, other);
} else {
output.setPixel(x, y, orgPixel);
}
}
return output;
}
var image1 = new SimpleImage("duvall.jpg");
var output = new SimpleImage(image1.getWidth(), image1.getHeight());
blur(image1);
print(output);
----i used one of the pictures in my file but any picture should do.
I am drawing a 17×17 2D grid on canvas using rect(). But whenever I increase the numbers of cells (for example 20×20) the grid on canvas is shrinking. At first I thought that it was a floating point precision loss problem. However it seems that it is not the case. Does the density or pixels of screen has something to do with it? Because it happens differently on different sizes of screen.
Here is my code in draw():
let size = width / 17;
for (let x = 0; x < size; x++) {
for (let y = 0; y < size; y++) {
rect(x * size, y * size, size, size);
}
}
19×19
20×20
Yo have to iterate from 0 to the number of cells, rather than from 0 to size. size is the size of a single cell, not the number if cells:
let no_of_cells = 20;
let size = width / no_of_cells;
for (let x = 0; x < no_of_cells; x++) {
for (let y = 0; y < no_of_cells; y++) {
rect(x * size, y * size, size, size);
}
}
So lately I've been trying to make a 2D Zelda-like game. I want to make a camera to follow the player.
So I looked at https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/translate, https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Transformations, and some others in my search (MDN has an article on it but I couldn't follow although it didn't look like what I was looking for).
I also didn't want to just center the player, I want to have a camera which has a limit, so you have to go a certain amount outside of the camera for the map to start scrolling.
function camera(data) {
var x, y;
if(I.x <= 2 && I.x >= -2 && I.y <= 2 && I.y >= -2) { x = 0; y = 0;}
if(I.x > 2) { x = -I.size; y = 0; }
if(I.x < -2) { x = I.size; y = 0; }
if(I.y > 2) { x = 0; y = -I.size; }
if(I.y < -2) { x = 0; y = I.size; }
ctx.translate(x, y);
draw.map();
draw.camera();
draw.players(data);
ctx.resetTransform();
}
draw.map() draws the tiles.
draw.camera() draws a little dotted box so I know the boundary of the camera.
draw.players(data) draws every player.
I.size refers to the size of each tile(16 in this case).
I.x & I.y are self explanatory.
I do have a working version(uses node and socket.io):
http://dais-jaackotorus.codeanyapp.com:8080/
EDIT:
Almost forgot! The problem with this code is that it follows the player for only one tile and then it doesn't any longer, and it goes outside of the camera range instead of staying inside and I dont understand why.
Here's a simplified example:
https://jsfiddle.net/2xbo0kas/
The trick is to start drawing the world around the player. So, in the jsfiddle, you can see the player is stationary but the map moves, so that the player is always centered into the viewport.
What the fiddle does not show is the final position of the player once you reach the edge of the map (where you'd draw a stationary map but update the player rectangle).
function draw() {
var startx = Math.max([player.x - size.width], 0);
var endx = Math.min(startx + size.width, map.length);
var starty = Math.max([player.y - size.height], 0);
var endy = Math.min(starty + size.height, map[0].length);
for (var x = startx; x < endx; x++) {
for (var y = starty; y < endy; y++) {
var drawx = x - startx;
var drawy = y - starty;
//draw tile
}
}
//draw player
}
I saw that you have helped David with his mirroring canvas problem before. Canvas - flip half the image
I have a similar problem and hope that maybe you could help me.
I want to apply the same mirror effect on my webcam-canvas, but instead of the left side, I want to take the RIGHT half of the image, flip it and apply it to the LEFT.
This is the code you've posted for David. It also works for my webcam cancas. Now I tried to change it, so that it works for the other side, but unfortunately I'm not able to get it.
for(var y = 0; y < height; y++) {
for(var x = 0; x < width / 2; x++) { // divide by 2 to only loop through the left half of the image.
var offset = ((width* y) + x) * 4; // Pixel origin
// Get pixel
var r = data[offset];
var g = data[offset + 1];
var b = data[offset + 2];
var a = data[offset + 3];
// Calculate how far to the right the mirrored pixel is
var mirrorOffset = (width - (x * 2)) * 4;
// Get set mirrored pixel's colours
data[offset + mirrorOffset] = r;
data[offset + 1 + mirrorOffset] = g;
data[offset + 2 + mirrorOffset] = b;
data[offset + 3 + mirrorOffset] = a;
}
}
Even if the accepted answer you're relying on uses imageData, there's absolutely no use for that.
Canvas allows, with drawImage and its transform (scale, rotate, translate), to perform many operations, one of them being to safely copy the canvas on itself.
Advantages is that it will be way easier AND way way faster than handling the image by its rgb components.
I'll let you read the code below, hopefully it's commented and clear enough.
The fiddle is here :
http://jsbin.com/betufeha/2/edit?js,output
One output example - i took also a mountain, a Canadian one :-) - :
Original :
Output :
html
<canvas id='cv'></canvas>
javascript
var mountain = new Image() ;
mountain.onload = drawMe;
mountain.src = 'http://www.hdwallpapers.in/walls/brooks_mountain_range_alaska-normal.jpg';
function drawMe() {
var cv=document.getElementById('cv');
// set the width/height same as image.
cv.width=mountain.width;
cv.height = mountain.height;
var ctx=cv.getContext('2d');
// first copy the whole image.
ctx.drawImage(mountain, 0, 0);
// save to avoid messing up context.
ctx.save();
// translate to the middle of the left part of the canvas = 1/4th of the image.
ctx.translate(cv.width/4, 0);
// flip the x coordinates to have a mirror effect
ctx.scale(-1,1);
// copy the right part on the left part.
ctx.drawImage(cv,
/*source */ cv.width/2,0,cv.width/2, cv.height,
/*destination*/ -cv.width/4, 0, cv.width/2, cv.height);
// restore context
ctx.restore();
}
I want to resize image using very simple algorithm. I have something like this:
var offtx = document.createElement('canvas').getContext('2d');
offtx.drawImage(imageSource, offsetX, offsetY, width, height, 0, 0, width, height);
this.imageData = offtx.getImageData(0, 0, width, height).data;
offtx.clearRect(0, 0, width, height);
for(var x = 0; x < this.width; ++x)
{
for(var y = 0; y < this.height; ++y)
{
var i = (y * this.width + x) * 4;
var r = this.imageData[i ];
var g = this.imageData[i+1];
var b = this.imageData[i+2];
var a = this.imageData[i+3];
offtx.fillStyle = "rgba("+r+","+g+","+b+","+(a/255)+")";
offtx.fillRect(0.5 + (x * this.zoomLevel) | 0, 0.5 + (y*this.zoomLevel) | 0, this.zoomLevel, this.zoomLevel);
}
}
this.imageData = offtx.getImageData(0, 0, this.width * this.zoomLevel, this.height * this.zoomLevel);
However, the problem I have with this solution, is that the image looses any transparency information that way. I don't know if this happens somewere in this algorithm, or maybe putImageData that I am using later to display that image is doing this, but I can't seem to be able to preserve transparency.
Each time I do this I create a canvas, I put the image on that canvas and use getImageData to get image from that canvas as you can see in the first lines of the code. Maybe there is no other way, so I might not mind that...
But the problem is I use two for loops to draw resized image and then use getImageData to store that image information. This is a wierd way to do it. I would prefer to create empty image data and fill it with all the original image information only resized. I can't grasp that with my mind, I can't image the loop structure for this. To show what I mean:
for(var x = 0; x < this.width; ++x)
{
for(var y = 0; y < this.height; ++y)
{
var i = (y * this.width + x) * 4;
var r = this.imageData[i ];
var g = this.imageData[i+1];
var b = this.imageData[i+2];
var a = this.imageData[i+3];
//I WOULD LIKE MAGIC TO HAPPEN HERE THAT WILL
//RESIZE THAT CURRENT PIXEL AND MOVE IT TO THE NEW IMAGE DATA RESIZED
//SO EVERYTHING IS DONE NICE AND CLEAN IN THIS LOOP WITHOUT THE
//GETIMAGEDATA LATER AND MAYBE SET TRANSPARENT PIXELS WHILE I'M AT IT
}
}
I can't figure out the MAGIC part.
Thank you for reading!
Why not just use the built-in drawImage combined with image smoothing disabled? Doing this operation in a loop is not only relative slow but also prone to errors (as you already discovered).
Doing it the following way will give you the "pixel art" look and will also preserve the alpha channel:
var factor = 4; /// will resize 4x
offtx.imageSmoothingEnabled = false; /// prefixed in some browsers
offtx.drawImage(imageSource, offsetX, offsetY, width, height,
0, 0, width * factor, height * factor);
Here is an online demo.
Try using this library I recently made which can load an image, resize it fixed width & height or precentage.
It does exactly what you need, and much more like converting canvas to base64, blob, etc...
var CanvaWork = new CanvaWork();
CanvaWork.canvasResizeAll(obj.canvas, function(canvases){
// "canvases" will be an array containing 3 canvases with different sizes depending on initial options
});
https://github.com/vnbenny/canvawork.js
Hope this helps you!