Posted by: pixelero | June 19, 2008

Flash 10: new method BitmapData.histogram();

this demo requires Flash 10 Beta installed:

Extract from as3 language reference:

histogram() method

flash10 function histogram(hRect:Rectangle = null):Vector

Language Version : ActionScript 3.0
Player Version : Flash Player 10

Computes a 256 bin histogram of a BitmapData object.
The functions returns a vector of 4 number vectors.
The 4 number vectors represent the red, green, blue
and alpha components respectively. Each number vector
contains 256 values which represent the population count
of a indivual component value, from 0 to 255.

Parameters
hRect:Rectangle (default = null) — The area of the BitmapData
object that should be used.

Returns Vector

some code snippet from my demo:

function updateHistograms(bmpData:BitmapData,
sprites:Vector.<Sprite>):void {

// histogram is a Vector in two dimensions
// notice the interesting type Vector.<Vector.<Number>>

var hst:Vector.<Vector.<Number>> = bmpData.histogram();

var height:int=128; // height for diagrams
var maxValue:Number;
var value:Number;
var i:int;
var clr:int = 16; // value for bitwise shift left, start with red
// channel = 0:red, 1:green, 2:blue

for (var channel:int = 0; channel!=3; channel++) {

// find the max value on the histogram,
// i goes from 1 to 254,
// I discarded the 0 and 0xFF values to get a better balanced chart

maxValue =0.0;
for (i=1; i!=255; i++) {
value = hst[channel][i];
maxValue = value>maxValue ? value : maxValue;
}

with (sprites[channel].graphics) {
// empty and white background
clear();
beginFill(0xFFFFFF,1.0);
drawRect(0,0,255,height);
// draw a vertical line for each value with a corresponding color

i=0;
for each(value in hst[channel]) {
lineStyle(1.0,i<<clr) ;
moveTo(i,height);
lineTo(i++,Math.max(0.0,height-value*height/maxValue) );
}

}
clr -= 8;
}
}

In the demo I used Grant Skinner’s ColorMatrix for manipulating the image.

… two other new methods for BitmapData are getVector() and setVector() working just like older getPixels and setPixels-methods except with a Vector of uints, length = width x height:
like for instance copying pixels from 0,0 – 49,49 to 100,100 – 149,149:

var bmpVct:Vector.<uint> = bmpData.getVector(new Rectangle(0,0,50,50));
bmpData.setVector(new Rectangle(100,100,50,50),bmpVct);

And an example of experimental image manipulation of sorting by the pixel value Sorted pixels

Advertisements

Responses

  1. hi,

    nice tutorial. just a question – how can i get the most dominant color (rgb value) in an image?

    thanks.

  2. hi,

    well nicely challenging question, two solutions comes to my mind:

    1) How to keep it simple, just scale the image to size of one pixel and read that value. ok, might give wrong result in cases such as black and white line art …
    as code something like:

    var bmp2:BitmapData = new BitmapData(1,1,false,0x00);

    bmp2.draw(bmpData,new Matrix(1/bmp.width,0,0,1/bmp.height) );

    return bmp2.getPixel(0,0);

    2) take some samples from the bitmap, and count, with something like bucketsort, the values with most occurances, simplified by taking only some tree or four most significant bytes from each channel:

    something like:

    function sampleColor(bmpData:BitmapData):uint {
    var buckets:Object = {};
    var pxl:uint;

    for (var y:int =0; y<bmpData.height; y +=2 ) {
    for (var x:int =0; x<bmpData.width; x +=2) {
    pxl = bmpData.getPixel(x,y) & 0xE0E0E0;
    buckets[pxl]= (buckets[pxl] == null) ? 1 : buckets[pxl]+1 ;
    }
    }

    var maxsample:uint =0;
    var maxvalue:uint =0;
    for ( var s in buckets) {
    if (buckets[s]>maxvalue) {
    maxsample=s;
    maxvalue=buckets[s];
    }
    }

    return maxsample;
    }

    Funnily these two approaches return in some cases quite different results ?
    … never had done this before so I did do some experimenting. Above 1×1 pixel sample, below sorted sample.

    Hope this will help …

  3. […] Read more […]

  4. was it just me or is BitmapData.histogram a lot slower then two for loops with BitmapData.getPixelat(i,j);

    I know there is still a lot of work left in flash player 10 so I hope this is just something that is gonna be fixed down the road.

  5. @Josh Chernoff:
    I wouldn’t worry about that, I did some testing on a 375×500 pixels bitmapdata
    and running .histogram() for one hundred times took ~200 ms,
    while a getPixel(i,j)-loop reading the rgb-channels took ~120 ms running once:

    for (j=0; j!=bmpData.height; j++) {
    for (i=0; i!=bmpData.width; i++) {
    blueArray[(pxl = bmpData.getPixel32(i,j) ) & 0xFF]++;
    greenArray[(pxl >>=8 ) & 0xFF]++;
    redArray[(pxl >>=8 ) & 0xFF]++;
    }
    }

  6. this looks awesome. take a look on another flash creation: http://www.onemotion.com/flash/spider/

  7. […] pixelero – The new BitmapData histogram method […]

  8. […] discovered nice blogposts about Flash 10. Some could be inspiration for Krita. I like this version of histogram and I like articles about various blurring effects and there is nice one about linear […]

  9. I was looking for a way to include a flash histogram for my photos on my website and this is just the way I would want, and by the way, its great. Is there a more detailed tutorial to do this? like for begginers in AS

  10. Hi Petri,
    Thank you for the excellent tutorial. Is there a way to get the grayscale levels similar to how Photoshop gives you (Photoshop > Image > Adjustments > Levels)?

    • You mean like making a greyscale copy of source image and reading histogram from that ?
      Something like (sorry written by heart, hope no errors) :

      // source: bitmapdata in RGB
      var cp:BitmapData = source.clone();
      cp.applyFilter(cp, cp.rect, new Point(),
      new ColorMatrixFilter([
      0.3, 0.6, 0.1, 0,0,
      0.3, 0.6, 0.1, 0,0,
      0.3, 0.6, 0.1, 0,0,
      0, 0, 0, 1,0
      ]));

      • Yeah. In the Adjustment Levels dialog the Channel dropdown it has three channels, Red, Green and Blue and then a forth called RGB. I’m guessing it would be gray scale right? Or is it something else?

      • Ok I didn’t think that through. Yes, thank you. 🙂


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: