How to resize a centered image on a canvas? - javascript

The code I have below will take an uploaded image and center it on a canvas, it is working but I'm unable to change the size of the actual image. I want to be able to upload an image and then scale it down by a percentage or pixel with it centered.
The way it works right now is you upload an image and it automatically gets populated on the canvas. The final product will return a base64 string that I will convert using C#.
Any help would be great, thanks.
Codepen Link
HTML:
<input type="file">
Javascript:
$("input").on("change", function(e) {
var file = this.files[0];
if (!file) return;
var fileReader = new FileReader();
fileReader.onload = () => {
var image = new Image();
image.onload = () => {
canvas.width = image.width;
canvas.height = image.height;
var context = canvas.getContext("2d");
// Change Background
context.beginPath();
context.rect(0, 0, 1000, 1000);
context.fillStyle = "#7D8491";
context.fill();
// Draw Logo
context.drawImage(image, canvas.width / 2 - image.width / 2,
canvas.height / 2 - image.height / 2);
// Append to body
$("body").append(canvas);
// Open base64 url
//window.open(canvas.toDataURL("image/png"));
};
image.src = fileReader.result;
};
fileReader.readAsDataURL(file);
var canvas = document.createElement("canvas");
});

I simply had to divide both the position and the actual width/height by the percentage I wanted to scale the image down.
// Draw Logo
context.drawImage(
image,
canvas.width / 2 - image.width * .75 / 2,
canvas.height / 2 - image.height * .75 / 2,
image.width * .75, image.height * .75
);

Related

Custom crop method isn't working in iPhone

Im facing this STRANGEST issue in my website. The method given below takes a base64 string and the crop, zoom and rotation values and returns a modified base64 string. This method works absolutely fine on all the android devices and desktops. But when an iPhone is used, this methods returns a base64 string that when converted is a plain black image. I have no clue why its behaving like this on all the iPhones.
Extra info : This only happens for the HEIF images that are automatically converted to jpeg when a user selects them from the iPhone's gallery. For other formats like jpg and png the method works fine even on iPhone.
Here's the crop method
async function getCroppedImg(imageSrc, pixelCrop, rotation) {
console.log('imagesrc : ', imageSrc)
const image = await createImage(imageSrc);
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
const maxSize = Math.max(image.width, image.height);
const safeArea = 2 * ((maxSize / 2) * Math.sqrt(2));
canvas.width = safeArea;
canvas.height = safeArea;
ctx.translate(safeArea / 2, safeArea / 2);
ctx.rotate(getRadianAngle(rotation));
ctx.translate(-safeArea / 2, -safeArea / 2);
ctx.drawImage(
image,
safeArea / 2 - image.width * 0.5,
safeArea / 2 - image.height * 0.5
);
const data = ctx.getImageData(0, 0, safeArea, safeArea);
canvas.width = pixelCrop.width;
canvas.height = pixelCrop.height;
ctx.putImageData(
data,
0 - safeArea / 2 + image.width * 0.5 - pixelCrop.x,
0 - safeArea / 2 + image.height * 0.5 - pixelCrop.y
);
// As Base64 string
return canvas.toDataURL("image/jpeg");
}
const createImage = (url) =>
new Promise((resolve, reject) => {
const image = new Image();
image.addEventListener("load", () => resolve(image));
image.addEventListener("error", (error) => reject(error));
image.setAttribute("crossOrigin", "anonymous");
image.src = url;
});
function getRadianAngle(degreeValue) {
return (degreeValue * Math.PI) / 180;
}

Image rotation using canvas

