Reputation: 15
I am making an app which will convert users uploaded image to black and white and then return a base64
string of image
Like:
<input type="file" onchange="handleFiles(this.file)" />
function handleFiles(f) { var o=[];
for(var i =0;i<f.length;i++)
{
var reader = new FileReader();
reader.onload = (function(theFile) {
return function(e) {
gCtx.clearRect(0, 0, gCanvas.width, gCanvas.height);
//i want e.target.result to have base64 of black and white image not colorful image.
//My processing with e.target.result image
};
})(f[i]);
reader.readAsDataURL(f[i]);
}
}
e.target.result
contains colordful image base 64 string
i want e.target.result
to have black and white base 64 string
Upvotes: 1
Views: 5154
Reputation: 19294
You can have your result with like 4 lines of codes and little efforts !
Just use the new blending modes of the canvas, that will do the math for you and will be faster than handling the r,g,b bytes by yourself.
Another bonus is you won't have any CORS security issue with your images.
Here's a fiddle, it would work quite the same with a base64 src :
http://jsfiddle.net/gamealchemist/7woa7oyp/
The idea is to fill the canvas in white, then using the luminosity
mode, the image will be drawn keeping current saturation(0) and hue(not relevant since saturation of white is 0)
==>> you end up with only the luminosity of the image, with no saturation == B&W version of the image.
ctx.save();
ctx.fillStyle = '#FFF';
ctx.fillRect(0, 0, cv.width, cv.height);
ctx.globalCompositeOperation = 'luminosity';
ctx.drawImage(coloredImage, 0, 0);
ctx.restore();
(blending modes specification : http://dev.w3.org/fxtf/compositing-1/ )
Upvotes: 2
Reputation: 105015
Here's one way using context.getImageData
to get the color pixel array and convert each pixel to grayscale by making the red, green & blue values of each pixel equal the average value of that pixel.
// make the r,g,b components of this pixel == the average of r,g,b
var average=(red+green+blue)/3;
red=average;
green=average;
blue=average;
Here's example code and a Demo. In this example canvas.toDataURL()
fetches the base64 encoded grayscale image data url you require.
// load an image file from the user
function handleFiles(files) {
for (var i = 0; i < files.length; i++) {
var file = files[i];
var imageType = /image.*/;
if (!file.type.match(imageType)) {
continue;
}
var img = document.createElement("img");
img.classList.add("obj");
img.file = file;
var reader=new FileReader();
reader.onload=(function(aImg){
return function(e) {
aImg.onload=function(){
// draw color image on new canvas
var canvas=document.createElement("canvas");
var ctx=canvas.getContext("2d");
canvas.width=img.width;
canvas.height=aImg.height;
ctx.drawImage(aImg,0,0);
// convert color to grayscale
var imageData=ctx.getImageData(0,0,canvas.width,canvas.height);
var data=imageData.data;
for(var i=0;i<data.length;i+=4){
// make the r,g,b components of this pixel == the average of r,g,b
data[i+0]=data[i+1]=data[i+2]=(data[i]+data[i+1]+data[i+2])/3;
}
ctx.putImageData(imageData,0,0);
// create grayscale img from canvas
var grayImg=new Image();
grayImg.onload=function(){
document.body.appendChild(aImg);
document.body.appendChild(grayImg);
}
grayImg.src=canvas.toDataURL();
}
// e.target.result is a dataURL for the image
aImg.src = e.target.result;
};
})(img);
reader.readAsDataURL(file);
} // end for
} // end handleFiles
//
$("#fileElem").change(function(e){
handleFiles(this.files);
});
//
$("#startInput").click(function(e){
document.getElementById("fileElem").click();
});
body{ background-color: ivory; padding:10px; }
img{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<button id="startInput">Click to select an image file</button><br>
<input type="file" id="fileElem" multiple accept="image/*" style="display:none">
Upvotes: 1
Reputation: 2907
If you are going to handle it in client side you should load your image into html5 canvas element and manipulate it.
There are some libraries do it like this Or take a look at this tutorial
Upvotes: 0