Search code examples
jqueryhtml5-canvasalpha-transparencyimage-masking

Masking White areas of JPEG images


I want to mask a total White (R:255,G:255,B:255) areas in a JPEG image, so when viewed in the browser, in the total white areas I will see what underneath (those area will be transparent). I don't mind using JQuery, CSS 3 or Canvas, whatever works to achieve this. Thanks

OK, the code:

<body style="background-color:red;">
  <canvas id="myCanvas" width="228" height="454"></canvas>
    <script>
        var canvas = document.getElementById('myCanvas');
        var context = canvas.getContext('2d');
        var x = 0;
        var y = 0;
        var width = 228;
        var height = 454;
        var imageObj = new Image();

        imageObj.onload = function () 
        {
            context.drawImage(imageObj, x, y, width, height);

            var canvas = document.getElementById('myCanvas');
            var ctx = canvas.getContext('2d');

            var imgData = ctx.getImageData(0, 0, width, height);
            var pixels = imgData.data; // get pixel data

            for (var i = 0; i < pixels.length; i +=4)
            {
                var r = pixels[i ];
                var g = pixels[i + 1]
                var b = pixels[i  + 2];

                if (r === 255 && g === 255 && b === 255) {
                    pixels[i + 3] = 1;
                }   
            }

            ctx.clearRect(0, 0, canvas.width, canvas.height);
            ctx.putImageData(imgData, 0, 0);
        };
        imageObj.src = 'img/test_image.jpg';
    </script>
  </body>

This code seems to do the job, but I get some scattered white dots in the area which is total white.


Solution

  • Your code looks fairly correct, but I would suggest these changes:

    You set the canvas size to 228x454, but if your image is slightly different sized, you may be accidentally scaling the source image when you draw it to the canvas. So, scale the canvas to exactly the image size:

    imageObj.onload=function(){
    canvas.width=imageObj.width;   // be sure canvas is *exactly* image sized to prevent 
    canvas.height=imageObj.height; // accidental scaling which might skew pixel colors
    

    You set the “transparent” pixels to 1 when you should set them to 0 for full transparency:

    pixels[i+3]=0;      // 0 instead of 1 for pure transparency
    

    You are only masking pure white--rgb(255,255,255). It’s possible some of the pixels in your image are “nearly” white, so you might try masking some near-white pixels too.

    var nearWhite=250;  // try experimenting with different “near white” values
    if(r>nearWhite && g>nearWhite && b>nearWhite)
    

    [Edited: To provide complete code]

    Here is the code (works for me on my computer).

    Be sure your image source is on your local domain, otherwise you will run into a security violation and the image will draw, but the white pixels will not be made transparent. So no http://otherDomain.com/picture.jpg!

    <!doctype html>
    <html>
    <head>
    <link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
    <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
    
    <style>
        body{ background-color: ivory; }
        canvas{border:1px solid red;}
    </style>
    
    <script>
    $(function(){
        var canvas=document.getElementById("canvas");
        var ctx=canvas.getContext("2d");
        var imageObj = new Image();
        imageObj.onload = function () {
    
            canvas.width=imageObj.width;
            canvas.height=imageObj.height;
            ctx.drawImage(imageObj, 0,0);
    
            var imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
            var pixels = imgData.data; // get pixel data
            for (var i = 0; i < pixels.length; i +=4)
            {
                var r = pixels[i ];
                var g = pixels[i + 1]
                var b = pixels[i  + 2];
    
                if (r>250 && g>250 && b>250) {
                    pixels[i + 3] = 0;
                    count++;
                }   
            }
            ctx.putImageData(imgData, 0, 0);
        }
        imageObj.src="car.jpg";
    
    }); // end $(function(){});
    </script>
    
    </head>
    
    <body>
        <canvas id="canvas" width=300 height=300></canvas>
    </body>
    </html>