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


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,0×00);

    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


Leave a response

Your response:

Categories