JS - How to turn Image object into grayscale and display it

19.1k Views Asked by At

Basically, when a button is clicked, it'll tell the mobile device to go to the camera. Once the camera takes a picture, it'll give me the image data (is it called the data URL?). This is my code to handle it:

var imagesrc = "data:image/jpeg;base64," + imageData;

var myimage = new Image(500, 500);
myimage.src = imagesrc;            <---- to populate the object with the colored image
myimage.src = grayscale(myimage);  <---- here I set it to the grayscale image

I want to call a method called grayscale() and make it return the image that's been turned into grayscale. I tried this:

function grayscale(image){
    var canvasContext = canvas.getContext('2d');
    var imgW = image.width;
    var imgH = image.height;
    canvas.width = imgW;
    canvas.height = imgH;

    canvasContext.drawImage(image, 0, 0);

    var imgPixels = canvasContext.getImageData(0, 0, imgW, imgH);


    for(>var y = 0; y < imgPixels.height; y++){
        for(>var x = 0; x < imgPixels.width; x++){
          var i = (y * 4) * imgPixels.width + x * 4;
          var avg = (imgPixels.data[i] + imgPixels.data[i + 1] + imgPixels.data[i + 2]) / 3;
          imgPixels.data[i] = avg;
          imgPixels.data[i + 1] = avg;
          imgPixels.data[i + 2] = avg;
        }
    }

    canvasContext.putImageData(imgPixels, 0, 0, 0, 0, imgPixels.width, imgPixels.height);

    dataurl = canvas.toDataURL();
    var newimg = "data:image/jpeg;base64," + dataurl;
    return newimg;
}

But for some reason it doesn't work. It just doesn't display the grayscale image. I got the for loop code online and tweaked it.

3

There are 3 best solutions below

0
Jonas M. Schlatter On BEST ANSWER

There are several reasons this does not work. It would be a good thing for you to start checking console output to track bugs. Firefox "F12" for example, would tell you that for(>var ...) is a problem. ;)

Did you declare canvas somewhere, outside the code you shared with us? Is dataurl declared? The prefixing of toDataUrl is not needed...

Here's a basic html file I typed around your for-loop, that does turn "test.png" to grey. Maybe you want to save it somewhere, put a png into the same folder, and start editing stuff step by step, instead of copying code. If you feel up for a challenge try making it pass http://jslint.com/! (You'd have to replace the for loop with while loops, I guess). :)

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>Canvas/ImgData Test</title>
</head>

<body>
    <canvas id="output"></canvas>
    <script>
        var cnv = document.getElementById('output');
        var cnx = cnv.getContext('2d');

        function grey(input) {
            cnx.drawImage(myimage, 0 , 0);
            var width = input.width;
            var height = input.height;
            var imgPixels = cnx.getImageData(0, 0, width, height);

            for(var y = 0; y < height; y++){
                for(var x = 0; x < width; x++){
                    var i = (y * 4) * width + x * 4;
                    var avg = (imgPixels.data[i] + imgPixels.data[i + 1] + imgPixels.data[i + 2]) / 3;
                    imgPixels.data[i] = avg;
                    imgPixels.data[i + 1] = avg;
                    imgPixels.data[i + 2] = avg;
                }
            }

            cnx.putImageData(imgPixels, 0, 0, 0, 0, imgPixels.width, imgPixels.height);
        }

        var myimage = new Image();
        myimage.onload = function() {
            grey(myimage);
        }
        myimage.src = "test.png";
    </script>
</body>
</html>
0
ATUL ANAND On

i know you are looking for converting dataURI to grayscale but, if you want to convert the video feedback itself to grayscale or convert any image to grayscale you can use this code.

.gray {
  filter: grayscale();
}
 <!--hey use this style to show in gray scale. can even use to convert image to grayscale-->
 <video id="camera-stream" class="gray" ></video>

0
Antony Penn On

You shouldn't take the average of the 3 colour components, as they vary greatly in brightness (100% green is a lot brighter than 100% blue). The TV systems (PAL and NTSC) define the brightness of the greyscale picture as 29.9% Red + 58.7% Green + 11.4% Blue.