drawing a cropped version of an image onto a canvas - javascript

I have the following html file which draws an image on the canvas.
<canvas id="canvas"width="800"height="800"></canvas>
<script>
var canvas = document.getElementById('canvas')
let ctx = canvas.getContext('2d')
let img = new Image()
img.src = 'https://clipartspub.com/images/circle-clipart-blue-1.jpg'
img.onload = function(){
ctx.drawImage(img,300,300,300,300)
}
</script>
It works fine, however I would like to instead draw a cropped version of this image, for example, the bottom right quarter of the image. Is this possible?

You have to use the below implementation of drawImage to achieve that
void ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
Check the docs here
var canvas = document.getElementById("canvas");
let ctx = canvas.getContext("2d");
let img = new Image();
img.src = "https://clipartspub.com/images/circle-clipart-blue-1.jpg";
img.onload = function () {
const width = img.width;
const height = img.height;
ctx.drawImage(
img, // Source image
width / 2, // Start at this x of image
height / 2, // Start at this y of image
width / 2, // Till this width of image
height / 2, // Till this height of image
0, // Start at this x of canvas
0, // Start at this y of image
300, // Till this width of canvas
300 // // Till this height of canvas
);
};
<canvas id="canvas"width="800"height="800"></canvas>
You can also use canvas.width and canvas.height in the canvas values used above for a better scaled result.

Related

How to scale small ImageData to large HTML canvas

I am trying to put image data 100x100 to canvas 1000x1000 , but cant able to do it ,
let width=1000; //canvas width
let height=1000; //canvas height
let img_w=100; //image width
let img_h=100; //image height
let img=new Image();
img.width=img_w
img.height=img_h
img.src="./flower.jpg"
var canvas = document.getElementById('mycanvas');
var context = canvas.getContext('2d');
canvas.width = width;
canvas.height = height;
let pixels,scannedimg;
img.onload=()=>{
context.drawImage(img, 0, 0,width,height );
scannedimg = context.getImageData(0, 0, img.width, img.height);
pixels=scannedimg.data
console.log(pixels)
redraw();
}
let row=4*img_w;
let col=img_h;
function redraw(){
for(let i=0;i<row;i+=4){
for(let j=0;j<col;j++){
pixels[i+j*row]=0;
pixels[i+j*row+1]=0;
pixels[i+j*row+2]=0;
//pixels[i+j*400+3]=0;
}
}
scannedimg.data=pixels;
console.log(scannedimg);
context.putImageData(scannedimg,0,0,0,0,width,height);
}
i have converted the original array into a black image array (array of zeros) , but while putting on canvas , it is still 100x100
How to scale it to 1000x1000?
i don't want to iterate through 1000x1000 and set it to zero ,
i need a computationally efficient answer
Unless you outsource the pixel calculations to a WebAssembly module a JavaScript-only approach would indeed be rather slow for a large image.
Honestly I'm not sure what you are actually doing in your code.
First your drawing an unknown-sized .jpg to a 1000x1000 canvas which - unless the .jpg is also 1000x1000 - will scale and eventually distort the source image.
let width=1000;
let height=1000;
context.drawImage(img, 0, 0, width, height);
Secondly you're obtaining the pixel data of a 100x100 region from the top-left of your 1000x1000 canvas.
let img_w=100;
let img_h=100;
img.width=img_w;
img.height=img_h;
scannedimg = context.getImageData(0, 0, img.width, img.height);
Finally in your redraw() function you're rather randomly setting some of the pixels to black and draw it back to the canvas at 1000x1000 (which doesn't work that way but I will get into it later).
Let's do it a little different. Say we have a 300x200 image. First we need to draw it to a 100x100 canvas while maintaining it's aspect ratio to get the 100x100 imagedata.
This can be done using a dynamically created off-screen <canvas> element as we don't need to see it.
Now the tricky part is the CanvasRenderingContext2D putImageData() method. I assume you were thinking that the last pair of parameters for the width & height would stretch existing pixel data to fill the region specifid by (x, y, width, height). Well that's not the case. Instead we need to - again - paint the 100x100 pixel data to a same-sized off-screen canvas (or for simlicity re-use the existing) and draw it to the final canvas using the drawImage() method.
Here's everything put together:
let pixelsWidth = 100;
let pixelsHeight = 100;
let finalWidth = 500;
let finalHeight = 500;
let tempCanvas = document.createElement('canvas');
let tempContext = tempCanvas.getContext('2d');
tempCanvas.width = pixelsWidth;
tempCanvas.height = pixelsHeight;
let pixelData;
let img = new Image();
img.crossOrigin = 'anonymous';
img.onload = (e) => {
let scale = e.target.naturalWidth >= e.target.naturalHeight ? pixelsWidth / e.target.naturalWidth : pixelsHeight / e.target.naturalHeight;
let tempWidth = e.target.naturalWidth * scale;
let tempHeight = e.target.naturalHeight * scale;
tempContext.drawImage(e.target, pixelsWidth / 2 - tempWidth / 2, pixelsHeight / 2 - tempHeight / 2, tempWidth, tempHeight);
pixelData = tempContext.getImageData(0, 0, pixelsWidth, pixelsHeight);
redraw();
}
img.src = 'https://picsum.photos/id/237/300/200';
function redraw() {
let canvas = document.getElementById('canvas');
let context = canvas.getContext('2d');
canvas.width = finalWidth;
canvas.height = finalHeight;
tempContext.putImageData(pixelData, 0, 0);
context.drawImage(tempCanvas, 0, 0, finalWidth, finalHeight);
}
canvas {
background: #cccccc;
}
<canvas id="canvas"></canvas>

