drawImage to resize all pictures to same width - javascript

Im using drawImage to "resize" the image with ;
img.onload = function(){
var width = img.width * 0.16,
height = img.height * 0.16;
canvas.width = width,
canvas.height = height;
ctx.imageSmoothingEnabled = false;
ctx.drawImage(img, 0, 0, width, height);
}
Whenever I use it like this, it shows the image nicely
But whenever i do fixed width and height it shows the init bit blurry
img.onload = function(){
ctx.imageSmoothingEnabled = false;
ctx.drawImage(img, 0, 0, 56, 56);
}
So I want fixed height and width but must show not blurry

Your first version sets the canvas's width and height to be the same dimensions as those of the image, so when you draw the image, no scaling is performed (actually, your img's width and height are scaled down by 16%, or 0.16, to match the value you specify, but it does not scale your image down when drawing into the canvas because the last 2 arguments of drawImage() match the dimensions of the canvas).
img.onload = function(){
var width = img.width * 0.16,
height = img.height * 0.16;
canvas.width = width, // canvas's width === img's width
canvas.height = height; // canvas's heeight === img's height
ctx.imageSmoothingEnabled = false;
ctx.drawImage(img, 0, 0, width, height); // draw img at the same dimensions as those of the canvas => no scaling => no blur
}
Whereas, your second version draws the image at 56x56 size, this does not match the canvas' dimensions, hence the image is scaled down, so it appears a little blurry.
img.onload = function(){
ctx.imageSmoothingEnabled = false;
ctx.drawImage(img, 0, 0, 56, 56); // last 2 arguments tell the browser to draw the image at 56x56 px dimensions
}

Related

Javascript crop and scale image to be 300 pixel

I want to know how we can scale and crop an image in Javascript. I want to scale it down to 300x300px and crop it a little.
Do you have any suggestions ? I have the following code :
function cropImage(imagePath, newX, newY, newWidth, newHeight) {
//create an image object from the path
var img = document.createElement('img');
img.src = "data:image/png;base64,"+imagePath;
//alert(img.width);
//alert(img.height);
//initialize the canvas object
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
//set the canvas size to the new width and height
canvas.width = 300;
canvas.height = 300;
//draw the image
ctx.drawImage(img, newX, 75, 300, 300, 0, 0, 300, 300);
variables.imageCrop = canvas.toDataURL();}
Thank you !
Try it:
And learn more about .drawImage()
function cropImage(imagePath, leftRight, topBottom, newWidth, newHeight) {
const img = document.createElement('img');
img.src = imagePath;
const canvas = document.createElement('canvas');
document.body.appendChild(canvas);
const ctx = canvas.getContext('2d');
img.addEventListener('load', function() {
//Set your canvas size as your choice
//here i just scaled by 10 with original dimension
canvas.width = img.naturalWidth*10;
canvas.height = img.naturalHeight*10;
const cropLeft = leftRight[0];
const cropRight = img.naturalWidth - leftRight[0] - leftRight[1];
const cropTop = topBottom[0];
const cropBottom = img.naturalHeight - topBottom[0] - topBottom[1];
ctx.drawImage(
img,
cropLeft,cropTop,
cropRight, cropBottom,
0,0, //here you can control placement of cropped image from left and top, by default it stays in 0,0 meaning the top left corner of the canvas
newWidth,newHeight //new width and height of cropped image
);
});
}
//Size of this image is 100x100 px
const img = "https://dummyimage.com/100.png/09f/fff";
//here [10,10] meaning crop 10px from left and 10px from right
//here [20,20] meaning crop 20px from top and 20px from bottom
cropImage(img,[10,10],[20,20], 100, 100);

Canvas drawImage: Proportion Issue when linearly interpolating from "fit"- to "fill"-style settings

