// Graphics Importer and Exporter Samples
// This example uses graphics importers to draw an image
// then demonstrates adding a filter effect to the image and
// using a Graphics Exporter component to export the image as
// a PNG image.
// Originally written by Sam Bushell for QuickTime "Live" '99
// WWDC 2000 Introduction to QuickTime

#include "MacShell.h"

//----------
static pascal Boolean theRequestSettingsFilter( DialogRef inDialog, EventRecord *ioEvent, short *outItemHit, void *inDataPtr );
static pascal Boolean theRequestSettingsFilter( DialogRef inDialog, EventRecord *ioEvent, short *outItemHit, void *inDataPtr )
{
#pragma unused( outItemHit )
	
	WindowRef		eventWindow;
	Boolean			result = false;
	PixMapHandle	hPixMap = GetGWorldPixMap(static_cast<GWorldPtr>(inDataPtr)); // static_cast for GCC

	if (ioEvent->what == updateEvt) {
		eventWindow = (WindowRef)(ioEvent->message);
		if (eventWindow != GetDialogWindow( inDialog )) {
			// blit the image to the screen	
			CopyBits(GetPortBitMapForCopyBits(static_cast<CGrafPtr>(inDataPtr)),
					 GetPortBitMapForCopyBits(GetWindowPort(eventWindow)),
			 		 &(*hPixMap)->bounds,
			 		 &(*hPixMap)->bounds,
					 ditherCopy,
			 		 NULL);
			 result = true;
		}
	}

	return result;
}

