Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
QTGraphImp.c
////////// |
// |
// File: QTGraphImp.c |
// |
// Contains: Sample code for using QuickTime's graphics import routines. |
// |
// Written by: Tim Monroe |
// Based loosely on the SimpleGIExample.c code written by Apple DTS; |
// exporting code based heavily on Dispatch 14 from the Ice Floe by Sam Bushell. |
// |
// Copyright: © 1998 by Apple Computer, Inc., all rights reserved. |
// |
// Change History (most recent first): |
// |
// <3> 03/21/00 rtm reworked functions to avoid calling Standard File Package |
// <2> 06/02/98 rtm added QTGraphImp_ExportGWorldToFile and _GetAvailableExportTypes, |
// from Dispatch 14 from the Ice Floe; added QTGraphImp_ExportImageFile |
// <1> 04/14/98 rtm first file |
// |
// This sample code illustrates how to use QuickTime's graphics importer routines |
// to open and display image files. The graphics importer routines were introduced |
// in QuickTime version 2.5 as a new way to draw still images. The graphics import |
// routines (for example, GetGraphicsImporterForFile) use graphics import components |
// (of component type 'grip') to open and perform other operations on image files. |
// Essentially, you can use the graphics import routines to insulate your application |
// from the nitty gritty details of the image file format and compression used in the |
// image. |
// |
// This code also shows how to export images as picture files, and how to determine which |
// formats an image can be exported in. The QT functions that support these operations |
// were introduced in QuickTime version 3. |
// |
// In this sample code, we allow the user to open an image file; then we draw it into |
// a window on the screen. Your application, of course, will probably want to do more |
// interesting things with the image. We also allow the user to save an image using JPEG |
// compression. |
// |
////////// |
////////// |
// |
// header files |
// |
////////// |
#include "QTGraphImp.h" |
////////// |
// |
// global variables |
// |
////////// |
WindowPtr gImageWindow = NULL; // the window we display the image in |
GraphicsImportComponent gImporter = NULL; |
////////// |
// |
// QTGraphImp_OpenImageFileAndDisplay |
// Open an image file, then display the image in a window. |
// |
////////// |
void QTGraphImp_OpenImageFileAndDisplay (FSSpecPtr theFSSpecPtr) |
{ |
Rect myRect; |
OSErr myErr = noErr; |
if (theFSSpecPtr == NULL) |
goto bail; |
////////// |
// |
// get a graphics importer for the image file and determine the natural size of the image |
// |
////////// |
myErr = GetGraphicsImporterForFile(theFSSpecPtr, &gImporter); |
if (myErr != noErr) |
goto bail; |
myErr = GraphicsImportGetNaturalBounds(gImporter, &myRect); |
if (myErr != noErr) |
goto bail; |
////////// |
// |
// create a window to display the image in; then draw into that window |
// |
////////// |
MacOffsetRect(&myRect, 50, 50); |
gImageWindow = NewCWindow(NULL, &myRect, theFSSpecPtr->name, true, movableDBoxProc, (WindowPtr)-1L, true, 0); |
if (gImageWindow == NULL) |
goto bail; |
// set the current port and draw |
GraphicsImportSetGWorld(gImporter, GetWindowPort(gImageWindow), NULL); |
GraphicsImportDraw(gImporter); |
bail: |
if (myErr != noErr) |
if (gImporter != NULL) |
CloseComponent(gImporter); |
} |
////////// |
// |
// QTGraphImp_SaveCompressedImageIntoDiskFile |
// Compress the current picture into the specified file. |
// |
////////// |
void QTGraphImp_SaveCompressedImageIntoDiskFile (FSSpecPtr theFSSpecPtr) |
{ |
Rect myRect; |
GWorldPtr myGWorld; |
OSErr myErr = noErr; |
if (theFSSpecPtr == NULL) |
goto bail; |
// get the natural size of the image |
myErr = GraphicsImportGetNaturalBounds(gImporter, &myRect); |
if (myErr != noErr) |
goto bail; |
// create an offscreen graphics world to draw the image into |
myErr = NewGWorld(&myGWorld, 0, &myRect, NULL, NULL, 0); |
if (myErr == noErr) { |
GraphicsImportSetGWorld(gImporter, (CGrafPtr)myGWorld, NULL); |
GraphicsImportDraw(gImporter); |
// save the compressed image |
QTGraphImp_SaveCompressedImage(myGWorld, theFSSpecPtr); |
if (myGWorld != NULL) |
DisposeGWorld(myGWorld); |
} |
bail: |
; |
} |
////////// |
// |
// QTGraphImp_SaveCompressedImage |
// Save the current image as a compressed file. |
// |
////////// |
void QTGraphImp_SaveCompressedImage (GWorldPtr theWorld, FSSpec *theFile) |
{ |
ImageDescriptionHandle myDesc; |
Handle myData; |
Rect myRect; |
PixMapHandle myPixMap; |
CTabHandle myCTab = NULL; |
ICMFlushProcRecord myFlushProc; |
short myRefNum; |
short myDepth; |
OSErr myErr = noErr; |
if ((theWorld == NULL) || (theFile == NULL)) |
goto bail; |
myDesc = (ImageDescriptionHandle)NewHandle(sizeof(ImageDescription)); |
if (myDesc == NULL) |
goto bail; |
#if TARGET_OS_MAC |
GetPortBounds(theWorld, &myRect); |
#endif |
#if TARGET_OS_WIN32 |
myRect = theWorld->portRect; |
#endif |
myPixMap = GetGWorldPixMap(theWorld); |
if (LockPixels(myPixMap)) { |
// if less than 16-bit, then get the color table of our GWorld |
myDepth = (**myPixMap).pixelSize; |
if (myDepth < 16) |
myCTab = (**myPixMap).pmTable; |
myData = NewHandle(kBufferSize); |
myErr = MemError(); |
if ((myData != NULL) && (myErr == noErr)) { |
CodecType myCodec = kJPEGCodecType; |
HLock(myData); |
myErr = FSpCreate(theFile, kImageFileCreator, kQTFileTypeJPEG, 0); |
if (myErr == noErr) |
myErr = FSpOpenDF(theFile, fsRdWrPerm, &myRefNum); |
if (myErr == noErr) |
myErr = SetFPos(myRefNum, fsFromStart, 0); |
if (myErr == noErr) { |
ICMFlushProcRecordPtr myFlushProcPtr = NULL; |
#if USE_FLUSH_PROC |
myFlushProc.flushProc = NewICMFlushProc(QTGraphImp_DataUnloadProc); |
myFlushProc.flushRefCon = myRefNum; |
myFlushProcPtr = &myFlushProc; |
#else |
myFlushProcPtr = NULL; |
#endif |
// compress the image |
myErr = FCompressImage( myPixMap, |
&myRect, |
myDepth, |
codecNormalQuality, |
myCodec, |
anyCodec, |
myCTab, |
codecFlagWasCompressed, |
kBufferSize, |
myFlushProcPtr, |
NULL, |
myDesc, |
*myData); |
#if !USE_FLUSH_PROC |
if (myErr == noErr) |
myErr = FSWrite(myRefNum, &(**myDesc).dataSize, *myData); |
#endif |
if (myErr == noErr) |
myErr = SetFPos(myRefNum, fsFromStart, (**myDesc).dataSize); |
if (myErr == noErr) |
myErr = SetEOF(myRefNum, (**myDesc).dataSize); |
if (myErr == noErr) |
myErr = FSClose(myRefNum); |
HUnlock(myData); |
DisposeHandle(myData); |
#if USE_FLUSH_PROC |
DisposeRoutineDescriptor(myFlushProc.flushProc); |
#endif |
} |
} |
} |
UnlockPixels(myPixMap); |
bail: |
if (myDesc != NULL) |
DisposeHandle((Handle)myDesc); |
} |
////////// |
// |
// QTGraphImp_DataUnloadProc |
// A data unloading procedure: write the compressed data to disk. |
// |
// The theRefCon parameter is assumed to be a file reference number of an open file. |
// |
////////// |
PASCAL_RTN OSErr QTGraphImp_DataUnloadProc (Ptr theData, long theBytesNeeded, long theRefCon) |
{ |
OSErr myErr = noErr; |
if (theData == NULL) { |
// if data is NULL, set a new position in the file from the current mark, offset by bytesNeeded |
myErr = SetFPos(theRefCon, fsFromMark, theBytesNeeded); |
} else { |
// otherwise, write the specified data to disk |
myErr = FSWrite(theRefCon, &theBytesNeeded, theData); |
} |
return(myErr); |
} |
////////// |
// |
// QTGraphImp_ExportGWorldToFile |
// Save the image in a graphics world to the specified file. |
// |
// Use this function when you've got an image that you want to export to a file |
// but that image wasn't read in from a file (in which case you could just use |
// the GetGraphicsImporterForFile function to open an appropriate graphics importer). |
// |
// Based on the function ExportGWorldToFile in Dispatch 14 from the Ice Floe. |
// |
////////// |
OSErr QTGraphImp_ExportGWorldToFile (GWorldPtr theWorld, FSSpec *theFile, OSType theType) |
{ |
PicHandle myPicture = NULL; |
PixMapHandle myPixMap = NULL; |
GraphicsImportComponent myImporter = NULL; |
Handle myHandle = NULL; |
CGrafPtr mySavedGW; |
GDHandle mySavedGD; |
Rect myRect; |
OSErr myErr = noErr; |
// save the current graphics world, and set the specified graphics world as current |
GetGWorld(&mySavedGW, &mySavedGD); |
SetGWorld(theWorld, NULL); |
mySrcPixMap = GetGWorldPixMap(theWorld); |
#if TARGET_OS_MAC |
GetPortBounds(theWorld, &myRect); |
#endif |
#if TARGET_OS_WIN32 |
myRect = theWorld->portRect; |
#endif |
// capture the contents of the specified graphics world in a picture handle |
myPicture = OpenPicture(&((GrafPtr)theWorld)->portRect); |
CopyBits( (BitMapPtr)*myPixMap, |
(BitMapPtr)*myPixMap, |
&myRect, |
&myRect, |
srcCopy, |
NULL); |
ClosePicture(); |
// convert the picture handle into a handle-based PICT file by adding a 512-byte header to the start; |
// picture files are just like picture handles, except that they have an extra 512-byte header at the |
// front; any data in this header is usually ignored but it must exist, for historical reasons |
myHandle = NewHandleClear(512); |
myErr = MemError(); |
if (myErr != noErr) |
goto bail; |
myErr = HandAndHand((Handle)myPicture, myHandle); |
if (myErr != noErr) |
goto bail; |
// open an instance of the picture file graphics importer |
myErr = OpenADefaultComponent(GraphicsImporterComponentType, kQTFileTypePicture, &myImporter); |
if (myErr != noErr) |
goto bail; |
myErr = GraphicsImportSetDataHandle(myImporter, myHandle); |
if (myErr != noErr) |
goto bail; |
// export the image to a file |
myErr = GraphicsImportExportImageFile(myImporter, theType, kImageFileCreator, theFile, smSystemScript); |
bail: |
// restore the original graphics world |
SetGWorld(mySavedGW, mySavedGD); |
if (myPicture != NULL) |
KillPicture(myPicture); |
if (myImporter != NULL) |
CloseComponent(myImporter); |
if (myHandle != NULL) |
DisposeHandle(myHandle); |
return(myErr); |
} |
////////// |
// |
// QTGraphImp_GetAvailableExportTypes |
// Get a list of the available image export file types. |
// |
// Based on a function in Dispatch 14 from the Ice Floe. |
// |
////////// |
OSErr QTGraphImp_GetAvailableExportTypes (GraphicsImportComponent theImporter) |
{ |
QTAtomContainer myContainer = NULL; |
short myCount, myIndex; |
OSErr myErr = noErr; |
// get an atom container that contains one or more kGraphicsExportGroup atoms; |
// each export group atom represents a single export format and has child atoms that indicate |
// the file type (kGraphicsExportFileType), a human-readable name (kGraphicsExportDescription), |
// a file extension (kGraphicsExportExtension) and a MIME type (kGraphicsExportMIMEType) |
myErr = GraphicsImportGetExportImageTypeList(theImporter, &myContainer); |
if (myErr != noErr) |
goto bail; |
myCount = QTCountChildrenOfType(myContainer, kParentAtomIsContainer, kGraphicsExportGroup); |
for (myIndex = 1; myIndex <= myCount; myIndex++) { |
QTAtom myGroupAtom; |
myGroupAtom = QTFindChildByIndex(myContainer, kParentAtomIsContainer, kGraphicsExportGroup, myIndex, NULL); |
if (myGroupAtom != 0) { |
QTAtom myTypeAtom; |
myTypeAtom = QTFindChildByIndex(myContainer, myGroupAtom, kGraphicsExportFileType, 1, NULL); |
if (myTypeAtom != 0) { |
OSType myType; |
myErr = QTCopyAtomDataToPtr(myContainer, myTypeAtom, false, sizeof(myType), &myType, NULL); |
// the data in QT atoms is always big-endian, so convert the file type to native format |
myType = EndianU32_BtoN(myType); |
// at this point, you probably want to do something interesting with the file type, eh? |
// this is left as an exercise for the reader |
} else { |
myErr = cannotFindAtomErr; |
} |
} |
} |
bail: |
if (myContainer != NULL) |
QTDisposeAtomContainer(myContainer); |
return(myErr); |
} |
////////// |
// |
// QTGraphImp_ExportImageFile |
// Let the user select a disk file, then export the current picture into that file. |
// |
////////// |
OSErr QTGraphImp_ExportImageFile (GraphicsImportComponent theImporter) |
{ |
OSType myType; |
FSSpec myFSSpec; |
OSErr myErr = noErr; |
myErr = GraphicsImportDoExportImageFileDialog( |
theImporter, |
NULL, // no default name for the file |
NULL, // use the default prompt in the dialog box |
NULL, // no modal dialog filter procedure |
&myType, // return the type of the selected file |
&myFSSpec, // return the name (etc.) of the selected file |
NULL); // don't return the script code |
return(myErr); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14