I have a canvas and I want to be able to draw an image in different sizes from "fit" (like CSS "contain") to "fill" (like CSS "cover"). I use drawImage() with different source and destination properties for fit and fill. Both extremes work perfectly as expected, but in between the image proportions are way off, and the image looks flat. I use linear interpolation to calculate the between source and destination properties.
"fit/contain" properties:
ctx.drawImage(
img, // image
0, // source x
0, // source y
img.width, // source width
img.height, // source height
(canvas.width - canvas.height * imageAspect) / 2, // destination x
0, // destination y
canvas.height * imageAspect, // destination width
canvas.height // destination height
)
"fill/cover" Properties:
ctx.drawImage(
img, // image
0, // source x
(image.height - img.width / canvasAspect) / 2, // source y
img.width, // source width
img.width / canvasAspect, // source height
0, // destination x
0, // destination y
canvas.width, // destination width
canvas.height // destination height
)
These are both fine, but linear interpolation of all the values get the wrong proportions of the image. Here's a quick demo that is not working as expected, I animated the interpolation so that you can see the squished effect more clearly:
Code Pen
The desired result would be keeping the image's proportions right in every step between 0 (fit) and 1 (fill). What am I missing here?
EDIT: The easiest solution would be to always take the full source image (not crop it with sX, sY, sWidth, and sHeight) and then draw the destination with negative coordinate values on the canvas when the image is bigger than the canvas. This is working but it is not the desired behavior. Because further on I need to be able to draw only to a certain sub-rectangle in the canvas, where the overlapping ("negative values") would be seen. I don't want to draw outside the rectangle. I am quite sure it is just a small mathematical issue here that needs to be solved.
For me, the solution in your "Edit" is the way to go.
If later on you want to clip the image in a smaller rectangle than the canvas, use the clip() method:
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
canvas.width = 800;
canvas.height = 150;
let step = 1;
let direction = 1;
// control the clipping rect position with the mouse
const mouse = {x: 400, y: 75};
onmousemove = (evt) => {
const rect = canvas.getBoundingClientRect();
mouse.x = evt.clientX - rect.left;
mouse.y = evt.clientY - rect.top;
};
function getBetweenValue(from, to, stop) {
return from + (to - from) * stop;
}
const image = new Image();
image.src =
"https://w7.pngwing.com/pngs/660/154/png-transparent-perspective-grid-geometry-grid-perspective-grid-geometric-grid-grid.png";
let imageAspect = 0;
let canvasAspect = canvas.width / canvas.height;
let source;
let containDestination;
let coverDestination;
function draw(image) {
ctx.save();
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Clip the context in a sub-rectangle
ctx.beginPath();
ctx.rect(mouse.x - 150, mouse.y - 50, 300, 100);
ctx.stroke();
ctx.clip();
// Since our image scales from the middle of the canvas,
// set the context's origin there, that makes our BBox values simpler
ctx.translate(canvas.width / 2, canvas.height / 2);
ctx.drawImage(
image,
source.x,
source.y,
source.width,
source.height,
getBetweenValue(containDestination.x, coverDestination.x, step),
getBetweenValue(containDestination.y, coverDestination.y, step),
getBetweenValue(containDestination.width, coverDestination.width, step),
getBetweenValue(containDestination.height, coverDestination.height, step)
);
ctx.restore(); // remove clip & transform
}
image.addEventListener("load", () => {
imageAspect = image.width / image.height;
source = {
x: 0,
y: 0,
width: image.width,
height: image.height
};
containDestination = {
x: -(canvas.height * imageAspect) / 2,
y: -(canvas.height / 2),
width: canvas.height * imageAspect,
height: canvas.height
};
coverDestination = {
x: -image.width / 2,
y: -image.height / 2,
width: image.width,
height: image.height
};
raf();
});
function raf() {
draw(image);
step += .005 * direction;
if (step > 1 || step < 0) {
direction *= -1;
}
window.requestAnimationFrame(raf);
}
canvas {
border:1px solid red;
}
img {
max-width:30em;
height:auto;
}
Use your mouse to move the clipping rectangle<br>
<canvas></canvas><br><br>
Original image proportions:<br>
<img src="https://w7.pngwing.com/pngs/660/154/png-transparent-perspective-grid-geometry-grid-perspective-grid-geometric-grid-grid.png" alt="">

Rescaling image make it black in javascript

I have come up with a function which transform the width and height of an image to new values,
function imageToDataUri(src, width, height) {
// create an off-screen canvas
var img=new Image();
img.src=src;
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
// set its dimension to target size
canvas.width = width;
canvas.height = height;
// draw source image into the off-screen canvas:
ctx.drawImage(img, 0, 0, width, height);
var d = ctx.getImageData(0, 0, width, height);
console.log('de from transformation is');
console.log(d);
return canvas.toDataURL();
}
The input to the function is a base64 string and the output is the same as well, but sometimes above function gives me a complete black image when I use my input image. Can someone tell me is there anything I am missing in my codes?

How to resize html2canvas and scale to original 100% resolution?

html2canvas(document.querySelector("#capture")).then(canvas => {
document.querySelector(".canvas-layout").appendChild(canvas);
});
I need to resize this canvas (2304x1440 pixels to 230.4x144, for example) and scale back to the original 100% (2304x1440). How can I do that?
I use it for blur-effect on a background of the fixed header. Then scroll it with $(this).scrollTop(); The method is here.
After you get the canvas object from the html2canvas method, use its context to draw the canvas again in your desired resolution.
Like this for example,
function resizeCanvas(canvas, newHeight, newWidth)
{
var context = canvas.getContext('2d');
var imageData = context.getImageData(0, 0, canvas.width, canvas.width);
var newCanvas = document.createElement("canvas");
newCanvas.height = canvas.height;
newCanvas.width = canvas.width;
newCanvas.putImageData(imageData, 0, 0, 0, 0, newWidth, newHeight);
return newCanvas;
}

Image resizing working in Chrome, but not in Firefox

I've got a function in my Angular 1.5 app that resizes a base64-encoded image if it's over a maximum size. This function works great in Chrome, but in Firefox it returns a empty string instead of anything base64-encoded.
I've got it packaged up in an Angular app in Plunker here, but here's the relevant function:
// Image resizing
$scope.resizeImage = function(base64Data, maxWidth, maxHeight) {
img = document.createElement('img');
img.src = base64Data;
height = img.height;
width = img.width;
if (width > maxWidth) {
ratio = maxWidth / width; // get ratio for scaling image
height = height * ratio; // Reset height to match scaled image
width = width * ratio; // Reset width to match scaled image
}
// Check if current height is larger than max
if (height > maxHeight) {
ratio = maxHeight / height; // get ratio for scaling image
width = width * ratio; // Reset width to match scaled image
height = height * ratio; // Reset height to match scaled image
}
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
// We set the dimensions at the wanted size.
canvas.width = width;
canvas.height = height;
// We resize the image with the canvas method drawImage();
ctx.drawImage(img, 0, 0, width, height);
var dataURI = canvas.toDataURL();
return dataURI;
}
You may need to wait until the <img> is loaded:
img.onload = function() {
// now your image is ready for use
};

Categories

Resources