11 Replies Latest reply: Feb 13, 2012 2:05 AM by wedgedkc RSS

    ANE, iOS and BitmapData

    shanlyticketsolve Community Member

      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;

      }

       

        • 1. Re: ANE, iOS and BitmapData
          Innovatology Community Member

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

          • 2. Re: ANE, iOS and BitmapData
            shanlyticketsolve Community Member

            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;

                }

            • 3. Re: ANE, iOS and BitmapData
              shanlyticketsolve Community Member

              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;

              }

              • 4. Re: ANE, iOS and BitmapData
                wedgedkc Community Member

                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.

                • 5. Re: ANE, iOS and BitmapData
                  Anton Azarov Community Member

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

                  • 6. Re: ANE, iOS and BitmapData
                    Innovatology Community Member

                    Because doing it C is much, much faster.

                    • 7. Re: ANE, iOS and BitmapData
                      Anton Azarov Community Member

                      how much ? ) for a few seconds? )))

                      • 8. Re: ANE, iOS and BitmapData
                        Innovatology Community Member

                        That depends on the size of your image and compression parameters. I'd estimate a factor of 10.

                        • 9. Re: ANE, iOS and BitmapData
                          shanlyticketsolve Community Member

                          It is painfully slow in AS - typically 30 seconds and more. This seems to be the consistent experience from others as well.

                           

                          Sean

                          • 10. Re: ANE, iOS and BitmapData
                            shanlyticketsolve Community Member

                            I stopped the work while waiting for Adobe to fix the issue with taking pictures on an iOS device crashing consistently. See below for wrapping AS code and usage example. Should be enough to get you bootstrapped.

                             

                            Sean

                             

                            package com.ticketsolve

                            {

                                      import flash.display.BitmapData;

                                      import flash.events.EventDispatcher;

                                      import flash.events.StatusEvent;

                                      import flash.external.ExtensionContext;

                                      import flash.utils.ByteArray;

                             

                                      public class Extensions extends EventDispatcher

                                      {

                             

                             

                                                //---------------------------------------------------------------------

                                                //

                                                // Constants

                                                //

                                                //---------------------------------------------------------------------

                             

                                                private static const EXTENSION_ID : String = "com.ticketsolve.extensions";

                                                  

                                                //---------------------------------------------------------------------

                                                //

                                                // Private Properties.

                                                //

                                                //---------------------------------------------------------------------

                             

                                                private var context : ExtensionContext;

                                                  

                                                //---------------------------------------------------------------------

                                                //

                                                // Public Methods.

                                                //

                                                //---------------------------------------------------------------------

                                                

                                                public function Extensions()

                                                {

                                                          context = ExtensionContext.createExtensionContext( EXTENSION_ID, null );

                                                }

                             

                                                public function encodeJPEG(image:BitmapData):ByteArray

                                                {

                                                          var bytes:ByteArray = new ByteArray();

                                                          context.call('encodeJPEG', image, bytes);

                                                          return bytes;

                                                }

                                                

                                                //---------------------------------------------------------------------

                                                //

                                                // Private Methods.

                                                //

                                                //---------------------------------------------------------------------

                             

                                                private function onExtensionHandler( event : StatusEvent ) : void

                                                {

                                                          if( event.code == ExtensionsEvent.EXTENSION_EVENT )

                                                          {

                                                                    dispatchEvent( new ExtensionsEvent( event.level ) );

                                                                    context.removeEventListener( StatusEvent.STATUS, onExtensionHandler );

                                                          }

                                                }

                                      }

                            }

                             

                             

                            <extension xmlns="http://ns.adobe.com/air/extension/2.5">

                                <id>com.ticketsolve.extensions</id>

                                <versionNumber>0.0.1</versionNumber>

                                <platforms>

                                    <platform name="iPhone-ARM">

                                        <applicationDeployment>

                                            <nativeLibrary>libExtensions.a</nativeLibrary>

                                            <initializer>ExtInitializer</initializer>

                                            <finalizer>ExtFinalizer</finalizer>

                                        </applicationDeployment>

                                    </platform>

                                  <platform name="default">

                                    <applicationDeployment/>

                                  </platform>

                                </platforms>

                            </extension>

                             

                             



                            public function scaledFile() : File


                            {



                            var file:File
                                    = File.applicationStorageDirectory.resolvePath( "paisti" + new Date().time + ".jpg" );



                            var stream:FileStream       = new FileStream()



                            var extensions : Extensions = new Extensions();







                            var bytes:ByteArray;







                            if( Capabilities.os.match( /iPhone/ ) )




                            bytes = extensions.encodeJPEG( original );



                            else




                            bytes = new JPEGEncoder().encode( original );











                            stream.open( file, FileMode.WRITE );



                            stream.writeBytes( bytes, 0, bytes.bytesAvailable );



                            stream.close();







                            bytes.clear();







                            return file;


                            }
                            • 11. Re: ANE, iOS and BitmapData
                              wedgedkc Community Member

                              Thanks, but I already got it going by looking at the .net image resize ane.