I need to rotate an image through canvas and through the cropper.js library I can do the rotation of the image but save the image and condition it with canvas does not save me with the format of the rotation.
In my code what I have is an event that makes me rotating towards 90 or -90 degrees. Then when saving the image I need to be saved with that format.
I need to rotate on the axis of the image so that when the image is saved with rotate canvas it is saved with the correct position. I have seen some ways to do it but it has not worked for me, I do not know that I am losing.
//Events to rotate using cropper Js library
'click #rotateL': function(e, instance){
$('#target').cropper('rotate', -90);
angleInDegrees = angleInDegrees - 90 ;
drawRotated(angleInDegrees);
},
'click #rotateR': function(events, instance){
$('#target').cropper('rotate', 90);
angleInDegrees += 90;
drawRotated(angleInDegrees);
},
function drawRotated(degrees){
var canvas = $("#canvas")[0];
var context = canvas.getContext('2d');
var image = document.createElement("img");
image.src = $('#target').attr("src");
image.onload = function () {
context.drawImage(image,(canvas.width - x1) / 2,
(canvas.height - y1) / 2,x1, y1);
//ctx.drawImage(img, x, y, width, height)
}
context.clearRect(0,0,canvas.width,canvas.height);
context.save();
context.translate(canvas.width/2,canvas.height/2);
context.rotate(degrees*Math.PI/180);
context.drawImage(image, -x1/2,-y1/2);
context.restore();
var dataURL = canvas.toDataURL("image/jpeg");
Session.set("url", dataURL);
}
// event that saves the changes made when you cut the image or rotate.
'click #Save' : function(e) {
$(".loader").fadeIn("slow");
e.preventDefault();
var photoid = $('#photoid').val();
var dataURL = Session.get("url");
var photo = {
srcData : dataURL,
userid : Meteor.userId(),
photo_id : photoid
}
Meteor.call('updatePhoto',photo,function(err) {
if (!err) {
$('#photos').show();
$('#crops').hide();
canvas.height = 0;
canvas.width = 0;
//page relod is better than
//document.getElementById('target').src="";
FlowRouter.go('/search');
FlowRouter.go('/addphoto');
}
});
},
If you are using cropper.js. You can use build-in method getCroppedCanvas to get edited and cropped new canvas back. There is no bother to write on your own.
var canvas = $ ('# target').cropper ('getCroppedCanvas');
console.log (canvas)
var dataURL = canvas.toDataURL ("image / jpeg");
To rotate 90 deg clockwise on a new canvas.
// assuming that image is a loaded image.
const canvas = document.createElement("canvas");
canvas.width = image.height;
canvas.height = image.width;
const ctx = canvas.getContext("2d");
ctx.setTransform(
0,1, // x axis down the screen
-1,0, // y axis across the screen from right to left
image.height, // x origin is on the right side of the canvas
0 // y origin is at the top
);
ctx.drawImage(image,0,0);
To rotate -90Deg onto a new canvas
const canvas = document.createElement("canvas");
canvas.width = image.height;
canvas.height = image.width;
const ctx = canvas.getContext("2d");
ctx.setTransform(
0,-1, // x axis up the screen
1,0, // y axis across the screen from left to right
0, // x origin is on the left side of the canvas
image.width // y origin is at the bottom
);
ctx.drawImage(image,0,0);
The origins are where the top left corner of the image ends up being after the rotation.

How to rotate the canvas by 90 degree in Firefox

I’m trying to rotate the html5 canvas to 90 degree by below code snippet. It working fine in all browsers except Firefox.
var canvas = document.getElementById('pagecanvas_' + i);
var canvasUrl = canvas.toDataURL();
var context = canvas.getContext('2d');
var image = new Image();
context.save();
context.translate(canvas.width / 2, canvas.height / 2);
context.rotate(-Math.PI / 2);
image.src = canvasUrl;
context.drawImage(image, -image.width/2 , -image.height/2);
context.restore();
Please provide your idea to overcome this issue. Also let me know if I’m doing any think wrong?
It looks like you got a few things mixed up here. Load the image first, then draw the image to the canvas. You cant intermingle it like that and expect consistent, or even working, results
var canvas = document.getElementById('pagecanvas_' + i);
var canvasUrl = canvas.toDataURL();
var context = canvas.getContext('2d');
var image = new Image();
img.onload = function(){
drawCanvas();
}
img.src = canvasUrl;
function drawCanvas(){
context.save();
context.translate(canvas.width / 2, canvas.height / 2);
context.rotate(-Math.PI / 2);
context.drawImage(image, -image.width/2 , -image.height/2);
context.translate(-canvas.width / 2, -canvas.height / 2);
context.restore();
}

javascript - Why does this canvas image not rotate correctly?

Why does this canvas image not rotate correctly?
When I click the rotate button the image rotates but gets cropped weirdly. I want the image to stay intact and simply rotate.
Important: I'm not looking to rotate the div, I'm looking to rotate the actual image.
See fiddle:
http://jsfiddle.net/8V4V7/2/
Code:
function rotateBase64Image(base64data, callback) {
console.log("what we get: " + base64data);
var canvas = document.getElementById("dummyCanvas");
var ctx = canvas.getContext("2d");
var image = new Image();
image.src = base64data;
image.onload = function() {
ctx.translate(image.width, image.height);
ctx.rotate(Math.PI);
ctx.drawImage(image, 0, 0);
callback(canvas.toDataURL());
};
}
EDIT:
I need the image to rotate by 90 degrees on every click.
I tried the following but it doesn't work:
ctx.rotate(Math.PI/2);
This worked for me (I specified the height and width of the canvas inside the onload function):
function rotateBase64Image(base64data, callback) {
console.log("what we get: " + base64data);
var canvas = document.getElementById("dummyCanvas");
var ctx = canvas.getContext("2d");
var image = new Image();
image.src = base64data;
image.onload = function () {
canvas.height = image.height;
canvas.width = image.width;
ctx.translate(image.width, image.height);
ctx.rotate(Math.PI);
ctx.drawImage(image, 0, 0);
callback(canvas.toDataURL());
};
}
Edit
Updated function to rotate 90 degrees with every click (remove i in i*Math.PI to rotate 90 degrees only once)
var i = 0;
function rotateBase64Image(base64data, callback) {
console.log("what we get: " + base64data);
var canvas = document.getElementById("dummyCanvas");
var ctx = canvas.getContext("2d");
var image = new Image();
image.src = base64data;
image.onload = function() {
canvas.width = image.height;
canvas.height = image.width;
ctx.translate(canvas.width / 2, canvas.height / 2);
i++;
ctx.rotate(i*Math.PI/2);
ctx.translate(-canvas.width / 2, -canvas.height / 2);
ctx.drawImage(image, 0, 0);
};
}
Updated Fiddle
Just some supporting info for rotations, notably the saving of the context and how to rotate around the center of the image.
var context = canvas.getContext('2d');
//save the context
//pushes a Matrix on the transformation stack
context.save();
context.translate(x, y); //where to put image
context.rotate(angle); //angle in degrees (i think...)
context.scale(scale); //optional scale
//rotate around center of image
context.drawImage(bitmap, -image.width / 2, -image.height / 2);
//or rotate around top left corner of image
context.drawImage(image, 0, 0);
//restore the canvas
//pop a matrix off the transformation stack
context.restore();
References:
https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Transformations
http://html5.litten.com/understanding-save-and-restore-for-the-canvas-context/

Image scaling works locally but not when ran from server

I am trying to scale images when loaded into the browser. Here is my code that I am working with -
function importImage(e) {
var canvas = document.getElementsByTagName('canvas')[0];
var ctx = canvas.getContext('2d');
var reader = new FileReader;
reader.onload = function(event) {
event.preventDefault();
var img = new Image;
img.src = event.target.result;
img.onload = function() {
width = img.width;
height = img.height;
var scaleX, scaleY, scale;
var scaledWidth, scaledHeight;
scaleX = width / canvas.width;
scaleY = height / canvas.height;
scale = scaleX > scaleY ? scaleX : scaleY;
scaledWidth = width / scale;
scaledHeight = height / scale;
ctx.clearRect(0,0, canvas.width, canvas.height);
ctx.drawImage(img, (canvas.width - scaledWidth) / 2, (canvas.height - scaledHeight) / 2, scaledWidth, scaledHeight);
}
}
reader.readAsDataURL(e.target.files[0]);
}
It seems to works ok when used from a local machine but when it is ran from the server the scaling doesn't work. I assume it is to do with how I am referring to the actual image but I am unsure.

Categories

Resources