10 Replies Latest reply: Sep 12, 2012 12:44 PM by xTLS RSS

    Get average brightness of a JPG movieclip?

    xTLS Community Member

      Hi, I was working on a project a few months ago, which I had to put on hold but am finally getting back to. One major feature I need that I wasn't able to figure out before was how to measure the average brightness of an image file loaded as a movieclip. I remember spending hours going through tutorials but I wasn't able to get it working. Now I don't even remember what or where I read before and I'm not keen on rereading all of it and still not knowing what to do.

       

      I just want the simplest possible way to get an average brightness level of an image, I don't care which way the brightness is measured as it is only important relative to other images which will be measured the same way. Any help would be greatly appreciated, thank you.

        • 1. Re: Get average brightness of a JPG movieclip?
          kglad CommunityMVP

          use the bitmapdata class and loop through its pixels.  you probably only need to check 1/4 or 1/9 the pixels to get an average brightness.

          • 2. Re: Get average brightness of a JPG movieclip?
            xTLS Community Member

            Ah yeah, that's what I remember messing with before. Well, I'll try it again, but if you've got any more specific advice that'd be great, otherwise I'll just come back if I need more help. Thanks!

            • 3. Re: Get average brightness of a JPG movieclip?
              Lee Burrows Community Member

              hi

               

              you could also use the histogram() method of BitmapData to get the 'amount' of colour in the image:

               

              var v:Vector.<Vector.<Number>> = myBitmapDataObject.histogram(new Rectangle(...));

               

              this returns a Vector containing 4 Vectors (one for R,G,B and A) which contain 256 items - so it may be quicker to sum and average 3x256 values rather than bitmapWidth x bitmapHeight values (especially as getPixel is relatively slow)

              • 4. Re: Get average brightness of a JPG movieclip?
                xTLS Community Member

                Thanks Lee, that sounds like a good approach, but I don't know how to use vectors so I don't know how to implement it. Could you explain?

                • 5. Re: Get average brightness of a JPG movieclip?
                  Lee Burrows Community Member

                  hi

                   

                  this should do the trick (assuming you have a BitmapData object called "bmd"):

                   

                   

                  var v:Vector.<Vector.<Number>> = bmd.histogram(new Rectangle());
                  var r:Number = 0;
                  var g:Number = 0;
                  var b:Number = 0;
                  for (var i:uint=0;i<256;i++)
                  {
                       r += i*v[0][i]/255;
                       g += i*v[1][i]/255;
                       b += i*v[2][i]/255;
                  }
                  var totalPixels:uint = bmd.rect.width*bmd.rect.height;
                  r /= totalPixels;
                  g /= totalPixels;
                  b /= totalPixels;
                  var brightness:Number = (r+g+b)/3;
                  

                   

                  You should now have a value between 0 and 1 for the image brightness (this is off the top of my head so there may be a bug in there somewhere...)

                   

                  For general info on using Vectors, see: http://www.mikechambers.com/blog/2008/08/19/using-vectors-in-actionscript-3-and-flash-play er-10/

                  • 6. Re: Get average brightness of a JPG movieclip?
                    xTLS Community Member

                    Thanks Lee, I tried it but the R, G, and B values always return 0. Any thoughts?

                     

                    EDIT: By removing "new Rectangle()" from the function call I think I got it partly working, but return values range from .75 to 1.

                     

                    For PNGs with transparency it reads fully transparent pixels as white; guess I can't do anything about that.

                    • 7. Re: Get average brightness of a JPG movieclip?
                      Lee Burrows Community Member

                      hi

                       

                      yes - my bad; new Rectangle() should be null (or empty)

                       

                      make sure your bitmapData object is not transparent (ie: third param of constructor is false)

                       

                      for transparent bm's, this seems to work (but havent tested thoroughly)

                       

                      var v:Vector.<Vector.<Number>> = bmd.histogram(null);

                      var r:Number = 0;

                      var g:Number = 0;

                      var b:Number = 0;

                      var a:Number = 0;

                      for (var i:uint=0;i<256;i++)

                      {

                           r += i*v[0][i]/255;

                           g += i*v[1][i]/255;

                           b += i*v[2][i]/255;

                           a += i*v[3][i]/255;

                      }

                      var totalPixels:uint = bmd.rect.width*bmd.rect.height;

                      r /= totalPixels;

                      g /= totalPixels;

                      b /= totalPixels;

                      a /= totalPixels;

                      var brightness:Number = a*(r+g+b)/3;

                      • 8. Re: Get average brightness of a JPG movieclip?
                        FeZEC CommunityMVP

                        There is one more trick, instead of all teh calculations. Though i like the idea of the histogram.

                         

                        Shrink the jpg to 1x1 pixel width.

                        And check what the color is.  that will give you an average color.

                         

                        Then you can get the brightness of that rgb by returning the perceived LUMA

                         

                             var luma:int =  red * red * .241 +   green * green * .691 +   blue * blue  * .068
                        • 9. Re: Get average brightness of a JPG movieclip?
                          xTLS Community Member

                          Lee, is the new variation you game me supposed to ignore alpha? It gives me a slightly different value but it's still reading fully transparent pixels as pure white. It doesn't matter if I set the transparency in the BMD constructor to false or true.

                           

                          Lazec, that's an interesting idea, I'll try it out. Do you know how reliable it is? I need a completely reliable method for what I'm doing.

                           

                          EDIT: I just realized I was doing var bmd:BitmapData = new BitmapData(testImage.width,testImage.height,true) but I should have been doing var bmd:BitmapData = new BitmapData(testImage.width/4,testImage.height/4,true). I don't understand why it needs to be that way yet, but that fixes the values only ranging from .75 to 1. It doesn't help with the transparent pixels reading as pure white but maybe it will be less of an issue.

                           

                          EDIT2: Yeah, after fixing the problem with the dimensions, Lee's method is definitely accurate enough for my purposes, even with the transparency problem. Awesome, thanks again Lee.

                          • 10. Re: Get average brightness of a JPG movieclip?
                            xTLS Community Member

                            Coming back to this a year and a half later, I've had to expand the number of images that are being checked, and now the inaccuracy from reading transparent pixels as white is too severe. Anyone know a better way to do this?

                             

                            EDIT:

                            How many times did I think I got this right before I actually did? Anyway, HERE IS THE REAL SOLUTION. Less complicated than what I was trying before.

                             

                            protected static function getAverageColor(image:MovieClip):Number {

                                                          var bmp:BitmapData = new BitmapData(image.width,image.height, true, 0x00000000);

                                                          //bmp.draw(image);

                                                          bmp.draw(image.getChildAt(0));

                                                          var v:Vector.<Vector.<Number >  >  = bmp.histogram();

                                                          var r:Number = 0;

                                                          var g:Number = 0;

                                                          var b:Number = 0;

                                                          var a:Number = 0;

                             

                                                          for (var i:int=0; i<256; i++) {

                                                                    r +=  i * v[0][i] / 255;

                                                                    g +=  i * v[1][i] / 255;

                                                                    b +=  i * v[2][i] / 255;

                                                                    a += i*v[3][i]/255;

                                                          }

                             

                                                          var brightness:Number = (r+g+b)/(3*a);

                                                          bmp.dispose();

                                                          trace("brightness: " + brightness);

                                                          return brightness;

                                                }

                             

                            Returns a value between 0 and 1, with .5 being halfway between pure white and pure black.

                             

                            Message was edited by: xTLS