Help Helper
Help Helper

Reputation: 15

Make image Black and White Javascript

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

Answers (3)

GameAlchemist
GameAlchemist

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

enter image description here

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

Upvotes: 2

markE
markE

Reputation: 105015

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

Upvotes: 1

Super Hornet
Super Hornet

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

Related Questions