Drawing iOS UIViews to AS3 bitmapData via Adobe AIR native extensions

A major draw back to displaying native iOS UIView objects on top of your Adobe AIR applications is that they… well… are on top. Here is a quick code snippet for rendering native iOS view objects to ActionScript bitmapData objects via the recently released native extensions support.

This allows you to add them to the Flash display list (at the loss of all their native functionality). With native extensions we can update the bitmapData directly in memory which results in very fast updates. The possibilities are endless.

FREObject drawToBitmap(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]) {
    // grab the AS3 bitmapData object for writing to
    FREBitmapData bmd;
    FREAcquireBitmapData(argv[0], &bmd);

    // Draw the UIView to a UIImage object. myView is a UIView object
    // that exists somewhere in our code. It can be any view.
    [map.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

    // Now we'll pull the raw pixels values out of the image data
    CGImageRef imageRef = [image CGImage];
    NSUInteger width = CGImageGetWidth(imageRef);
    NSUInteger height = CGImageGetHeight(imageRef);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

    // Pixel color values will be written here
    unsigned char *rawData = malloc(height * width * 4);
    NSUInteger bytesPerPixel = 4;
    NSUInteger bytesPerRow = bytesPerPixel * width;
    NSUInteger bitsPerComponent = 8;
    CGContextRef context = CGBitmapContextCreate(rawData, width, height,
    bitsPerComponent, bytesPerRow, colorSpace,
    kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);

    // Pixels are now in rawData in the format RGBA8888
    // We'll now loop over each pixel write them into the AS3 bitmapData memory
    int x, y;

    // There may be extra pixels in each row due to the value of
    // bmd.lineStride32, we'll skip over those as needed
    int offset = bmd.lineStride32 - bmd.width;
    int offset2 = bytesPerRow - bmd.width*4;
    int byteIndex = 0;
    uint32_t *bmdPixels = bmd.bits32;

    // NOTE: In this example we are assuming that our AS3 bitmapData and our
    // native UIView are the same dimensions to keep things simple.
    for(y=0; y<bmd.height; y++) {
        for(x=0; x<bmd.width; x++, bmdPixels ++, byteIndex += 4) {
            // Values are currently in RGBA8888, so each colour
            // value is currently a separate number
            int red = (rawData[byteIndex]);
            int green = (rawData[byteIndex + 1]);
            int blue = (rawData[byteIndex + 2]);
            int alpha = (rawData[byteIndex + 3]);

            // Combine values into ARGB32
            * bmdPixels = (alpha << 24) | (red << 16) | (green << 8) | blue;

        bmdPixels += offset;
        byteIndex += offset2;

    // free the the memory we allocated
    // Tell Flash which region of the bitmapData changes (all of it here)
    FREInvalidateBitmapDataRect(argv[0], 0, 0, bmd.width, bmd.height);
    // Release our control over the bitmapData


Flash, ActionScript-3, development, code, performance, programming, How to


Comment functionality has been disabled. Contact me on Twitter.

carl.gloria said:

You rock! this is exactly what I needed. I did figure out how to add a UIview to the sharedApplication and was assuming it was some sort of layering issue. I thought the air player would be living within some UIview and I would just have to manage the layering somehow. Wish I new/understood a little more of exactly what airtoios does. I will be integrating this UIview to bitmapdata approach today! And yes, if performance is acceptable, the uses are endless! Thanks again!


Browse All >