Difference between revisions of "Binary Tips"
From FM Plugin Wikipedia
(→Example Binary Functions) |
(→Example Binary Functions) |
||
| Line 81: | Line 81: | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| Line 165: | Line 149: | ||
*outSize = size; // return the size of our created buffer | *outSize = size; // return the size of our created buffer | ||
return outBuffer; // and the buffer itself | return outBuffer; // and the buffer itself | ||
| + | } | ||
| + | #endif | ||
| + | |||
| + | |||
| + | |||
| + | The 'returnGraphicImage' function for Windows: | ||
| + | |||
| + | #if defined(FMX_WIN_TARGET) | ||
| + | unsigned char * returnTimetableImage( long width, long height, long* outSize ) | ||
| + | { | ||
| + | // ----------------------------------------------------------------------------------------------------------------------------- | ||
| + | // Use GDI to draw our original Bitmap image | ||
| + | |||
| + | Bitmap * outBM = new Bitmap(width, height, PixelFormat32bppARGB ); | ||
| + | Graphics * gr = Graphics::FromImage( outBM ); | ||
| + | |||
| + | gr->Clear(Gdiplus::Color::Transparent); | ||
| + | |||
| + | SolidBrush sb(Gdiplus::Color::Red); | ||
| + | gr->FillRectangle( &sb, 20,20, 100, 50 ); | ||
| + | |||
| + | sb.SetColor(Gdiplus::Color::Green); | ||
| + | gr->FillRectangle( &sb, 220,220, 80, 60 ); | ||
| + | |||
| + | Pen pen(Color(Gdiplus::Color::Black), 5); | ||
| + | gr->DrawRectangle( &pen, 30, 30, 120, 70 ); | ||
| + | |||
| + | |||
| + | FontFamily fontFamily(L"Verdana"); | ||
| + | Font font(&fontFamily, 12, FontStyleRegular, UnitPixel); | ||
| + | PointF pointF(160, 200); | ||
| + | sb.SetColor(Gdiplus::Color::Black); | ||
| + | gr->DrawString(L"Hello", -1, &font, pointF, &sb); | ||
| + | |||
| + | |||
| + | RectF rectF( 180, 250, 100, 100 ); | ||
| + | sb.SetColor(Color(127,0,0,255)); | ||
| + | gr->FillRectangle( &sb, rectF ); | ||
| + | gr->DrawRectangle(&pen, rectF ); | ||
| + | |||
| + | sb.SetColor(Color(Gdiplus::Color::Black)); | ||
| + | gr->DrawString(L"This is lots of text", -1, &font, rectF, NULL, &sb); | ||
| + | |||
| + | |||
| + | Gdiplus::Rect r; | ||
| + | r.X = 0; | ||
| + | r.Y = 0; | ||
| + | r.Width = width; | ||
| + | r.Height = height; | ||
| + | |||
| + | BitmapData * bitmapData = new BitmapData; | ||
| + | outBM->LockBits( &r, ImageLockModeRead, PixelFormat32bppARGB, bitmapData ); // Lock the bitmapData - must release it after 'CreateBitmapFromMemory' | ||
| + | |||
| + | BYTE* pixels = (BYTE*)bitmapData->Scan0; // This is the Bitmap image raw data | ||
| + | UINT stride = bitmapData->Stride; // This is the bytes per line. We need this for 'CreateBitmapFromMemory' below | ||
| + | |||
| + | |||
| + | // ----------------------------------------------------------------------------------------------------------------------------- | ||
| + | HRESULT hr = CoInitialize(NULL); | ||
| + | |||
| + | IWICImagingFactory* pFactory = NULL; | ||
| + | hr = CoCreateInstance( CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, (LPVOID*)&pFactory); | ||
| + | |||
| + | //Create the outgoing stream | ||
| + | HGLOBAL hOutGlobal = GlobalAlloc( GMEM_SHARE | GMEM_MOVEABLE, 0 ); | ||
| + | IStream* pOutStream = NULL; | ||
| + | hr = CreateStreamOnHGlobal( hOutGlobal, FALSE, &pOutStream ); | ||
| + | |||
| + | //Create the encoder. | ||
| + | IWICBitmapEncoder* pEncoder = NULL; | ||
| + | hr = pFactory->CreateEncoder( GUID_ContainerFormatPng, NULL, &pEncoder ); | ||
| + | hr = pEncoder->Initialize( pOutStream, WICBitmapEncoderNoCache ); | ||
| + | |||
| + | //Get frame to decode | ||
| + | IWICBitmapSource* pFrameDecode = NULL; | ||
| + | hr = pFactory->CreateBitmapFromMemory( width, height, GUID_WICPixelFormat32bppBGRA, stride, height * stride, pixels, (IWICBitmap**)&pFrameDecode ); | ||
| + | |||
| + | //Create frame to encode into | ||
| + | IWICBitmapFrameEncode* pFrameEncode = NULL; | ||
| + | IPropertyBag2* pPropertyBag = NULL; | ||
| + | hr = pEncoder->CreateNewFrame( &pFrameEncode, &pPropertyBag ); | ||
| + | hr = pFrameEncode->Initialize( pPropertyBag ); | ||
| + | |||
| + | // Set the encoder's size, resolution, color palette, pixel format, etc now | ||
| + | WICRect rect = {0, 0, 0, 0}; | ||
| + | rect.Width = width; | ||
| + | rect.Height = height; | ||
| + | hr = pFrameEncode->WriteSource( pFrameDecode, &rect ); | ||
| + | |||
| + | hr = pFrameEncode->Commit(); | ||
| + | hr = pEncoder->Commit(); | ||
| + | pFrameEncode->Release(); | ||
| + | pFrameDecode->Release(); | ||
| + | |||
| + | //Get the bytes from the outStream | ||
| + | ULARGE_INTEGER Size; | ||
| + | LARGE_INTEGER zero; | ||
| + | zero.QuadPart = 0; | ||
| + | |||
| + | pOutStream->Seek( zero, STREAM_SEEK_END, &Size ); | ||
| + | ULONG encoded; | ||
| + | ULongLongToULong( Size.QuadPart, &encoded); | ||
| + | UINT imageSize = encoded; | ||
| + | |||
| + | pOutStream->Release(); | ||
| + | |||
| + | LPVOID p2 = GlobalLock(hOutGlobal); | ||
| + | void * imagePtr = malloc( encoded ); | ||
| + | memcpy( imagePtr, p2, encoded ); | ||
| + | |||
| + | pEncoder->Release(); | ||
| + | |||
| + | GlobalUnlock( hOutGlobal ); | ||
| + | GlobalFree( hOutGlobal ); | ||
| + | |||
| + | pFactory->Release(); | ||
| + | |||
| + | // Clean up our original Bitmap | ||
| + | outBM->UnlockBits( bitmapData ); | ||
| + | delete bitmapData; | ||
| + | delete outBM; | ||
| + | delete gr; | ||
| + | |||
| + | |||
| + | *outSize = imageSize; | ||
| + | return (unsigned char *)imagePtr; | ||
} | } | ||
#endif | #endif | ||
Revision as of 01:28, 2 May 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); // 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_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
The 'returnGraphicImage' function for Windows:
#if defined(FMX_WIN_TARGET)
unsigned char * returnTimetableImage( long width, long height, long* outSize )
{
// -----------------------------------------------------------------------------------------------------------------------------
// Use GDI to draw our original Bitmap image
Bitmap * outBM = new Bitmap(width, height, PixelFormat32bppARGB );
Graphics * gr = Graphics::FromImage( outBM );
gr->Clear(Gdiplus::Color::Transparent);
SolidBrush sb(Gdiplus::Color::Red);
gr->FillRectangle( &sb, 20,20, 100, 50 );
sb.SetColor(Gdiplus::Color::Green);
gr->FillRectangle( &sb, 220,220, 80, 60 );
Pen pen(Color(Gdiplus::Color::Black), 5);
gr->DrawRectangle( &pen, 30, 30, 120, 70 );
FontFamily fontFamily(L"Verdana");
Font font(&fontFamily, 12, FontStyleRegular, UnitPixel);
PointF pointF(160, 200);
sb.SetColor(Gdiplus::Color::Black);
gr->DrawString(L"Hello", -1, &font, pointF, &sb);
RectF rectF( 180, 250, 100, 100 );
sb.SetColor(Color(127,0,0,255));
gr->FillRectangle( &sb, rectF );
gr->DrawRectangle(&pen, rectF );
sb.SetColor(Color(Gdiplus::Color::Black));
gr->DrawString(L"This is lots of text", -1, &font, rectF, NULL, &sb);
Gdiplus::Rect r;
r.X = 0;
r.Y = 0;
r.Width = width;
r.Height = height;
BitmapData * bitmapData = new BitmapData;
outBM->LockBits( &r, ImageLockModeRead, PixelFormat32bppARGB, bitmapData ); // Lock the bitmapData - must release it after 'CreateBitmapFromMemory'
BYTE* pixels = (BYTE*)bitmapData->Scan0; // This is the Bitmap image raw data
UINT stride = bitmapData->Stride; // This is the bytes per line. We need this for 'CreateBitmapFromMemory' below
// -----------------------------------------------------------------------------------------------------------------------------
HRESULT hr = CoInitialize(NULL);
IWICImagingFactory* pFactory = NULL;
hr = CoCreateInstance( CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, (LPVOID*)&pFactory);
//Create the outgoing stream
HGLOBAL hOutGlobal = GlobalAlloc( GMEM_SHARE | GMEM_MOVEABLE, 0 );
IStream* pOutStream = NULL;
hr = CreateStreamOnHGlobal( hOutGlobal, FALSE, &pOutStream );
//Create the encoder.
IWICBitmapEncoder* pEncoder = NULL;
hr = pFactory->CreateEncoder( GUID_ContainerFormatPng, NULL, &pEncoder );
hr = pEncoder->Initialize( pOutStream, WICBitmapEncoderNoCache );
//Get frame to decode
IWICBitmapSource* pFrameDecode = NULL;
hr = pFactory->CreateBitmapFromMemory( width, height, GUID_WICPixelFormat32bppBGRA, stride, height * stride, pixels, (IWICBitmap**)&pFrameDecode );
//Create frame to encode into
IWICBitmapFrameEncode* pFrameEncode = NULL;
IPropertyBag2* pPropertyBag = NULL;
hr = pEncoder->CreateNewFrame( &pFrameEncode, &pPropertyBag );
hr = pFrameEncode->Initialize( pPropertyBag );
// Set the encoder's size, resolution, color palette, pixel format, etc now
WICRect rect = {0, 0, 0, 0};
rect.Width = width;
rect.Height = height;
hr = pFrameEncode->WriteSource( pFrameDecode, &rect );
hr = pFrameEncode->Commit();
hr = pEncoder->Commit();
pFrameEncode->Release();
pFrameDecode->Release();
//Get the bytes from the outStream
ULARGE_INTEGER Size;
LARGE_INTEGER zero;
zero.QuadPart = 0;
pOutStream->Seek( zero, STREAM_SEEK_END, &Size );
ULONG encoded;
ULongLongToULong( Size.QuadPart, &encoded);
UINT imageSize = encoded;
pOutStream->Release();
LPVOID p2 = GlobalLock(hOutGlobal);
void * imagePtr = malloc( encoded );
memcpy( imagePtr, p2, encoded );
pEncoder->Release();
GlobalUnlock( hOutGlobal );
GlobalFree( hOutGlobal );
pFactory->Release();
// Clean up our original Bitmap
outBM->UnlockBits( bitmapData );
delete bitmapData;
delete outBM;
delete gr;
*outSize = imageSize;
return (unsigned char *)imagePtr;
}
#endif