JavaScript - Take Center of Image

I got an image, it could be of every size but I need to take the center area of 86x86. Also I've to do that in javascript when a new image is loaded, replacing the old one.
At the end of the code I need to have my 's src updated with the new image.
function loadedImage(elem,gCount){
var crop = { //just messing with numbers
top : 10,
left : 10,
right : 20,
bottom : 20,
};
var file = elem.files[0]; //I take the loaded image
var img = document.getElementsByName('imag')[gCount]; //I take the interessed <img>
var canvas = document.createElement("canvas"); //create canvas
canvas.width = crop.right - crop.left; //set dimensions
canvas.height = crop.bottom - crop.top;
var ctx = canvas.getContext("2d"); // so we can draw
var image = new Image();
image.setAttribute('crossOrigin', 'anonymous');
image.width = img.width;
image.height = img.height;
image.src = window.URL.createObjectURL(file);
ctx.drawImage(image, -crop.left, -crop.top);
image.src = canvas.toDataURL("image/png");
img.src = image.src;
}
No image is shown
Use a load event listener to wait for your image to load. Once it's ready, you can then start drawing.
To draw the center part of your image, the source x-coordinate should be half the width of your image, minus half the width of the crop. (The source y-coordinate can be calculated in a similar way.)
var input = document.getElementsByName('input')[0];
input.addEventListener('change', function (e) {
var file = e.target.files[0];
drawCroppedImage(file, 86, 86);
});
function drawCroppedImage(file, w, h) {
var canvas = document.getElementById('canvas');
canvas.width = w;
canvas.height = h;
var ctx = canvas.getContext('2d');
var image = new Image();
image.addEventListener('load', function (e) {
var sx = (image.width / 2) - (w / 2), // Source X
sy = (image.height / 2) - (h / 2), // Source Y
dx = 0, // Destination X
dy = 0; // Destination Y
ctx.drawImage(image, sx, sy, w, h, dx, dy, w, h);
});
image.src = URL.createObjectURL(file);
}
<input type="file" name="input">
<br><br>
<canvas id="canvas" width="86" height="86"></canvas>

How to draw a photo then a shape on top of the photo using a canvas in Ionic?

There are numerous examples out there showing how to draw things onto a canvas, however, my problem is slightly different - I want to load a photo into memory, draw a shape onto exact coordinates over the photo, THEN draw/scale the photo onto a canvas. Not sure where to start with this. Are there any relevant libraries out there I can use with ionic that will allow you to do this?
Edit 1 ~ I now have this mostly working:
private properties:
#ViewChild('mainCanvas') canvasEl: ElementRef;
private _CANVAS: any;
private _CONTEXT: any;
ionViewDidEnter():
this._CANVAS = this.canvasEl.nativeElement;
this._CONTEXT = this._CANVAS.getContext('2d');
updateCanvas():
var img = new Image();
const ctx = this._CONTEXT;
const canvas = this._CANVAS;
ctx.clearRect(0, 0, this._CANVAS.width, this._CANVAS.height);
ctx.fillStyle = "#ff0000";
img.onload = (() => {
img.width = img.width;
img.height = img.height;
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
ctx.lineWidth = 8;
ctx.strokeStyle = "#FF0000";
ctx.strokeRect(100, 100, 400, 400);
ctx.scale(0.5, 0.5); // this does nothing
});
img.src = (<any>window).Ionic.WebView.convertFileSrc(path);
This draws the photo then the rectangle onto the canvas, however, the resulting image is too large to fit onto the screen, so I need to scale the canvas after all drawing is complete. I tried this with ctx.scale but the canvas remains the same size regardless of which values I specify.
You cannot draw straight onto a photo, but what you can do is create an offscreen canvas that is the same size as the photo, draw the photo to it, and then draw your shapes on top.
The result can then be drawn to your main canvas e.g.
// Empty image for example purposes
const img = new Image(100, 100);
// Creating a canvas for example purposes
const mainCanvas = document.createElement('canvas');
const mainCtx = mainCanvas.getContext('2d');
// Create an offscreen buffer
const bufferCanvas = document.createElement('canvas');
const bufferCtx = bufferCanvas.getContext('2d');
// Scale the buffer canvas to match our image
bufferCanvas.width = img.width;
bufferCanvas.height = img.height;
if (bufferCtx && mainCtx) {
// Draw image to canvas
bufferCtx.drawImage(img, 0, 0);
// Draw a rectangle in the center
bufferCtx.fillRect(img.width / 2 - 5, img.height / 2 - 5, 10, 10);
// Draw the buffer to the main canvas
mainCtx.drawImage(bufferCanvas, 0, 0);
}

