[futurebasic] Re: [FB] Saving various image formats

Message: < previous - next > : Reply : Subscribe : Cleanse
Home   : April 2011 : Group Archive : Group : All Groups

From: Robert Purves <listrp@...>
Date: Fri, 22 Apr 2011 20:26:18 +1200
Warren Lanford wrote:

>  I then save the contents of gworld1 as an image file.  This is where I wish to save the files as different types such as .png, .jpeg, .tiff, etc.
>      I can't see how to use the function ( local fn MyCreateCGBitmapContext( w as UInt32, h as UInt32 ) as CGContextRef ) to create a bitmap of my gworld1.

CreateCGBitmapContextFromGWorld() in the demo below takes a GWorld parameter and returns a CGContextRef.
SaveBitmapContextAsImageFile() saves the image in whatever format you choose.

Robert P.


'------------------
include "Tlbx CoreGraphics.incl"
include "Tlbx UTCoreTypes.incl"

#if ndef _DEFINEDINCARBON
// CGImageDestination.h
#define CGImageDestinationRef as pointer
#endif
toolbox fn CGImageDestinationCreateWithURL( CFURLRef url, CFStringRef type, UInt32 count, CFDictionaryRef options ) = CGImageDestinationRef
toolbox fn CGImageDestinationFinalize( CGImageDestinationRef idst ) = Boolean
toolbox CGImageDestinationAddImage( CGImageDestinationRef idst, CGImageRef image, CFDictionaryRef properties )

/*
Wrap a CGBitmapContext around the pixel data of a GWorld.
Caller must release the context.
*/
local mode
local fn CreateCGBitmapContextFromGWorld( theGW as CGrafPtr ) as CGContextRef
'~'1
dim as CGColorSpaceRef  cs
dim as CGContextRef     ctx : ctx = 0
dim as long             rowBytes     
dim as ^^PixMap         pmHandle     
dim as pointer          imageBuf     
dim as Rect             bounds

pmHandle = fn GetGWorldPixMap( theGW )
if ( pmHandle..pixelSize != 32 ) then stop "GWorld must have depth 32"
rowBytes = fn GetPixRowBytes( pmHandle )
imageBuf = fn GetPixBaseAddr( pmHandle )
bounds = pmHandle..bounds
cs = fn CGColorSpaceCreateDeviceRGB()
ctx = fn CGBitmapContextCreate( imageBuf, bounds.right, bounds.bottom, 8, rowBytes, cs, _kCGImageAlphaPremultipliedFirst )
CGColorSpaceRelease( cs )
if ( ctx == 0 ) then stop "CGBitmapContextCreate failed"
end fn = ctx


local mode
local fn SaveBitmapContextAsImageFile( ctx as CGContextRef, url as CFURLRef, type as CFStringRef )
'~'1
dim as CGImageDestinationRef  imageDest 
dim as CGImageRef             image
dim as Boolean                success : success = _false

// CGBitMapContext -> CGImage
image = fn CGBitmapContextCreateImage( ctx ) 
long if ( image )
// create CGImageDestination
imageDest = fn CGImageDestinationCreateWithURL( url, type, 1, 0 )
long if ( imageDest )
// CGImage + CGImageDestination -> file
CGImageDestinationAddImage( imageDest, image, 0 )
success = fn CGImageDestinationFinalize( imageDest )
CFRelease( imageDest )
end if
CGImageRelease( image )
end if
end fn = success


local fn DrawInGWorld( theGW as CGrafPtr )
'~'1
dim as CGrafPtr    oldGW
dim as GDHandle    oldDev

GetGWorld( @oldGW, @oldDev )
SetGWorld( theGW, 0 )
PenSize( 5, 5 )
ForeColor( _redColor )
MoveTo( 0, 0 ) : LineTo( 400, 600 )
ForeColor( _blueColor )
MoveTo( 0, 600 ) : LineTo( 400, 0 )
ForeColor( _blackColor )
LineTo( 0, 0 )
SetGWorld( oldGW, oldDev )
end fn


// main
dim as Rect            r
dim as CGrafPtr        theGW   
dim as CGContextRef    ctx
dim as CFURLRef        url
dim as Boolean         ok

SetRect( r, 0, 0, 400, 600 )
fn NewGWorld( @theGW, 32, r, 0, 0, 0 )
fn DrawInGWorld( theGW )

ctx = fn CreateCGBitmapContextFromGWorld( theGW )
long if ( ctx )
long if ( files$( _CFURLRefSave,, "untitled.png", url ) )
// kUTTypePNG kUTTypeTIFF kUTTypeGIF kUTTypeJPEG ...
ok = fn SaveBitmapContextAsImageFile( ctx, url, kUTTypePNG ) 
CFRelease( url )
if ( ok == _false ) then stop "SaveBitmapContextAsImageFile failed"
end if
CGContextRelease( ctx ) // release context only (its data belongs to theGW)
end if

DisposeGWorld( theGW )
end
'------------------