Hi,
I’ve tried actionscript code to create histograms for any image. And it works . My intention was to read the histogram data and perform automatic adjustment on the image levels. Here’s how i wanted to implement
- Generate histogram data
- Read/ Analyze the histogram output of the image
- Determine where the majority of the pixels lay in the full brightness range to set new black and white points of a level adjustment
I tried doing something like this
googled for anttikupila pixel bender
Here’s the working code
package {
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.BitmapDataChannel;
import flash.geom.Point;
import flash.geom.Rectangle;
[SWF(width=800, height=600, backgroundColor=0xFFFFFF)]
/**
* Demonstrates how BitmapData's histogram() method can be used to access brightness level data for each all
* channels of each pixel, and how this may be visually displayed.
*/
public class HistogramTest extends AbstractImageLoader {
/**
* Constructor. Passes path of image to load to super class.
*/
public function HistogramTest() {
super("../../assets/test.jpg");
}
/**
* Run after the image loads in super class. This gets the histrogram data and draws this in a colored
* column chart in a new image that is displayed to the right of the loaded image.
*/
override protected function runPostImageLoad():void {
var bitmapData:BitmapData = _loadedBitmap.bitmapData;
addChild(_loadedBitmap);
var histogram:Vector.<Vector.<Number>> = bitmapData.histogram();
// retrieve the maximum number of pixels in a single brightness level;
// this is used to set the top of the column chart
var maxPixels:uint = getMaxPixels(histogram);
// new image in which the histrogram data will be displayed
var histogramData:BitmapData = new BitmapData(256, 256, false, 0xFF000000);
// draws each individual color channel's histrogram data into the new image
drawChannelData(maxPixels, histogramData, histogram[0], BitmapDataChannel.RED);
drawChannelData(maxPixels, histogramData, histogram[1], BitmapDataChannel.GREEN);
drawChannelData(maxPixels, histogramData, histogram[2], BitmapDataChannel.BLUE);
// adds the bitmap data to a bitmap and the stage
var histogramBitmap:Bitmap = new Bitmap(histogramData);
histogramBitmap.x = bitmapData.width + (bitmapData.width-256)/2;
histogramBitmap.y = (bitmapData.height-256)/2;
addChild(histogramBitmap);
}
/**
* Returns the maximum number of pixels in a single brightness level in all channels.
*
* @param histogram The histrogram data retrieved from an image.
*
* @return The maximum number of pixels in a single brightness level in all channels.
*/
private function getMaxPixels(histogram:Vector.<Vector.<Number>>):uint {
var maxPixels:uint = 0;
var x:uint;
var channel:Vector.<Number>;
// run through all three channels
for (var i:uint = 0; i < 3; i++) {
channel = histogram*;
// run through all 256 brightness levels
for (x = 0; x < 256; x++) {
maxPixels = Math.max(channel[x], maxPixels);
}
}
return maxPixels;
}
/**
* Draws a column chart of a channel's histogram data into the specified bitmap.
*
* @param maxPixels The maximum number of pixels that will be displayed on the y axis, defining chart size.
* @param bitmapData The bitmap data in which to draw the channel data column chart.
* @param channelData The histogram data for the channel to draw.
* @param channel The channel of the image in which to draw the column chart.
*/
private function drawChannelData(
maxPixels:uint,
bitmapData:BitmapData,
channelData:Vector.<Number>,
channel:uint
):void {
// new bitmap data of exact same dimensions is used
var channelBitmapData:BitmapData = bitmapData.clone();
var y:Number;
// run through all 256 brightness levels and draw column for each
for (var x:uint = 0; x < 256; x++) {
// scale of the column is dictated by the number of pixels of that brightness in that channel
// and the maxPixels value, which defines the height of the y axis and the chart
y = channelData[x]/maxPixels*256;
// draw a column from the bottom of the image up (256-y)
channelBitmapData.fillRect(new Rectangle(x, 256-y, 1, y), 0xFFFFFFFF);
}
// copy the single channel's data into the final bitmap data
bitmapData.copyChannel(channelBitmapData,channelBitmapData.rect,new Point(),channel,channel);
}
}
}
Thanks :pleased: