Saving an html object to firebase - javascript

I'm working in ember.js my project has an image cropping mechanic. This returns to me by default a canvas object and some data necessary to redraw the cropped image.
But when I try to save the canvas object to firebase it saves it as something like [htmlObject Canvas] or something like that, so when I try to get the record and display the canvas it displays that instead of the actual canvas object.
How can I save a canvas object to firebase to use later as an actual canvas.

You have to serialize and deserialize the image:
function serialize(canvas) {
return canvas.toDataURL();
}
function deserialize(data, canvas) {
var img = new Image();
img.onload = function() {
canvas.width = img.width;
canvas.height = img.height;
canvas.getContext("2d").drawImage(img, 0, 0);
};
img.src = data;
}
Based on this answer.
Update 1
The canvas.toDataURL() method is able to compress the data into JPEG with compression. Using even 95% quality will drastically decrease filesize for photos, compared to PNG.
Use this:
canvas.toDataURL({
format: 'jpeg',
quality: 0.9
});
Based on this answer.

Related

Watermark.js increases image size

Trying to do image optimization(reduce the image size) and add watermaker to multiple images before uploading to cloud env(S3).
Approaches:
browser-image-compression - Used browser-image-compression image optimization working perfectly, but watermark unable to add.
watermark.js - Used watermark.js without image optimization, the size of image getting increased to 2x.
const compressedFile = await imageCompression(file, options)
let compressedFile1 = await watermark([compressedFile]).blob(watermark.text.center('watermark.js',
'300px serif', '#fff', 0.5))
Performance is also the key aspect of both operations.
Don't want to perform any image manipulation serverside or in a cloud environment(serverless image manipulation).
Any idea on how to add a watermark and also, optimize the image without losing the quality of the image?
Thanks
I have a similar use case where users need to take pictures and then these have to be uploaded to a server with a watermark.
First, I add the watermark and then I change the format to JPEG, which has good quality and does not take as much space as the PNG output of watermarkJS.
This is the function called on the output of the watermark (as dataURL):
async convertImageToJpeg(image):Promise<string>{
return new Promise(function (resolved,rejected) {
var i = new Image();
i.onload = function(){
var canvas = document.createElement("canvas");
canvas.width = i.width;
canvas.height = i.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(i,0,0);
var dataUrl = canvas.toDataURL('image/jpeg', 0.3);
resolved(dataUrl);
}
i.src = image;
})
}

canvas2d toDataURL() different output on different browser

I have the same image and the same size of canvas, but the output is different. I want the same output, how should I do it?
var canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d'),
img = new Image;
img.crossOrigin = 'Anonymous';
img.onload = function(){
canvas.height = img.height;
canvas.width = img.width;
ctx.drawImage(img, 0, 0);
var dataURL = canvas.toDataURL();
setBreakpoint(dataURL);
callback.call(this, dataURL);
canvas = null;
};
img.src = url;
Images drawn onto a canvas are decoded before being drawn, then reencoded when the toDataURL method is called.
This process will produce some variations in every browser (e.g some will be able to decode color-profiles embedded in the image while others won't), and even every machine (look at canvas fingerprinting and this post by #Oriol which concern images with transparency). Add to that that every browser will use different encoders/settings for a different tradeoff between speed, size and quality and you arrive at a situation where you can't expect two users to produce the same result from the same input image.
But since all you do with that canvas is to draw an image, you should rather use a FileReader and its method readAsDataURL(). For external files, you can still use it by first fetching the resource as a Blob.
This will work directly on the binary data of the file, encoding each byte to its base64 representation, and thus you will be sure to have the same result in every browser.
Here is a snippet which will test your browser's conversion against mine's.
fetch("https://dl.dropboxusercontent.com/s/4e90e48s5vtmfbd/aaa.png")
.then((resp) => resp.ok && resp.blob())
.then((blob) => {
const reader = new FileReader();
reader.onload = (evt) => {
if (reader.result === imageDataURL) {
console.log("same result");
}
else {
console.log("please post a comment stating which browser has such a bug");
}
};
reader.readAsDataURL(blob);
});
var imageDataURL = "data:image/png;base64,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"
However for the ones using the canvas for real drawing, as we said above, you can't really have the same results between different UAs. Every method from drawing ones to export ones may produce different results and you would have to actually rewrite all these methods entirely in order to have the exact same results.
For the ones that really need this, a project like node-canvas could help, though it would obviously be a lot less performant than native implementations.

AngularJS save and display image from URL

I wish to create a simple function in angularJS so I can read image from URL. Simply I put image URL and it convert image of that URL to base64 and saves to DB as well it shows to that Image Canvas. I wish to read image of all type irrespective of only PNG.
I have tried few logics, from Google I found code where it takes dimensions of canvas first..
$scope.convertBase64 = function () {
console.log("Firing Function");
var canvas = $scope.imageURL;
canvas.width = $scope.imageURL.width;
canvas.height = $scope.imageURL.height;
var ctx = canvas.getContext("2d");
ctx.drawImage($scope.imageURL, 0, 0);
var dataURL = canvas.toDataURL("image/png");
$scope.imageURLBase = dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
return $scope.imageURLBase;
};
At same moment I wish to save image's base64 content. How to render using that base64 content anytime irrespective of canvas size using ng-source or else.

Canvas toDataURL without alpha channel

I'd like to resize uploaded images in browser. I am using canvas to draw the uploaded image to canvas and then resize it, and use the result from toDataURL method.
Simplified code (without upload parts) looks something like this:
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d', { alpha: false} );
// img src contains data url of uploaded image
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
var dataUrl = canvas.toDataURL('image/png');
The problem is dataUrl contains alpha channel, although context was created with alpha set to false.
Is it possible to get data url without the alpha channel?
If not, I considered using one of Javascript image libraries, but most of them rely on canvas.
Also, I could encode the image using data in canvas, but I'd rather not do that :)
alpha:false is only used in WebGL. It's ignored when creating a 2d context.
But you can export the canvas in jpg format where your unwanted alpha is eliminated:
// export a full-quality jpg dataUrl
canvas.toDataURL("image/jpeg", 1.0);

Canvas toDataUrl increases file size of image

When using toDataUrl() to set the source of an image tag I am finding that the image when saved is a great deal larger than the original image.
In the example below I am not specifying a second param for the toDataUrl function so the default quality is being used. This is resulting in an image much larger that the original image size. When specifying 1 for full quality the image generated is even larger.
Does anybody know why this is happening or how I can stop it?
// create image
var image = document.createElement('img');
// set src using remote image location
image.src = 'test.jpg';
// wait til it has loaded
image.onload = function (){
// set up variables
var fWidth = image.width;
var fHeight = image.height;
// create canvas
var canvas = document.createElement('canvas');
canvas.id = 'canvas';
canvas.width = fWidth;
canvas.height = fHeight;
var context = canvas.getContext('2d');
// draw image to canvas
context.drawImage(image, 0, 0, fWidth, fHeight, 0, 0, fWidth, fHeight);
// get data url
dataUrl = canvas.toDataURL('image/jpeg');
// this image when saved is much larger than the image loaded in
document.write('<img src="' + dataUrl + '" />');
}
Thank you :D
Here is an example, unfortunately the image cannot be cross domain and so I am having to just pull one of the jsfiddle images.
http://jsfiddle.net/ptSUd/
The image is 7.4kb, if you then save the image which is being output you will see that it is 10kb. The difference is more noticeable with more detailed images. If you set the toDataUrl quality to 1, the image is then 17kb.
I am also using FireFox 10 for this, when using Chrome the image sizes are still larger but not by as much.
The string returned by the toDataURL() method does not represent the original data.
I have just performed some extensive tests, which showed that the created data-URL depends on the browser (not on the operating system).
Environment - md5 sum - file size
Original file - c9eaf8f2aeb1b383ff2f1c68c0ae1085 - 4776 bytes
WinXP Chrome 17.0.963.79 - 94913afdaba3421da6ddad642132354a - 7702 bytes
Linux Chrome 17.0.963.79 - 94913afdaba3421da6ddad642132354a - 7702 bytes
Linux Firefox 10.0.2 - 4f184006e00a44f6f2dae7ba3982895e - 3909 bytes
The method of getting the data-URI does not matter, the following snippet was used to verify that the data-URI from a file upload are also different:
Test case: http://jsfiddle.net/Fkykx/
<input type="file" id="file"><script>
document.getElementById('file').onchange=function() {
var filereader = new FileReader();
filereader.onload = function(event) {
var img = new Image();
img.onload = function() {
var c = document.createElement('canvas'); // Create canvas
c.width = img.width;
c.height = img.height; c.getContext('2d').drawImage(img,0,0,img.width,img.height);
var toAppend = new Image;
toAppend.title = 'Imported via upload, drawn in a canvas';
toAppend.src = c.toDataURL('image/png');
document.body.appendChild(toAppend);
}
img.src = event.target.result; // Set src from upload, original byte sequence
img.title = 'Imported via file upload';
document.body.appendChild(img);
};
filereader.readAsDataURL(this.files[0]);
}
</script>
The size of the image is determined mostly by the quality of the encoder built into the browser. It has very little to do with the size of the original image. Once you draw anything onto a canvas all you have are pixels, you no longer have the original image. toDataURL does not magically reconstitute an image that was painted onto the canvas. If you want a file with the same size as the original image: use the original image.
Looks like kirilloid and Rob nailed it. I had this issue too and it appears to be a combo:
the dataURL uses base64 encoding which makes it around 1.37 X larger
each browser processes the toDataURL function differently
base64 encoded image size
I tested my thumbnail generator in win8.1 firefox and chrome and got dataURL string sizes:
firefox = 3.72kB
chrome = 3.24kB
My original image when converted to dataURL went from 32kB to 45kB.
I think the base64 part is the larger factor so I guess my plan now is to convert the dataURL back to a binary byte array before I store it on the server (probably on the client side because my server's lazy).

Categories