1

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

3
  • If this grayscale feature is important to your application, you should probably do it on the server. Don't trust the data coming from the client; users may modify the JavaScript or forge the request and upload their image in color. Commented Dec 25, 2014 at 5:15
  • @JonathanNewmuis This app is for use of our tem, means we are owners and users! Commented Dec 25, 2014 at 5:17
  • @JonathanNewmuis Its strict order to use nothing Server side! Commented Dec 25, 2014 at 5:17

3 Answers 3

2

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(); 

enter image description here

(blending modes specification : http://dev.w3.org/fxtf/compositing-1/ )

Sign up to request clarification or add additional context in comments.

3 Comments

Blend compositing will certainly be the future of image filtering. But as of this post (Dec2014) most of the common browsers have not implemented blend compositing.
Wrong : only IE -useless anyway- does not support it : caniuse.com/#feat=canvas-blending
Wow--I stand corrected. I see most browsers have added blending since I last checked can-I-use. Thanks for the update! Sadly, I still can't use globalCompositeOperation blending in my company since IE has a significant market share. I see MS is "considering it" for future inclusion in IE. Maybe I'll recode some of our apps to use it with a fallback for IE--if I find the time!
1

enter image description here

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">

1 Comment

It is grayscale, not black-and-white :-(
0

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

1 Comment

You need to follow its instructions

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.