1

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.

Lee Taylor
  • 7,761
  • 16
  • 33
  • 49
Liron Harel
  • 10,819
  • 26
  • 118
  • 217

4 Answers4

2

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>
markE
  • 102,905
  • 11
  • 164
  • 176
  • when I use canvas.width - imageObj.width (same for the height), it doesn't clear the white pixels anymore, image stays the same, any idea why (wen I remove those lines it removes them again) – Liron Harel Mar 08 '13 at 06:56
  • I posted full code that works for me. **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 this will not work: http://otherDomain.com/picture.jpg – markE Mar 08 '13 at 16:25
1

Maybe create a canvas and populate the pixel values with the corrosponding ones from the image. If a pixel is white rgb(255,255,255) set the alpha to 1. Not sure if this is possible, just an idea.

Tutorial for pixel manipulation

Imperative
  • 3,138
  • 2
  • 25
  • 40
0

There is a solution to add alpha channel to existing JPEG image and to render it in the browser: https://jim.studt.net/jpeg-alpha/.

Martin Ždila
  • 2,998
  • 3
  • 31
  • 35
-2

as far as is know JPEGs do not have the option of transparency. You need to use PNG or you have to fill in the virtual transparent content from underneath

wegus
  • 282
  • 1
  • 9