views:

41

answers:

2

I've checked the document:

http://help.adobe.com/en_US/AS3LCR/Flash_10.0/flash/media/Camera.html

But still don't find info on how to control the visual affect(like lightness, saturation and so on) of my pc camera.

Is that kind of job possible with actionscript?

+1  A: 

You can't alter the actual Camera data (there is a difference between that and what I am describing further), but it's possible to do what you want easily, after attaching the Camera object to a Video object and using the variety of transformation filters and routines from other native ActionScript classes like ColorTransform, DisplayObject.transform.colorTransform and DisplayObject.filters, to alter what is displayed on the screen/memory, which, I believe, is probably what you want anyway.

To give you a real world usage example, you can adjust saturation of the camera data being displayed in your video with the following code:

/// Desaturate displayed image completely
video.filters = [ new ColorMatrixFilter(saturation_filter_matrix(0)) ];

where I have defined the methods as:

static inline var RWGT = 0.3086;
static inline var GWGT = 0.6094;
static inline var BWGT = 0.0820;

static public function brightness_filter_matrix(b: Float)
{
    return [    b, 0, 0, 0, 0,
                0, b, 0, 0, 0,
                0, 0, b, 0, 0,
                0, 0, 0, 1, 0 ];
}

static public function saturation_filter_matrix(s: Float)
{
    var b = (1 - s) * RWGT;
    var a = b + s;
    var d = (1 - s) * GWGT;
    var e = d + s;
    var g = (1 - s) * BWGT;
    var i = g + s;

    return [    a, d, g, 0, 0,
                b, e, g, 0, 0,
                b, d, i, 0, 0,
                0, 0, 0, 1, 0 ];
}

static public function contrast_filter_matrix(v: Float)
{
    v += 1;

    var r = v;
    var g = v;
    var b = v;

    return [    r, 0, 0, 0, 128 * (1 - r),
                0, g, 0, 0, 128 * (1 - g),
                0, 0, b, 0, 128 * (1 - b),
                0, 0, 0, 1, 0 ];
}

I also think that transform.colorTransform may be more efficient with doing the same job, somehow I have observed that filters tend to tax Adobe Flash Player to moderate to high degree, so be advised.

The implications of the fact that you cannot change actual camera input, are that when you publish your camera across network (to Flash Media Server for instance), no matter what effects you use to display the data in your own video object, the party playing the stream will see the original unaltered data. A "workaround" would be to announce to the receiving party the exact parameters you want them to apply to their video object that is playing the stream. Assuming they apply these parameters in the same way you do for your displayed camera image, they will see your camera image the way you see it.

Note: The code is written in haXe, but the two languages are very similar. The changes you need to be aware of are (blatant advertisement for haXe follows :-) Float in haXe is Number in ActionScript 3 for example, and haXe uses type inference which makes it possible to omit variable types at will, letting haXe figure it out itself (when you add two int's what do you get? On Flash platform, you always get an int as well.) Also AS3 does not have the concept of inlining (yet?) and so you must simply remove inline syntax from the code, that's all.

amn
just adding to this, Grant Skinner wrote a utility class to handle this easier: http://www.gskinner.com/blog/archives/2007/12/colormatrix_upd.html
George Profenza
Is there any official announcement that it's impossible to alter the actual Camera data? As that is the most performant way to do the job...
Adobe ActionScript 3 LiveDocs is the de-facto reference for the API you use with Flash Player. If there is not listed any method of Camera class that lets you manipulate the incoming data from the camera driver, then there is no such method and no API-endorsed way to do this. I don't think there are hidden methods and/or undocumented features here either. Bottomline: you just can't do that in Flash Player. However, and to support the other answers, you could alter the data at another node such as server streaming it. I would however do it in a distributed-computing way instead.
amn
Also, how do you know it's the most performant way to do the job, and what criteria you use when judging this performance? If it's speed, you again can't be sure, as everything is done by Flash Player for you anyway, and you can only assume how it does things. As one smart guy here said, to measure is to know. Also keep in mind that your contrast/brightness/hue/saturation preferences may not suit the party looking at the stream at the other end, assuming you are publishing the data of course, so maybe you can give them some sliders so that they can adjust these themselves.
amn
A: 

In response to your comment regarding accessing the camera data directly, the only area I can think of where this would be an issue is if you are recording to a FMS (flash media server, Red5, wowza etc), in which case the data comes directly out of the camera and into the netstream (netStream.attachCamera(cam)). For this there is no direct workaround, you could maybe store the brightness and contrast settings (from a filter effect) as flv metadata when you publish/stream the video, but then the person on the other end would have to decode this metadata (i.e. playback using a Flash component or something that can decode AMF data), for this see the setDataFrame method of NetConnection

For everything else you can use the methods suggested above, take the cam, shove it into a Video instance with video.attachCamera and then use video.filters = [myFilter] to apply the effect you desire. If you want to get down and dirty with the pixels you could use the draw property of a BitmapData object to draw the camera image from the video onto a bitmap for manipulation, you must however do this on an enterFrame or Timer to keep the bitmapData in sync.

var video:Video = new Video(w,h);
video.attachCamera(Camera.getCamera());
var bmd:BitmapData = new BitmapData(w,h);
bmd.draw(video);

Hope this is helps