I'd like to be able to detect if a logo type image has a transparent background or not, let's imagin that two similar images are .png files but one has a white background and another on has a transparent background, how would I be able to determine the one with transparency ?
I've tried using colorthief but it doesn't take transparency into account, so I thought doing it by myself on canvas. A first solution would be to convert the png file into jpg and if the background color of the jpg after being converted appear to be black then it's a transparent logo, but this might be a problem for users with black background and white logos. Is there a better solution than that ?
http://jsfiddle.net/9s5qf5cu/
from png to jpg :
var imageLoader = document.getElementById('imageLoader');
imageLoader.addEventListener('change', handleImage, false);
var canvas = document.getElementById('imageCanvas');
var ctx = canvas.getContext('2d');
function handleImage(e){
var reader = new FileReader();
reader.onload = function(event){
var img = new Image();
img.onload = function(){
canvas.width = 100;
canvas.height = 100;
ctx.drawImage(img,0,0, 100, 100);
document.getElementById("image").src = canvas.toDataURL("image/jpeg");
}
img.src = event.target.result;
}
reader.readAsDataURL(e.target.files[0]);
}
Use this function by passing your context and your canvas. Then it will loop over the alpha channel until it finds an entry that is not completely opaque.
function hasAlpha (context, canvas) {
var data = context.getImageData(0, 0, canvas.width, canvas.height).data,
hasAlphaPixels = false;
for (var i = 3, n = data.length; i < n; i+=4) {
if (data[i] < 255) {
hasAlphaPixels = true;
break;
}
}
return hasAlphaPixels;
}
Note: this will not work if your canvas is tainted.
Related
I'm importing an image (that has to come in portrait) onto a canvas object, rotating it (because it's actually landscape) and running some OCR on the base64 from the canvas. That all works fine. However when I put a new image onto the canvas, the old one is retained and never replaced. I've tried clearRect, even gone to the extent of creating a new dom element each time and destroying it when I have everything I need (which is still in the code below) but I just cannot get the first image to clear.
Here's the relevant bit of the code
function onSuccess(imageURI) {
//CREATE NEW CANVAS ELEMENT
g = document.createElement('canvas');
g.setAttribute("id", "thePic");
g.style.overflow = "visible";
document.body.appendChild(g);
const canvas = document.getElementById('thePic'),
context = canvas.getContext('2d');
make_base();
function make_base()
{
base_image = new Image();
base_image.src = imageURI;
base_image.onload = function(){
const uriheight = base_image.naturalHeight;
const uriwidth = base_image.naturalWidth;
console.log(uriwidth + " " + uriheight);
context.canvas.width = uriheight;
context.canvas.height = uriheight;
context.drawImage(base_image, 0, 0);
//ROTATE THE IMAGE 90
context.clearRect(0,0,canvas.width,canvas.height);
context.save();
context.translate(canvas.width/2,canvas.height/2);
context.rotate(90*Math.PI/180);
context.drawImage(base_image,-base_image.width/1.2,-base_image.width/1.2);
context.restore();
var theCanvas = document.getElementById('thePic');
var rotImg = theCanvas.toDataURL();
var rotImg = rotImg.substring(21);
textocr.recText(4, rotImg, onSuccess, onFail);
function onSuccess(recognizedText) {
var recdata = recognizedText.lines.linetext;
var blockData = recognizedText.blocks.blocktext;
context.clearRect(0, 0, 10000,10000);
base_image = "";
rotImg = "";
document.getElementById('thePic').outerHTML = "";
document.getElementById('cgh').innerHTML = "";
}
}
}
Any advice much appreciated.
So it turned out to not be the canvas at all, it was image caching in a previous function that give the image to the canvas.
Thanks to everyone who took the time to have a squiz.
I am trying to draw an image in the canvas. The image that I'm using is got as base64 string from the server. For testing purpose, I have saved the image to the disk both at the client and the server while debugging. The image is saved fine. While drawing in the canvas, the image is not rendered in Chrome and Firefox. But it works fine in IE 11.Is there any way to make the images draw in all the browsers.
var base64String = "data:image/png;base64,SUkqANZ1AQAAEbQhURQh0dUQ6mh0dHQ62ao6GIEQkpodHSEOqKiHXodDqaoh1NOqKaOjo6HU0dUQ6mqIdeh16dSUJQqJCmh0hUR0OvQ6HU0OqIdenXodTQ69DqidTVEdOpodIXIdDr1RDokXIdeh0OuQ6HXodDr0Oh16HQ6oh16HQ6mh1NDqioi6XS0OqKidcnXp16HTr0OqIdHQ69Dodch1PHX469D1EOvQ6HU0OqIdch0hUQ2h0dF0DVEOqI6HS2tgiHQ65Do6Qh1NDqiQqIdHU0OhiOhCHU0dOqL0OpqiHXodDpe0XR0OvQ6QqIdHVE69DqaHXpOADuamqIujo6IR1t1RHVEhHR0dBqiOi6OkI6BobS8IQgRF1RHSEDR0dA0hNypCEOqIhAilqtlCS1uEDSEDQmhpURCmh0XR1sYqI6Bo6og0NI6QkJCLoGhpSLpCGJCEJCQjoQh0dIVEdBEDRmACU.." //only few of the string is shared
function drwImage(base64String) {
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
var img = new Image();
img.onload=function(){
context.drawImage(img, 0, 0, 1, 1);
}
img.src = base64String;
}
Thanks for your help in advance.
Seems something related to the serialized image, as you can see in the snippet below, it works on Chrome, I used an online encoder.
As you can read here the datauri is almost supported at all.
var base64String = "data:image/jpeg;base64,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" //only few of the string is shared
drwImage(base64String);
function drwImage(b) {
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
var img = new Image();
img.onload = function() {
console.log('load')
context.drawImage(img, 0, 0, 1, 1);
document.body.appendChild(img);
}
img.onerror = function() {
console.log('error')
}
img.src = b;
}
I have an image on canvas or a set of images that i draw on the canvas. I can draw them fine but I want to change the window level of the image on canvas by dragging the mouse over it. I've seen a lot of external javascript api's but they're quite huge and i don't want to use them for this purpose.
here's my JSFIDDLE that is basically drawing an image on the canvas
this is how my code looks
// Grab the Canvas and Drawing Context
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
// Create an image element
var img = document.createElement('IMG');
// When the image is loaded, draw it
img.onload = function () {
ctx.drawImage(img, 0, 0);
}
// Specify the src to load the image
img.src = "http://imgsv.imaging.nikon.com/lineup/lens/zoom/normalzoom/af-s_dx_18-140mmf_35-56g_ed_vr/img/sample/sample5_l.jpg";
i need something with basic JS or JQuery. it would be great if you can point me in the right direction using a sample code.
Thanks in advance.
If you want to use JavaScript, try something like:
<script>
var c = document.getElementById("drawingboard");
var ctx = c.getContext("2d");
var mouseDown = 0;
document.body.ontouchstart = function() {
mouseDown+=1;
}
document.body.ontouchend = function() {
mouseDown-=1;
}
function draw(event){
ctx.color='gold';
ctx.fillStyle = "lime";
ctx.drawImage(img,event.clientX,event.clientY);}
</script>
This is what I gained after some research:
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const rangeMin = level - window / 2;
const rangeMax = level + window / 2;
const totalSize = canvas.width * canvas.height;
for (let idx = 0; idx < totalSize; idx++) {
if (imageData.data[idx] < rangeMin) {
imageData.data[idx] = 0;
} else if (imageData.data[idx] > rangeMax) {
imageData.data[idx] = 255;
}
}
ctx.putImageData(imageData, 0, 0);
I want to resize (as in reduce the filesize if it exceeds limit) an Image using canvas. I see that the resultant image size drawn on canvas, keeping the width and height constant, results in different file size depending upon what has been drawn on canvas.
I am willing to reduce the resolution further provided I get the desired file size.
How do I make sure whatever the resolution I get file(image) size within the limit?
Refer to this fiddle
var el = document.getElementById('f');
el.addEventListener('change', onChange);
function onChange(e) {
var file = this.files[0];
console.log("CHANGING");
var fr = new FileReader();
fr.onload = function(e) {
drawOnCanvas(e.target.result);
}
fr.readAsDataURL(file);
}
function drawOnCanvas(imgSrc) {
var canv = document.createElement('canvas'),
img = new Image();
console.log("DRAWING");
canv.width = canv.height = 500;
ctx = canv.getContext('2d');
img.onload = function() {
console.log("IMAGE LOADED");
ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, canv.width, canv.height);
try {
document.body.removeChild(document.querySelector('canvas'));
} catch (e) {}
document.body.appendChild(canv);
blob = canvasToFile(canv.toDataURL());
alert("FILE SIZE " + blob.size);
}
img.src = imgSrc;
}
function canvasToFile(dataUrl) {
var encData = dataUrl.split(',')[1],
binString = atob(encData),
binData = new Uint8Array(binString.length),
i, blob;
for (i = 0; i < binString.length; i++) {
binData[i] = binString.charCodeAt(i);
}
blob = new Blob([binData], {
type: 'image/jpeg'
});
return blob;
}
<p>Try uploading different image file and see the difference in size for same output resolution:</p>
<input type="file" id="f">
What you are experiencing is that the default type argument for canvas.toDataURL(type, encoderOptions) is image/png, and also that it's actually a base64 encode of the image data.
For the former, most browsers do support image/jpeg as image type. This may reduce the data size, thanks to jpg compression, but this will above all enable the encoderOptions parameter of the method, which could be translated to quality parameter and requires a 0 to 1 float.
Note that you can't be sure that the data will be lighter if converted into jpg though : if the image is mainly composed of transparent pixels, then png will be lighter. Also, remember that jpeg compression will reduce the quality of your image, see the last snippet to see what 0 results in :)
For the later, ( you can find an explanation of the why here ), the solution is to transform back the dataURL to a blob.
Here is a snippet to demonstrate it :
var input = document.querySelector('input');
var canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d');
function draw(){
var img = new Image();
img.src = URL.createObjectURL(this.files[0]);
img.onload = function(){
canvas.width = this.naturalWidth;
canvas.height = this.naturalHeight;
ctx.drawImage(this, 0,0);
var noData = canvas.toDataURL();
png_data.innerHTML = 'dataURL length: '+noData.length;
var noBlob = dataURItoBlob(noData);
png_blob.innerHTML = 'blob size: '+ noBlob.size;
var jpgData10 = canvas.toDataURL('image/jpeg', 1),
jpgData5 = canvas.toDataURL('image/jpeg', 0.5),
jpgData0 = canvas.toDataURL('image/jpeg', 0);
jpg_data.innerHTML = 'quality = 1 : '+ jpgData10.length+'<br>';
jpg_data.innerHTML += 'quality = 0.5 : '+ jpgData5.length+'<br>';
jpg_data.innerHTML += 'quality = 0 :'+ jpgData0.length+'<br>';
var jpgBlob10 = dataURItoBlob(jpgData10);
jpg_blob.innerHTML = 'blob quality = 1 : '+jpgBlob10.size+'<br>';
var jpgBlob5 = dataURItoBlob(jpgData5);
jpg_blob.innerHTML += 'blob quality = .5 : '+jpgBlob5.size+'<br>';
var jpgBlob0 = dataURItoBlob(jpgData0);
jpg_blob.innerHTML += 'blob quality = 0 : '+jpgBlob0.size;
}
this.previousElementSibling.innerHTML = 'orginal size : '+this.files[0].size;
}
input.onchange = draw;
// Taken from https://stackoverflow.com/a/5100158/3702797
function dataURItoBlob(dataURI) {
var byteString;
if (dataURI.split(',')[0].indexOf('base64') >= 0)
byteString = atob(dataURI.split(',')[1]);
else
byteString = unescape(dataURI.split(',')[1]);
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
var ia = new Uint8Array(byteString.length);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ia], {type:mimeString});
}
<div></div>
<input type="file"/>
<br>PNG :
<div id="png_data"></div>
<div id="png_blob"></div>
<br>Jpeg :
<div id="jpg_data"></div>
<div id="jpg_blob"></div>
canvas.toDataURL('image/jpeg', 0) demo ?
var canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d');
document.querySelector('input').onchange = function(){
var img = new Image();
img.src = URL.createObjectURL(this.files[0]);
img.onload = function(){
canvas.width = this.naturalWidth;
canvas.height = this.naturalHeight;
ctx.drawImage(this, 0,0);
document.images[0].src = canvas.toDataURL('image/jpeg', 0);
}
}
<input type="file"/>
<img/>
Also, if you need to make your file lighter than a specific size, I wrote something on another question, which limited the data size to 3Mb (just change maxSize to your needs and remove the localStorage part).
I have a canvas which is loaded with a png image. I get its jpg base64 string by .toDataURL() method like this:
$('#base64str').val(canvas.toDataURL("image/jpeg"));
But the transparent parts of the png image are shown black in the new jpg image.
Any solutions to change this color to white? Thanks in advance.
This blackening occurs because the 'image/jpeg' conversion involves setting the alpha of all canvas pixels to fully opaque (alpha=255). The problem is that transparent canvas pixels are colored fully-black-but-transparent. So when you turn these black pixels opaque, the result is a blackened jpeg.
The workaround is to manually change all non-opaque canvas pixels to your desired white color instead of black.
That way when they are made opaque they will appear as white instead of black pixels.
Here's how:
// change non-opaque pixels to white
var imgData=ctx.getImageData(0,0,canvas.width,canvas.height);
var data=imgData.data;
for(var i=0;i<data.length;i+=4){
if(data[i+3]<255){
data[i]=255;
data[i+1]=255;
data[i+2]=255;
data[i+3]=255;
}
}
ctx.putImageData(imgData,0,0);
After spending a lot of time on this and this post specifically, and these solutions kinda worked expect I just couldn't get the canvas to look right. Anyway I found this solution elsewhere and wanted to post it here incase it helps someone else from spending hours trying to get the black background to white and look like the original.
public getURI(): string {
let canvas = <HTMLCanvasElement>document.getElementById('chartcanvas');
var newCanvas = <HTMLCanvasElement>canvas.cloneNode(true);
var ctx = newCanvas.getContext('2d');
ctx.fillStyle = "#FFF";
ctx.fillRect(0, 0, newCanvas.width, newCanvas.height);
ctx.drawImage(canvas, 0, 0);
return newCanvas.toDataURL("image/jpeg");
}
This answer is a bit longer, but I find it to be more 'correct' in that it handles these things without directly modifying raw canvas data. I find that to be a pretty messy and theoretically unsatisfying solution. There are built in functions to achieve that, and they ought to be used. Here is the solution I found/pilfered:
function canvasToImage(backgroundColor){
var context = document.getElementById('canvas').getContext('2d');
canvas = context.canvas;
//cache height and width
var w = canvas.width;
var h = canvas.height;
var data;
//get the current ImageData for the canvas.
data = context.getImageData(0, 0, w, h);
//store the current globalCompositeOperation
var compositeOperation = context.globalCompositeOperation;
//set to draw behind current content
context.globalCompositeOperation = "destination-over";
//set background color
context.fillStyle = backgroundColor;
//draw background / rect on entire canvas
context.fillRect(0,0,w,h);
//get the image data from the canvas
var imageData = this.canvas.toDataURL("image/jpeg");
//clear the canvas
context.clearRect (0,0,w,h);
//restore it with original / cached ImageData
context.putImageData(data, 0,0);
//reset the globalCompositeOperation to what it was
context.globalCompositeOperation = compositeOperation;
//return the Base64 encoded data url string
return imageData;
}
Basically, you create a white background image and underlay it under the canvas and then print that. This function is mostly plagiarized from someone's blog, but it required a bit of modification -- such as actually getting the context -- and copied directly from my (working) code, so as long as your canvas element has the id 'canvas', you should be able to copy/paste it and have it work.
This is the blog post I modified it from:
http://www.mikechambers.com/blog/2011/01/31/setting-the-background-color-when-generating-images-from-canvas-todataurl/
The big advantage of my function over this is that it outputs to jpeg instead of png, which is more likely to work well in chrome, which has a dataurl limit of 2MB, and it actually grabs the context, which was a glaring omission in the original function.
Marks answer is correct, but when a picture has some antialiasing applied, the exported image won't be as good as it should be (mainly text). I would like to enhance his solution:
// change non-opaque pixels to white
var imgData=ctx.getImageData(0,0,canvas.width,canvas.height);
var data=imgData.data;
for(var i=0;i<data.length;i+=4){
if(data[i+3]<255){
data[i] = 255 - data[i];
data[i+1] = 255 - data[i+1];
data[i+2] = 255 - data[i+2];
data[i+3] = 255 - data[i+3];
}
}
ctx.putImageData(imgData,0,0);
If you want to move to white only full transparent pixels just check for (data[i+3]==0) instead of (data[i+3]<255).
Why not to save it as PNG?
canvas.toDataURL("image/png");
// change non-opaque pixels to white
var imgData=ctx.getImageData(0,0,canvas.width,canvas.height);
var data=imgData.data;
for(var i=0;i<data.length;i+=4){
if(data[i+3]<255){
data[i] = 255 - data[i];
data[i+1] = 255 - data[i+1];
data[i+2] = 255 - data[i+2];
data[i+3] = 255 - data[i+3];
}
Here is my function that resizes a photo and handles the black transparent background problem:
resizeImage({ file, maxSize, backgroundColor }) {
const fr = new FileReader();
const img = new Image();
const dataURItoBlob = (dataURI) => {
const bytes = (dataURI.split(',')[0].indexOf('base64') >= 0)
? window.atob(dataURI.split(',')[1])
: window.unescape(dataURI.split(',')[1]);
const mime = dataURI.split(',')[0].split(':')[1].split(';')[0];
const max = bytes.length;
const ia = new Uint8Array(max);
for (let i = 0; i < max; i += 1) {
ia[i] = bytes.charCodeAt(i);
}
return new Blob([ia], { type: mime });
};
const resize = () => {
// create a canvas element to manipulate
const canvas = document.createElement('canvas');
canvas.setAttribute('id', 'canvas');
const context = canvas.getContext('2d');
// setup some resizing definitions
let { width, height } = img;
const isTooWide = ((width > height) && (width > maxSize));
const isTooTall = (height > maxSize);
// resize according to `maxSize`
if (isTooWide) {
height *= maxSize / width;
width = maxSize;
} else if (isTooTall) {
width *= maxSize / height;
height = maxSize;
}
// resize the canvas
canvas.width = width;
canvas.height = height;
// place the image on the canvas
context.drawImage(img, 0, 0, width, height);
// get the current ImageData for the canvas
const data = context.getImageData(0, 0, width, height);
// store the current globalCompositeOperation
const compositeOperation = context.globalCompositeOperation;
// set to draw behind current content
context.globalCompositeOperation = 'destination-over';
// set background color
context.fillStyle = backgroundColor;
// draw background / rect on entire canvas
context.fillRect(0, 0, width, height);
// get the image data from the canvas
const imageData = canvas.toDataURL('image/jpeg');
// clear the canvas
context.clearRect(0, 0, width, height);
// restore it with original / cached ImageData
context.putImageData(data, 0, 0);
// reset the globalCompositeOperation to what it was
context.globalCompositeOperation = compositeOperation;
// return the base64-encoded data url string
return dataURItoBlob(imageData);
};
return new Promise((resolve, reject) => {
if (!file.type.match(/image.*/)) {
reject(new Error('VImageInput# Problem resizing image: file must be an image.'));
}
fr.onload = (readerEvent) => {
img.onload = () => resolve(resize());
img.src = readerEvent.target.result;
};
fr.readAsDataURL(file);
});
},
That is a Vue JS instance method that can be used like this:
// this would be the user-uploaded file from the input element
const image = file;
const settings = {
file: image,
maxSize: 192, // to make 192x192 image
backgroundColor: '#FFF',
};
// this will output a base64 string you can dump into your database
const resizedImage = await this.resizeImage(settings);
My solution here is a combination of about 74 different StackOverflow answers related to resizing images client-side, and the final boss was to handle transparent PNG files.
My answer would not be possible without Laereom's answer here.