Binary Tips

From FM Plugin Wikipedia
Revision as of 21:07, 25 April 2013 by Kent (talk | contribs) (Example Binary Functions)

Jump to: navigation, search

This page is about editing and working with Binary data (Images, sound, etc) passed from FileMaker to your plugin.


Binary Public 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