Html canvas decreases the resolution of images and shapes. Is there a way by which we can increase the quality?
Sure:
const width = ..., height = ..., scale = 2;
const canvas = document.querySelector('...')
canvas.style.width = width;
canvas.style.height = height;
canvas.width = width * scale;
canvas.height = height * scale;
Related
const canvas = document.querySelector('canvas');
canvas.style.width = 750+"px";
canvas.style.height = 250+"px";
OR
canvas.width = 750;
canvas.height = 250;
I just want to know which is the right way to do it
I have a boundingBox selecting a zone in a image and i would like to scale this boundingBox to my canvas ratio.
I would like to recalculate the ratio of my boundingBox to correctly target a zone of the resized image in the canvas.
Here an example + jsFiddle : ( this is an example, the real project use multiple boundingBox with a big range of images)``
The boundingBox coordinate / width and height are calculated from the image but after the transformation i dont know how to convert the coordinate / ratio.
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext("2d");
//bbox
let [bx, by, bw, bh] = [146, 58, 82, 87]
console.log(bx, by, bw, bh)
function bboxDraw(){
// Draw the bounding box.
ctx.strokeStyle = "#00FFFF";
ctx.lineWidth = 4;
ctx.strokeRect(bx, by, bw, bh);
// Draw the label background.
ctx.fillStyle = "#00FFFF";
}
function scaleToFill(img, callback){
canvas.width = window.innerWidth
canvas.height = window.innerHeight
// get the scale
var scale = Math.max(canvas.width / img.width, canvas.height / img.height);
// get the top left position of the image
var x = (canvas.width / 2) - (img.width / 2) * scale;
var y = (canvas.height / 2) - (img.height / 2) * scale;
ctx.drawImage(img, x, y, img.width * scale, img.height * scale);
bboxDraw()
}
let img = new Image()
try {
img.src = "https://via.placeholder.com/1280x720"
} catch (error) {
console.log("image URL", error);
}
img.onload = function() {
scaleToFill(this)
}
JSFiddle
Any good idea to preserve the ratio after the scale2fill transformation and correctly target the boundingBox area ?
To recalculate BoundingBox coordinates from image after scale to fill transformation in HTML Canvas.
We need to recalculate the width/height/x/y of the boundingBox using the naturalWidth and naturalHeight of the image.
let [bx, by, bw, bh] = [146, 58, 82, 87]
function bboxRatioDraw(img) {
// Use percent to correctly adapt the coordinate to the scaled image
let percentBx = (100 * (bx / img.naturalWidth)), // x %
percentBy = (100 * (by / img.naturalHeight)), // y %
percentBw = (bw * 100) / img.naturalWidth, // width%
percentBh = (bh * 100) / img.naturalHeight; // height%
// then map the values to the current canvas
let finalBx = (percentBx * canvas.width) / 100, // x en pixel
finalBy = (percentBy * canvas.height) / 100, // y en pixel
finalBw = (percentBw * canvas.width) / 100, // width en pixel
finalBh = (percentBh * canvas.height) / 100; // height en pixel
// Draw the bounding box.
ctx.strokeStyle = "green";
ctx.lineWidth = 4;
ctx.strokeRect(finalBx, finalBy, finalBw, finalBh);
// Draw the label background.
ctx.fillStyle = "#00FFFF";
}
Updated JSFiddle
Im resizing the image size to make it smaller im taking 20% of the height and 20% of the width. but im getting wrong result is getting me a higher size of an image.
function imageToDataUri(img, width, height) {
var canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d');
canvas.width = width;
canvas.height = height;
ctx.drawImage(img, 0, 0, width, height);
return canvas.toDataURL();
}
imageToAdjust = 'data:image/png;base64,' + window.btoa(e.target.result);
var img = new Image;
img.onload = resizeImage;
img.src = imageToAdjust;
function resizeImage() {
console.log(img.width);
console.log(img.height);
var x = img.width - (0.2 * img.width);
var y = img.height - (0.2 * img.height);
console.log(x);
console.log(y);
var newDataUri = imageToDataUri(this, x, y);
console.log(newDataUri);
var base64 = newDataUri.match(/data:(.+);base64,(.+)/);
console.log('after resizing');
console.log(base64);
var base64Number = Math.round((base64[2].length )*3/4) ;
console.log(base64Number);
}
what im getting through console.logs is for example i have image with size is 5663096 width 4032 and height 3024 then after i take 20% off im getting it width 3225.6 and height 2419.2 which is correct. but after i call imageToDataUri(this, x, y); function the image size will be 12031242 which is double. it should be smaller than 5663096
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
};
My autoresize canvas not works with kineticjs, the console say me that canvas.width and canvas.height is not defined.
Any people could help me.
Thank you .
Put the function and the call down.
function resize() {
console.log("ddddddddddddd");
//stage.setWidth((window.innerWidth / 100) * 80);
var canvas = document.getElementById('Contenedor');
console.log(canvas, canvas.height, canvas.width);
if(window.innerWidth < 1280){
var canvasRatio = canvas.height / canvas.width;
console.log(canvasRatio);
var windowRatio = window.innerHeight / window.innerWidth;
console.log(windowRatio);
var width;
var height;
if (windowRatio < canvasRatio) {
height = window.innerHeight;
width = height / canvasRatio;
} else {
width = window.innerWidth;
height = width * canvasRatio;
}
canvas.style.width = (parseFloat(width)*0.75) + 'px';
canvas.style.height = (parseFloat(height)*0.75) + 'px';
}else{
canvas.style.width=987+'px';
canvas.style.height=544+'px';
}
};
window.addEventListener('resize', resize, false);
What you can do is set the height of the canvas with respect to the width.
And use stage.setScale() and stage.setSize() to dynamically change the size of the stage
function resize() {
var canvasWidthRatio = 0.6; // canvas width to viewport width ratio
var viewPortWidth = window.innerWidth;
var canvasWidth = viewPortWidth * canvasWidthRatio;
var canvasHeight = canvasWidth * 0.6,
scale = stage.getScale(),
stageWidth = stage.getWidth(),
stageHeight = stage.getHeight(),
scaleFactor = Math.min(canvasWidth / stageWidth, canvasHeight / stageHeight),
newScale = scale * scaleFactor;
stage.setScale(newScale);
stage.setSize(canvasWidth, canvasHeight);
stage.draw();
}
window.addEventListener('resize', resize, false);
I think kineticjs sets the canvas dimensions.
set the stage width and height and don't touch the canvas directly.
Hello and sorry my bad english, also thank you to help me. I work with the code of VijayB, but with his code I have problems with multiply the object scale with a float.. I realease a few changes and for me are working.
I put the code for someone that have my own problem.
function resize() {
var __canvasWidthRatio = 0.6;
console.log( __canvasWidthRatio) ; // canvas width to viewport width ratio
var __viewPortWidth = window.innerWidth;
console.log(window.innerWidth);
var __canvasWidth = __viewPortWidth * __canvasWidthRatio;
console.log(__canvasWidth);
var aspec = 769 / 544;
var __canvasHeight = aspec *__canvasWidth * __canvasWidthRatio;
var __scale = ui.stage.getScale();
var __stageWidth = ui.stage.getWidth();
var __stageHeight = ui.stage.getHeight();
var __scaleFactor = Math.min( __canvasWidth / __stageWidth, __canvasHeight / __stageHeight);
stage.escala= __scale.x *__scaleFactor;
ui.scale=__scale.x *__scaleFactor;
stage.setScale(stage.escala,stage.escala);
stage.setSize(__canvasWidth, __canvasHeight);
stage.draw();
}
window.addEventListener('resize', resize, false);