Difference between revisions of "Binary Tips"
From FM Plugin Wikipedia
(→Example Binary Functions) |
|||
| Line 39: | Line 39: | ||
=Example Binary Functions= | =Example Binary Functions= | ||
| + | |||
| + | |||
| + | The following example code shows how to create a bitmap image, convert it to PNG and return to FileMaker | ||
| + | |||
| + | |||
| + | |||
| + | FMX_PROC(fmx::errcode) Do_Graphic(short /* funcId */, const fmx::ExprEnv& /* environment */, const fmx::DataVect& dataVect, fmx::Data& results ) | ||
| + | { | ||
| + | |||
| + | fmx::errcode err = 0; | ||
| + | bool haveImage = false; | ||
| + | fmx::QuadCharAutoPtr png('P', 'N', 'G', 'f'); | ||
| + | fmx::BinaryDataAutoPtr outImage; | ||
| + | |||
| + | |||
| + | long pixelsWide = 300; | ||
| + | long pixelsHigh = 150; | ||
| + | |||
| + | long size = 0; | ||
| + | unsigned char * outBuffer = returnGraphicImage(pixelsWide, pixelsHigh, &size); | ||
| + | if( outBuffer != NULL ) | ||
| + | { | ||
| + | |||
| + | err = outImage->Add ( *png, size, outBuffer ); | ||
| + | if (err == 0) | ||
| + | { | ||
| + | fmx::TextAutoPtr temp; | ||
| + | temp->Assign("Picture.png"); | ||
| + | const fmx::Text& name = *temp; | ||
| + | err = outImage->AddFNAMData( name ); // so FileMaker has a name for our image if the user tries to save it or external storage is used | ||
| + | |||
| + | err = outImage->AddSIZEData( pixelsWide, pixelsHigh ); // all images must have a size specified | ||
| + | haveImage = ( err == 0 ); | ||
| + | if( haveImage ) results.SetBinaryData ( *outImage ); | ||
| + | } | ||
| + | |||
| + | delete [] outBuffer; | ||
| + | } | ||
| + | |||
| + | return err; | ||
| + | } | ||
| + | |||
| + | |||
| + | |||
| + | The 'returnGraphicImage' function for Mac: | ||
| + | |||
| + | |||
| + | #if defined(FMX_MAC_TARGET) | ||
| + | unsigned char * returnGraphicImage( long width, long height, long *outSize ) | ||
| + | { | ||
| + | #define BYTES_PER_PIXEL 4 | ||
| + | |||
| + | CFMutableDataRef imgData = CFDataCreateMutable( kCFAllocatorDefault, 0); | ||
| + | if( imgData == NULL ) return NULL; | ||
| + | |||
| + | CGImageDestinationRef destRef = CGImageDestinationCreateWithData(imgData, kUTTypePNG, 1, NULL); | ||
| + | if( destRef == NULL ) { CFRelease( imgData ); return NULL; } | ||
| + | |||
| + | // create an image from the layer | ||
| + | void *buffer = malloc(width * height * BYTES_PER_PIXEL); | ||
| + | if( buffer == NULL ) { CFRelease( destRef ); CFRelease( imgData ); return NULL; } | ||
| + | memset(&buffer, 0, sizeof(buffer)); | ||
| + | |||
| + | |||
| + | CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); | ||
| + | CGContextRef context = CGBitmapContextCreate (buffer, width, height, 8, width * BYTES_PER_PIXEL, colorSpace, kCGImageAlphaPremultipliedLast); | ||
| + | CGColorSpaceRelease( colorSpace ); | ||
| + | |||
| + | if( context == NULL ) { CFRelease( destRef ); CFRelease( imgData ); free( buffer ); return NULL; } | ||
| + | |||
| + | |||
| + | // Open the image area for drawing | ||
| + | CGContextSaveGState(context); | ||
| + | CGRect rect = CGRectMake(0, 0, width, height); // RECT representing the area available for drawing to. | ||
| + | // --------------------------------------------------------------------------------------------------------------- | ||
| + | |||
| + | CGContextSetRGBStrokeColor(context, 1, 0, 0, 1); // Draw a 'Red' frame around our image. | ||
| + | CGContextStrokeRectWithWidth(context, rect, 6); | ||
| + | |||
| + | CGContextSelectFont(context, "Verdana", 12, kCGEncodingMacRoman); // Add some text to our image | ||
| + | CGContextSetAllowsAntialiasing(context, false); | ||
| + | CGContextSetCharacterSpacing(context, 1.0); | ||
| + | CGContextSetTextDrawingMode(context, kCGTextFill); | ||
| + | CGContextShowTextAtPoint(context, 50.0, 50.0, "Hello and Welcome", 17); | ||
| + | |||
| + | |||
| + | // --------------------------------------------------------------------------------------------------------------- | ||
| + | |||
| + | CGImageRef image = CGBitmapContextCreateImage(context); // We have finished drawing the image | ||
| + | CGContextRestoreGState(context); | ||
| + | |||
| + | CGImageDestinationAddImage(destRef, image, NULL); // Convert the image to PNG | ||
| + | CGImageDestinationFinalize(destRef); | ||
| + | |||
| + | CGContextRelease(context); | ||
| + | CFRelease(destRef); // have finished with destRef - our image should now be in 'imgData' | ||
| + | free(buffer); // have finished with the image buffer now too | ||
| + | |||
| + | unsigned char * outBuffer = NULL; | ||
| + | long size = (long)CFDataGetLength(imgData); | ||
| + | if( size > 0 ) | ||
| + | { | ||
| + | outBuffer = new unsigned char [ size ]; | ||
| + | |||
| + | if( outBuffer != NULL ) CFDataGetBytes( imgData, CFRangeMake(0, size), outBuffer ); | ||
| + | } | ||
| + | |||
| + | CFRelease(imgData); | ||
| + | |||
| + | *outSize = size; // return the size of our created buffer | ||
| + | return outBuffer; // and the buffer itself | ||
| + | } | ||
| + | #endif | ||
Revision as of 21:07, 25 April 2013
This page is about editing and working with Binary data (Images, sound, etc) passed from FileMaker to your plugin.
Binary Public Functions
- BinaryData &operator = ( const BinaryData &source )
- bool operator == ( const BinaryData &compareData ) const
- bool operator != ( const BinaryData &compareData ) const
- int GetCount () const
- int GetIndex ( const QuadChar& dataType ) const
- ulong GetTotalSize () const
- void GetType ( int index, QuadChar& dataType ) const
- ulong GetSize ( int index ) const
- errcode GetData ( int index, ulong offset, ulong amount, void *buffer ) const
- errcode Add ( const QuadChar& dataType, ulong amount, void *buffer )
- bool Remove ( const QuadChar& dataType )
- void RemoveAll ()
- errcode GetFNAMData ( Text &filepathlist ) const
- errcode AddFNAMData ( const Text &filepathlist )
- errcode GetSIZEData ( short &width, short &height ) const
- errcode AddSIZEData ( short width, short height )
Example Binary Functions
The following example code shows how to create a bitmap image, convert it to PNG and return to FileMaker
FMX_PROC(fmx::errcode) Do_Graphic(short /* funcId */, const fmx::ExprEnv& /* environment */, const fmx::DataVect& dataVect, fmx::Data& results )
{
fmx::errcode err = 0;
bool haveImage = false;
fmx::QuadCharAutoPtr png('P', 'N', 'G', 'f');
fmx::BinaryDataAutoPtr outImage;
long pixelsWide = 300;
long pixelsHigh = 150;
long size = 0;
unsigned char * outBuffer = returnGraphicImage(pixelsWide, pixelsHigh, &size);
if( outBuffer != NULL )
{
err = outImage->Add ( *png, size, outBuffer );
if (err == 0)
{
fmx::TextAutoPtr temp;
temp->Assign("Picture.png");
const fmx::Text& name = *temp;
err = outImage->AddFNAMData( name ); // so FileMaker has a name for our image if the user tries to save it or external storage is used
err = outImage->AddSIZEData( pixelsWide, pixelsHigh ); // all images must have a size specified
haveImage = ( err == 0 );
if( haveImage ) results.SetBinaryData ( *outImage );
}
delete [] outBuffer;
}
return err;
}
The 'returnGraphicImage' function for Mac:
#if defined(FMX_MAC_TARGET)
unsigned char * returnGraphicImage( long width, long height, long *outSize )
{
#define BYTES_PER_PIXEL 4
CFMutableDataRef imgData = CFDataCreateMutable( kCFAllocatorDefault, 0);
if( imgData == NULL ) return NULL;
CGImageDestinationRef destRef = CGImageDestinationCreateWithData(imgData, kUTTypePNG, 1, NULL);
if( destRef == NULL ) { CFRelease( imgData ); return NULL; }
// create an image from the layer
void *buffer = malloc(width * height * BYTES_PER_PIXEL);
if( buffer == NULL ) { CFRelease( destRef ); CFRelease( imgData ); return NULL; }
memset(&buffer, 0, sizeof(buffer));
CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
CGContextRef context = CGBitmapContextCreate (buffer, width, height, 8, width * BYTES_PER_PIXEL, colorSpace, kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease( colorSpace );
if( context == NULL ) { CFRelease( destRef ); CFRelease( imgData ); free( buffer ); return NULL; }
// Open the image area for drawing
CGContextSaveGState(context);
CGRect rect = CGRectMake(0, 0, width, height); // RECT representing the area available for drawing to.
// ---------------------------------------------------------------------------------------------------------------
CGContextSetRGBStrokeColor(context, 1, 0, 0, 1); // Draw a 'Red' frame around our image.
CGContextStrokeRectWithWidth(context, rect, 6);
CGContextSelectFont(context, "Verdana", 12, kCGEncodingMacRoman); // Add some text to our image
CGContextSetAllowsAntialiasing(context, false);
CGContextSetCharacterSpacing(context, 1.0);
CGContextSetTextDrawingMode(context, kCGTextFill);
CGContextShowTextAtPoint(context, 50.0, 50.0, "Hello and Welcome", 17);
// ---------------------------------------------------------------------------------------------------------------
CGImageRef image = CGBitmapContextCreateImage(context); // We have finished drawing the image
CGContextRestoreGState(context);
CGImageDestinationAddImage(destRef, image, NULL); // Convert the image to PNG
CGImageDestinationFinalize(destRef);
CGContextRelease(context);
CFRelease(destRef); // have finished with destRef - our image should now be in 'imgData'
free(buffer); // have finished with the image buffer now too
unsigned char * outBuffer = NULL;
long size = (long)CFDataGetLength(imgData);
if( size > 0 )
{
outBuffer = new unsigned char [ size ];
if( outBuffer != NULL ) CFDataGetBytes( imgData, CFRangeMake(0, size), outBuffer );
}
CFRelease(imgData);
*outSize = size; // return the size of our created buffer
return outBuffer; // and the buffer itself
}
#endif