void FilterExport( void )
{
	OSErr err = noErr;
	Handle hOpenTypeList = NewHandle(0);
	long  numTypes = 0;
	FSSpec	theFSSpec;
	Boolean isSelected, isReplacing;
	GraphicsImportComponent importer = 0;
	Rect naturalBounds, windowBounds;
	WindowPtr window = NULL;
	GWorldPtr sourceGWorld = NULL;
	ImageDescriptionHandle offscreenDesc = NULL;
	GWorldPtr destGWorld = NULL;
	MatrixRecord matrix;
	ImageSequence imageSequence = 0;
	QTAtomContainer videoFilter = 0;
	QTAtomContainer videoFilterList = 0;
	ImageDescriptionHandle effectDesc = NULL;
	ImageSequenceDataSource effectDataSource = 0;
	QTParameterDialog dialog = NULL;
	QTParamPreviewRecord previewParameter = {0, NULL};	// sourceID, picHandle
	long aLong;
	QTAtom effectTypeAtom;
	OSType effectType;
	GraphicsExportComponent exporter = 0;
	
	BuildGraphicsImporterValidFileTypes( hOpenTypeList, &numTypes );
	HLock( hOpenTypeList );

	err = GetOneFileWithPreview(numTypes, (OSTypePtr)*hOpenTypeList, &theFSSpec, NULL);
	DisposeHandle( hOpenTypeList );
	if ( err ) return;
	
	// locate and open a graphics importer component
	err = GetGraphicsImporterForFile( &theFSSpec, &importer );

	// get the native size of the image associated with the importer
	err = GraphicsImportGetNaturalBounds( importer, &naturalBounds );
	windowBounds = naturalBounds;
	OffsetRect( &windowBounds, 10, 45 );
	window = NewCWindow( NULL, &windowBounds, "\pFilter Export ", true, documentProc, (WindowPtr)-1, true, 0);
	SetPortWindowPort( window );
	
	// draw the image into an offscreen GWorld
// Step 1. Insert Step1.clp here...

	
	pause();

	// allocate a second offscreen GWorld to draw the filtered image into
	err = QTNewGWorld( &destGWorld, k32ARGBPixelFormat, &naturalBounds, NULL, NULL, kICMTempThenAppMemory );
	LockPixels( GetGWorldPixMap( destGWorld ) );

	// ask for a list of all the single source effects (ie, filters)
	// this function returns a QTAtomContainer holding a list of the currently installed effects components
// Step 2. Insert QTGetEffectsList.clp here...


	// prompt for the user to select a filter
	// create a new atom container to build the effect
// Step 3. Insert QTNewAtomContainer.clp here...

	
	// create the effect dialog box; choose an effect from the list of effects passed to the function
	// standard dialog includes a preview of the effect
// Step 4. Insert StandardParameterDialog.clp here...


	// parse the effect sample to find out what kind of effect it was
// Step 5. Insert QTFindChildByIndex.clp here...

	
	// copy the effect type from the effectType atom -- ie. Blur effect is type 'blur'									
// Step 6. Insert QTCopyAtomDataToPtr.clp here...

	
	// cross platform friendly						   
	effectType = EndianU32_BtoN(effectType);

	// add a source label to the effect sample
	aLong = EndianU32_BtoN('srca');
// Step 7. Insert QTInsertChild.clp here...


	HLockHi(videoFilter);

// Step 8. Insert Step8.clp here

	
	// blit the now filtered image to the screen		
	CopyBits(GetPortBitMapForCopyBits(destGWorld),
			 GetPortBitMapForCopyBits(GetWindowPort(window)),
			 &naturalBounds,
			 &naturalBounds,
			 ditherCopy,
			 NULL);

	pause();

	// write the filtered image out as a PNG file.
	err = PutFile( "\pSave the filtered image:", "\pfiltered.png", &theFSSpec, &isSelected, &isReplacing);
	if (err) goto bail;

	// find and open the PNG Graphics Exporter component
// Step 9. Insert OpenADefaultComponent.clp here...

	
	// set the input for the graphics exporter
	err = GraphicsExportSetInputGWorld( exporter,		// component instance
										destGWorld );	// input source
	
	// set the destination for the export								
// Step 10. Insert SetOutputFile.clp here...

	
	// the depth to use for the exported image
// Step 11. Insert SetDepth.clp here...

	
	// do the export
// Step 12. Insert DoExport.clp here...

	
	// blit the image to the screen	
	CopyBits(GetPortBitMapForCopyBits(destGWorld),
			 GetPortBitMapForCopyBits(GetWindowPort(window)),
			 &naturalBounds,
			 &naturalBounds,
			 ditherCopy,
			 NULL);
	
	CloseComponent ( exporter );
	
	pause();
	
	// write out the image again as a .jpg using the settings dialog
	OpenADefaultComponent( GraphicsExporterComponentType, kQTFileTypeJPEG, &exporter );
	
	// does the export component supports the exporter setting dialog?
	if ( CallComponentCanDo( exporter , kGraphicsExportRequestSettingsSelect )) {
	
		// set the input for the graphics exporter
		err = GraphicsExportSetInputGWorld( exporter,		// component instance
											destGWorld );	// input source
		
		// get the settings using the settings dialog
		err = GraphicsExportRequestSettings( exporter,
									   		 NewModalFilterYDUPP( theRequestSettingsFilter ),
									   		 destGWorld );
									   		 
		err = PutFile( "\pSave the filtered image:", "\pfiltered.jpg", &theFSSpec, &isSelected, &isReplacing);
		if (err) goto bail;		

		// set the destination for the export								
		err = GraphicsExportSetOutputFile( exporter,
									   	   &theFSSpec );	// export destination		
		// do the export
		err = GraphicsExportDoExport( exporter,
								  	  NULL );				// actual size written; NULL to ignore
	}
	
	// blit the image to the screen	
	CopyBits(GetPortBitMapForCopyBits(destGWorld),
			 GetPortBitMapForCopyBits(GetWindowPort(window)),
			 &naturalBounds,
			 &naturalBounds,
			 ditherCopy,
			 NULL);	
bail:
	// clean up
	if ( imageSequence ) 	CDSequenceEnd( imageSequence );
	if ( videoFilter ) 		QTDisposeAtomContainer( videoFilter );
	if ( videoFilterList ) 	QTDisposeAtomContainer( videoFilterList );
	if ( offscreenDesc)		DisposeHandle( (Handle)offscreenDesc );
	if ( effectDesc )		DisposeHandle( (Handle)effectDesc );
	if ( importer )			CloseComponent( importer );
	if ( exporter )			CloseComponent( exporter );
	if ( sourceGWorld )		DisposeGWorld( sourceGWorld );
	if ( destGWorld )		DisposeGWorld( destGWorld );
	if ( previewParameter.sourcePicture ) KillPicture( previewParameter.sourcePicture );
}
