Skip to main content
Inspiring
December 15, 2011
Answered

ANE, iOS and BitmapData

  • December 15, 2011
  • 3 replies
  • 4726 views

Is there any example of passing bitmap data into iOS and returning a modfified copy. I am trying to convert a bitmap into jpeg - similar to this example in Windows http://blog.magicalhobo.com/2011/09/12/air-3-native-extension-imageprocessor/ but it crashed every time. I am pretty sure I am doing something basic wrong but not been an iOS / Objective C programmer I am really just trying magic incantations and I can't find any good examples. Any help appreciated?

   

Sean

 

P.S. Below is my attempt:

 

FREObject encodeJPEG(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[])

{

     FREObject     objectBitmapData = argv[0];

     FREBitmapData bitmapData;

     

     FREAcquireBitmapData(objectBitmapData, &bitmapData);

     

     int width       = bitmapData.width;

     int height      = bitmapData.height;

     int stride      = bitmapData.lineStride32 * 4;

     uint32_t* input = bitmapData.bits32;

     

     FREReleaseBitmapData(objectBitmapData);

     

     

     UIImage *myImage = [UIImage imageWithData:input];

     NSData *jpgData  = UIImageJPEGRepresentation(myImage, 0.9);    

 

     FREObject    objectByteArray = argv[1];

     FREByteArray byteArray;

     

     FREObject length;

     

     FRENewObjectFromUint32(jpgData.length, &length);

     

     FRESetObjectProperty(objectByteArray, (const uint8_t*) "length", length, NULL);

     

     FREAcquireByteArray(objectByteArray, &byteArray);

     

     memcpy(byteArray.bytes, jpgData.bytes, jpgData.length);

     FREReleaseByteArray(objectByteArray);

         

     return NULL;

}

 

This topic has been closed for replies.
Correct answer shanlyticketsolve

Finale version - seems to work ok - encodes ok and I think cleans up after itself ok.

Sean

FREObject encodeJPEG( FREContext ctx, void* funcData, uint32_t argc, FREObject argv[] )

{

    FREObject       objectBitmapData = argv[ 0 ];

    FREBitmapData2  bitmapData;

   

    FREAcquireBitmapData2( objectBitmapData, &bitmapData );

   

    int width       = bitmapData.width;

    int height      = bitmapData.height;

    int stride      = bitmapData.lineStride32 * 4;

    uint32_t* input = bitmapData.bits32;

   

    // make data provider from buffer

    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, bitmapData.bits32, (width * height * 4), NULL);

   

    // set up for CGImage creation

    int                     bitsPerComponent    = 8;

    int                     bitsPerPixel        = 32;

    int                     bytesPerRow         = 4 * width;

    CGColorSpaceRef         colorSpaceRef       = CGColorSpaceCreateDeviceRGB();   

    CGBitmapInfo            bitmapInfo;

    if( bitmapData.hasAlpha )

    {

        if( bitmapData.isPremultiplied )

            bitmapInfo = kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst;

        else

            bitmapInfo = kCGBitmapByteOrder32Little | kCGImageAlphaFirst;           

    }

    else

    {

        bitmapInfo = kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst

    }

   

    CGColorRenderingIntent  renderingIntent     = kCGRenderingIntentDefault;

    CGImageRef              imageRef            = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);

    // make UIImage from CGImage

    UIImage *myImage = [UIImage imageWithCGImage:imageRef];   

    NSData* jpgData  = UIImageJPEGRepresentation( myImage, 0.9 );   

    FREReleaseBitmapData( objectBitmapData );

    FREObject    objectByteArray = argv[ 1 ];              

    FREByteArray byteArray;

    FREObject    length;

   

    FRENewObjectFromUint32( jpgData.length, &length );

    FRESetObjectProperty( objectByteArray, ( const uint8_t* ) "length", length, NULL );

    FREAcquireByteArray( objectByteArray, &byteArray );

   

    memcpy( byteArray.bytes, jpgData.bytes, jpgData.length );

   

    FREReleaseByteArray( objectByteArray );

       

    // release bits

    CGColorSpaceRelease(colorSpaceRef);

    CGImageRelease(imageRef);

    CGDataProviderRelease(provider);   

    return NULL;

}

3 replies

February 11, 2012

Hi Sean,

this is exactly what I've been looking for. Do you have any plans to do a proper release with an ane and perhaps a sample of how to use it?

cheers,

Otto

ps. it would be really sweet if it was possible to supply a width and height argument as well so that you could resize images.

User Unknow
Legend
February 12, 2012

Why you want use ANE ? this convertation may be you can do in AS ? Don't thinkg about that?

Innovatology
Participating Frequently
February 12, 2012