HTML flexible canvas scale

I am making a website which will load some blueprint images on a canvas.
but the images are vary in height and width.i Would like to make the canvas scaling equal to the uploaded image scale. How do i code to make the canvas width and height changeble respective to uploaded image.
This done in html5
If I understand you correctly, you want to load images with various dimensions. According to the dimension, set the width / height of the canvas and draw the image?
In that case you could add an eventListener to the image. Once it's loaded, get the width and height. Use those to set the dimensions of the canvas. After that, draw the image on the canvas.
var image = new Image();
image.addEventListener('load', function(e) {
var width = image.width;
var height = image.height;
var canvas = document.querySelector('canvas');
canvas.width = width;
canvas.height = height;
canvas.getContext('2d').drawImage(image, 0, 0, width, height);
});
image.src = 'https://upload.wikimedia.org/wikipedia/commons/c/c4/PM5544_with_non-PAL_signals.png';
<canvas></canvas>
Fiddle
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
var imageObj = new Image();
imageObj.src = 'images/e1.jpg';
canvas.width = imageObj.naturalWidth;
canvas.height = imageObj.naturalHeight;
this also works

Create Canvas element with image and append to parent

I need to create Canvas element with image and need to append to parent for this i have done this
<html>
<head>
<script>
window.onload = function() {
var canvas = document.createElement('canvas');
var context = canvas.getContext("2d");
canvas.id = "canvas_id";
canvas.setAttribute("class" ,"canvas");
canvas.height = "400";
canvas.width = "800";
var image = new Image();
image.src = "http://localhost/tile.png";
image.onload = function(){
context.drawImage(image, canvas.width, canvas.height);
}
document.body.appendChild(canvas);
}
</script>
</head>
<body>
</body>
</html>
it give blank canvas
can somebody guide me ?
You are using drawImage() the wrong way. Instead of drawing the image at (0,0) you are drawing it just outside the canvas area as width and height is where position normally goes.
The valid signatures are:
context.drawImage(image, dx, dy)
context.drawImage(image, dx, dy, dw, dh)
context.drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh)
Where dx and dy are delta position (relative to origin, normally (0,0) when untranslated). Without width and height specified drawImage() will by default use the image's natural width and height.
The second version allows to override the default size, and the third will allow you to draw from one region to another.
Source
Corrected example:
window.onload = function() {
var canvas = document.createElement('canvas');
var context = canvas.getContext("2d");
canvas.id = "canvas_id";
canvas.className = "canvas"; // should be className
canvas.height = 400; // should be numbers
canvas.width = 800;
var image = new Image();
image.onload = function() {
// or set canvas size = image, here: (this = currently loaded image)
// canvas.width = this.width;
// canvas.height = this.height;
context.drawImage(this, 0, 0); // draw at (0,0), size = image size
// or, if you want to fill the canvas independent on image size:
// context.drawImage(this, 0, 0, canvas.width, canvas.height);
}
// set src last (recommend to use relative paths where possible)
image.src = "http://lorempixel.com/output/fashion-q-c-800-400-7.jpg";
document.body.appendChild(canvas);
}
That being said, if you only need the image appended there is no need to go via canvas. Just add the image to DOM directly (I assume this is not you want, but just in case..):
var image = new Image();
image.src = "tile.png";
document.body.appendChild(image);
This is my take on it... You need to indicate the coordinates where you want to start drawing (i.e. 0, 0) and - optionally - you can specify how big (wide, height) the canvas is to be.
In my case, I make the canvas to be as big as the image (instead of an arbitrary 400x800) you may need to update that your suit your requirements.
I added some css to show how big the canvas is in relation to the image. You can update/remove that as well depending on your needs.
UPDATED
It uses an hidden image as the source.
I hope this will work for you.
window.onload = function() {
var canvas = document.createElement('canvas');
var ctx = canvas.getContext("2d");
canvas.id = 'canvas_id';
canvas.setAttribute("class", "canvas");
var image = new Image();
image.src = 'http://placekitten.com/g/200/300';
canvas.width = image.width;
canvas.height = image.height;
ctx.drawImage(image, 0, 0, image.width, image.height);
document.body.appendChild(canvas);
}
.canvas {
border: solid red 1px;
}
<html>
<body>
</body>
</html>

Categories