Copy link to clipboard
Copied
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;
}
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;
...
Copy link to clipboard
Copied
Not sure, but I don't think you can access input and thus bitmapData.bits32 after you have called FREReleaseBitmapData().
Copy link to clipboard
Copied
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;
}
Copy link to clipboard
Copied
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;
}
Copy link to clipboard
Copied
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.
Copy link to clipboard
Copied
Why you want use ANE ? this convertation may be you can do in AS ? Don't thinkg about that?
Copy link to clipboard
Copied
Because doing it C is much, much faster.
Copy link to clipboard
Copied
how much ? ) for a few seconds? )))
Copy link to clipboard
Copied
That depends on the size of your image and compression parameters. I'd estimate a factor of 10.
Copy link to clipboard
Copied
It is painfully slow in AS - typically 30 seconds and more. This seems to be the consistent experience from others as well.
Sean
Copy link to clipboard
Copied
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; | |||||
} |
Copy link to clipboard
Copied
Thanks, but I already got it going by looking at the .net image resize ane.