Binary Tips
From FM Plugin Wikipedia
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); // Get our image if( outBuffer != NULL ) { err = outImage->Add ( *png, size, outBuffer ); // Let FM know the image type is PNG 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 ); // Add the image data } delete [] outBuffer; } return err; }
The 'returnGraphicImage' function for Mac:
#if defined(FMX_WIN_TARGET) unsigned char * returnGraphicImage( long width, long height, long *outSize ) { long size = 0; unsigned char outBuffer = NULL; // This is a work in progress ! *outSize = size; // return the size of our created buffer return outBuffer; // and the buffer itself } #endif
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