Because doing it C is much, much faster.

Inspiring
December 16, 2011

This kinda works except reds are blues in jpeg and not sure I am releasing everything ok.

Thats tomorrows battle.

Sean

    FREObject encodeJPEG( FREContext ctx, void* funcData, uint32_t argc, FREObject argv[] ) 

    {

     FREObject       objectBitmapData = argv[ 0 ];

     FREBitmapData2  bitmapData;

   

     FREAcquireBitmapData2( objectBitmapData, &bitmapData );

   

     int width       = bitmapData.width;

     int height      = bitmapData.height;

     int stride      = bitmapData.lineStride32 * 4;

     uint32_t* input = bitmapData.bits32;

   

     // make data provider from buffer

     CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, bitmapData.bits32, (width * height * 4), NULL);

   

     // set up for CGImage creation

     int                     bitsPerComponent    = 8;

     int                     bitsPerPixel        = 32;

     int                     bytesPerRow         = 4 * width;

     CGColorSpaceRef         colorSpaceRef       = CGColorSpaceCreateDeviceRGB();

     CGBitmapInfo            bitmapInfo          = kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedFirst;

     CGColorRenderingIntent  renderingIntent     = kCGRenderingIntentDefault;

     CGImageRef              imageRef            = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);

       

     // make UIImage from CGImage

     UIImage *myImage = [UIImage imageWithCGImage:imageRef];   

     NSData* jpgData  = UIImageJPEGRepresentation( myImage, 0.9 );   

     FREReleaseBitmapData( objectBitmapData );

     FREObject    objectByteArray = argv[ 1 ];              

     FREByteArray byteArray;

     FREObject    length;

   

     FRENewObjectFromUint32( jpgData.length, &length );

     FRESetObjectProperty( objectByteArray, ( const uint8_t* ) "length", length, NULL );

     FREAcquireByteArray( objectByteArray, &byteArray );

   

     memcpy( byteArray.bytes, jpgData.bytes, jpgData.length );

   

     FREReleaseByteArray( objectByteArray );

       

     return NULL;

    }

shanlyticketsolveAuthorCorrect answer
Inspiring
December 17, 2011

Finale version - seems to work ok - encodes ok and I think cleans up after itself ok.

Sean

FREObject encodeJPEG( FREContext ctx, void* funcData, uint32_t argc, FREObject argv[] )

{

    FREObject       objectBitmapData = argv[ 0 ];

    FREBitmapData2  bitmapData;

   

    FREAcquireBitmapData2( objectBitmapData, &bitmapData );

   

    int width       = bitmapData.width;

    int height      = bitmapData.height;

    int stride      = bitmapData.lineStride32 * 4;

    uint32_t* input = bitmapData.bits32;

   

    // make data provider from buffer

    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, bitmapData.bits32, (width * height * 4), NULL);

   

    // set up for CGImage creation

    int                     bitsPerComponent    = 8;

    int                     bitsPerPixel        = 32;

    int                     bytesPerRow         = 4 * width;

    CGColorSpaceRef         colorSpaceRef       = CGColorSpaceCreateDeviceRGB();   

    CGBitmapInfo            bitmapInfo;

    if( bitmapData.hasAlpha )

    {

        if( bitmapData.isPremultiplied )

            bitmapInfo = kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst;

        else

            bitmapInfo = kCGBitmapByteOrder32Little | kCGImageAlphaFirst;           

    }

    else

    {

        bitmapInfo = kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst

    }

   

    CGColorRenderingIntent  renderingIntent     = kCGRenderingIntentDefault;

    CGImageRef              imageRef            = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);

    // make UIImage from CGImage

    UIImage *myImage = [UIImage imageWithCGImage:imageRef];   

    NSData* jpgData  = UIImageJPEGRepresentation( myImage, 0.9 );   

    FREReleaseBitmapData( objectBitmapData );

    FREObject    objectByteArray = argv[ 1 ];              

    FREByteArray byteArray;

    FREObject    length;

   

    FRENewObjectFromUint32( jpgData.length, &length );

    FRESetObjectProperty( objectByteArray, ( const uint8_t* ) "length", length, NULL );

    FREAcquireByteArray( objectByteArray, &byteArray );

   

    memcpy( byteArray.bytes, jpgData.bytes, jpgData.length );

   

    FREReleaseByteArray( objectByteArray );

       

    // release bits

    CGColorSpaceRelease(colorSpaceRef);

    CGImageRelease(imageRef);

    CGDataProviderRelease(provider);   

    return NULL;

}

Innovatology
Participating Frequently
December 15, 2011

Not sure, but I don't think you can access input and thus bitmapData.bits32 after you have called FREReleaseBitmapData().