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.
EI_GraphicsImport/EI_GraphicsImport.c
/*  | 
File: EI_GraphicsImport.c  | 
Description: QuickTime graphics importer component  | 
Author: QuickTime Engineering  | 
Copyright: © Copyright 1999-2003 Apple Computer, Inc. All rights reserved.  | 
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.  | 
                ("Apple") in consideration of your agreement to the following terms, and your | 
use, installation, modification or redistribution of this Apple software  | 
constitutes acceptance of these terms. If you do not agree with these terms,  | 
please do not use, install, modify or redistribute this Apple software.  | 
In consideration of your agreement to abide by the following terms, and subject  | 
to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs  | 
copyrights in this original Apple software (the "Apple Software"), to use,  | 
reproduce, modify and redistribute the Apple Software, with or without  | 
modifications, in source and/or binary forms; provided that if you redistribute  | 
the Apple Software in its entirety and without modifications, you must retain  | 
this notice and the following text and disclaimers in all such redistributions of  | 
the Apple Software. Neither the name, trademarks, service marks or logos of  | 
Apple Computer, Inc. may be used to endorse or promote products derived from the  | 
Apple Software without specific prior written permission from Apple. Except as  | 
expressly stated in this notice, no other rights or licenses, express or implied,  | 
are granted by Apple herein, including but not limited to any patent rights that  | 
may be infringed by your derivative works or by other works in which the Apple  | 
Software may be incorporated.  | 
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO  | 
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED  | 
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR  | 
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN  | 
COMBINATION WITH YOUR PRODUCTS.  | 
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR  | 
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE  | 
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)  | 
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION  | 
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT  | 
(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN  | 
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  | 
Change History (most recent first):  | 
<2> 12/09/00 ERA updated for X  | 
<1> 11/28/99 QTE first file  | 
*/  | 
#if TARGET_OS_WIN32  | 
#include "EIComponentWindowsPrefix.h"  | 
#endif  | 
#if __MACH__  | 
#include <Carbon/Carbon.h>  | 
#include <QuickTime/QuickTime.h>  | 
#else  | 
#include <Endian.h>  | 
#include <ImageCompression.h>  | 
#include <Movies.h>  | 
#include <Script.h>  | 
#include <TextUtils.h>  | 
#endif  | 
#include "EI_Image.h"  | 
#include "EI_MakeImageDescription.h"  | 
#include "EI_GraphicsImportVersion.h"  | 
// Component globals  | 
typedef struct { | 
ComponentInstance self;  | 
ComponentInstance parent;  | 
ComponentInstance delegateComponent;  | 
} EI_GraphicsImportGlobalsRecord, *EI_GraphicsImportGlobals;  | 
// Setup required for ComponentDispatchHelper.c  | 
#define GRAPHICSIMPORT_BASENAME() EI_GraphicsImport  | 
#define GRAPHICSIMPORT_GLOBALS() EI_GraphicsImportGlobals storage  | 
#define CALLCOMPONENT_BASENAME() GRAPHICSIMPORT_BASENAME()  | 
#define CALLCOMPONENT_GLOBALS() GRAPHICSIMPORT_GLOBALS()  | 
#define COMPONENT_UPP_PREFIX() uppGraphicsImport  | 
#define COMPONENT_DISPATCH_FILE "EI_GraphicsImportDispatch.h"  | 
#define COMPONENT_SELECT_PREFIX() kGraphicsImport  | 
#define GET_DELEGATE_COMPONENT() (storage->delegateComponent)  | 
#if __MACH__  | 
#include <CoreServices/Components.k.h>  | 
#include <QuickTime/ImageCompression.k.h>  | 
#include <QuickTime/ComponentDispatchHelper.c>  | 
#else  | 
#include <Components.k.h>  | 
#include <ImageCompression.k.h>  | 
#include <ComponentDispatchHelper.c>  | 
#endif  | 
// Component Open Request - Required  | 
pascal ComponentResult EI_GraphicsImportOpen(EI_GraphicsImportGlobals store, ComponentInstance self)  | 
{ | 
ComponentResult err = noErr;  | 
// Allocate memory for our globals, set them up and inform the component manager that we've done so  | 
store = (EI_GraphicsImportGlobals)NewPtrClear(sizeof(EI_GraphicsImportGlobalsRecord));  | 
if (err = MemError()) goto bail;  | 
store->self = self;  | 
store->parent = self;  | 
SetComponentInstanceStorage(self, (Handle)store);  | 
// Open and target an instance of the base graphic importer as we delegate  | 
// most of our calls to the base importer instance  | 
err = OpenADefaultComponent(GraphicsImporterComponentType, GraphicsImporterComponentType, &store->delegateComponent);  | 
if (err) goto bail;  | 
err = ComponentSetTarget(store->delegateComponent, self);  | 
if (err) goto bail;  | 
bail:  | 
return err;  | 
}  | 
// Component Close Request - Required  | 
pascal ComponentResult EI_GraphicsImportClose(EI_GraphicsImportGlobals store, ComponentInstance self)  | 
{ | 
#pragma unused(self)  | 
// Make sure to close the base component and dealocate our storage  | 
    if (store) { | 
if (store->delegateComponent)  | 
CloseComponent(store->delegateComponent);  | 
DisposePtr((Ptr)store);  | 
}  | 
return noErr;  | 
}  | 
// Component Version Request - Required  | 
pascal ComponentResult EI_GraphicsImportVersion(EI_GraphicsImportGlobals store)  | 
{ | 
#pragma unused(store)  | 
#if TARGET_CPU_68K || TARGET_OS_WIN32  | 
return kEI_GraphicsImportVersion;  | 
#else  | 
return kEI_GraphicsImportVersionPPC;  | 
#endif  | 
}  | 
// Component Target Request  | 
// Allows another component to "target" you i.e., you call another component whenever  | 
// you would call yourself (as a result of your component being used by another component)  | 
pascal ComponentResult EI_GraphicsImportTarget(EI_GraphicsImportGlobals store, ComponentInstance target)  | 
{ | 
store->parent = target;  | 
return noErr;  | 
}  | 
#pragma mark-  | 
// GraphicsImportGetImageDescription  | 
// Examine the image file and construct an image description for it.  | 
// The base importer uses this image description to respond to other calls such as GraphicsImportGetNaturalBounds and  | 
// GraphicsImportDraw. In the case of GraphicsImportDraw, the image description is passed to the Image Compression  | 
// Manager, so the cType field must identify a codec that will be able to draw the image. If a graphics importer needs to pass  | 
// extra information that the codec will need at PreDecompress time, it can pass it in an image description extension.  | 
pascal ComponentResult EI_GraphicsImportGetImageDescription(EI_GraphicsImportGlobals store, ImageDescriptionHandle *descOut)  | 
{ | 
ComponentResult err = noErr;  | 
ImageFrame frame;  | 
unsigned long offset, size;  | 
short colorCount;  | 
Ptr colors = NULL;  | 
if (!descOut)  | 
return paramErr;  | 
// Get the offset and size of the image data  | 
err = GraphicsImportGetDataOffsetAndSize(store->parent, &offset, &size);  | 
if (err) goto bail;  | 
// Read some data, in this case an ImageFrame (this is specific to the Electric Image Format)  | 
err = GraphicsImportReadData(store->parent, &frame, offset, sizeof(frame));  | 
if (err) goto bail;  | 
// framePalettes contains the number of entries in the color table  | 
colorCount = EndianU16_BtoN(frame.framePalettes);  | 
// Alocate some storage for the color table and get it  | 
colors = NewPtr(3 * colorCount);  | 
if (err = MemError()) goto bail;  | 
err = GraphicsImportReadData(store->parent, colors, offset + sizeof(frame), 3 * colorCount);  | 
if (err) goto bail;  | 
// Create the Image Description  | 
err = EI_MakeImageDescription(&frame, colorCount, (UInt8 *)colors, descOut);  | 
if (err) goto bail;  | 
bail:  | 
if (colors)  | 
DisposePtr(colors);  | 
return err;  | 
}  | 
// GraphicsImportGetDataOffsetAndSize  | 
// Returns the offset and size of the compressed image data within a file.  | 
// Sometimes, the data to be passed to the image decompressor is only a portion of the file. In these cases, implement  | 
// the GraphicsImportGetDataOffsetAndSize function to indicate the byte range to send to the image decompressor.  | 
// It is often useful for this call to first call the base importer's implementation to find out the size of the input data stream.  | 
pascal ComponentResult EI_GraphicsImportGetDataOffsetAndSize(EI_GraphicsImportGlobals store, unsigned long *offsetOut, unsigned long *sizeOut)  | 
{ | 
ComponentResult err = noErr;  | 
ImageHeader header;  | 
ImageFrame frame;  | 
unsigned long offset, size;  | 
// Call the base importer first  | 
err = GraphicsImportGetDataOffsetAndSize(store->delegateComponent, &offset, &size);  | 
if (err) goto bail;  | 
// Read some data  | 
err = GraphicsImportReadData(store->parent, &header, offset, sizeof(header));  | 
if (err) goto bail;  | 
// If we don't like what we see bail!  | 
    if ((EndianU16_BtoN(header.imageVersion) != 5) || (EndianU32_BtoN(header.imageFrames) < 1)) { | 
err = codecBadDataErr;  | 
goto bail;  | 
}  | 
// Read some more data  | 
err = GraphicsImportReadData(store->parent, &frame, offset + sizeof(header), sizeof(frame));  | 
if (err) goto bail;  | 
// Set the correct offset into the image and adjust the size appropriately  | 
if (offsetOut) *offsetOut = offset + sizeof(ImageHeader);  | 
if (sizeOut) *sizeOut = sizeof(ImageFrame) + (EndianU16_BtoN(frame.framePalettes) * 3) + EndianU32_BtoN(frame.frameSize);  | 
bail:  | 
return err;  | 
}  | 
// GraphicsImportValidate  | 
// Attempt to ascertain quickly whether a file matches the importer's format.  | 
// This is especially useful for formats which start with identifying codes or "magic numbers" (such as PNG and TIFF)  | 
// in situations where image files do not have correct file types or suffixes. In situations like this, the Image Compression  | 
// Manager may ask many graphics importers in turn to validate until it finds one that accepts the file, so it is important that  | 
// GraphicsImportValidate calls not be too slow. Importers that implement the GraphicsImportValidate call  | 
// should have the canMovieImportValidateFile bit set in their component flags.  | 
pascal ComponentResult EI_GraphicsImportValidate(EI_GraphicsImportGlobals store, Boolean *valid)  | 
{ | 
ComponentResult err = noErr;  | 
unsigned char header[2];  | 
*valid = false;  | 
err = GraphicsImportReadData(store->parent, &header[0], 0, 2);  | 
if (err) goto bail;  | 
// If your image format has a "magic number" at the start, this is where you should look for it.  | 
// Electric Image files don't have a magic number, but they do have a version code, which should  | 
// be a big-endian two-byte integer "5". So we'll check that.  | 
if( ( 0 == header[0] )  | 
&& ( 5 == header[1] ) )  | 
*valid = true;  | 
bail:  | 
return err;  | 
}  | 
// GraphicsImportGetMetaData  | 
// Extract metadata from an image file and add it to a user data structure.  | 
// Note that userData must already be allocated. If the user data passed to GraphicsImportGetMetaData  | 
// belongs to a movie, track or media, then whatever metadata is extracted will be added to that movie, track or media.  | 
pascal ComponentResult EI_GraphicsImportGetMetaData(EI_GraphicsImportGlobals store, void *userData)  | 
{ | 
#pragma unused(store)  | 
ComponentResult err = noErr;  | 
Handle dataHandle = NULL;  | 
UserData userDataOut = (UserData)userData;  | 
// For the sake of example we'll return a fixed string as metadata.  | 
    char *theCString = { "File created with Electric Image" }; | 
#if !TARGET_API_MAC_CARBON  | 
StringPtr thePString = c2pstr(theCString);  | 
#else  | 
Str255 thePString;  | 
CopyCStringToPascal(theCString, thePString);  | 
#endif // TARGET_API_MAC_CARBON  | 
    if (NULL == userData) { | 
err = paramErr;  | 
goto bail;  | 
}  | 
dataHandle = NewHandle(0);  | 
    if (NULL == dataHandle) { | 
err = memFullErr;  | 
goto bail;  | 
}  | 
err = PtrAndHand(&thePString[1], dataHandle, thePString[0]);  | 
if (err) goto bail;  | 
err = AddUserDataText(userDataOut, dataHandle, kUserDataTextInformation, 1, langEnglish);  | 
bail:  | 
if (dataHandle)  | 
DisposeHandle(dataHandle);  | 
return err;  | 
}  | 
// GraphicsImportGetMIMETypeList  | 
// Returns a list of MIME types supported by the graphics import component.  | 
// To indicate that your graphics import component supports this function, set the hasMovieImportMIMEList flag in the  | 
// componentFlags field of the component description record.  | 
pascal ComponentResult EI_GraphicsImportGetMIMETypeList(EI_GraphicsImportGlobals store, void *qtAtomContainerPtr)  | 
{ | 
// Note that GetComponentResource is only available in QuickTime 3.0 or later.  | 
// However, it's safe to call it here because GetMIMETypeList is only defined in QuickTime 3.0 or later.  | 
    return GetComponentResource((Component)store->self, FOUR_CHAR_CODE('mime'), 128, (Handle *)qtAtomContainerPtr); | 
}  | 
#pragma mark-  | 
// When building the *Application Version Only* make our component available for use by applications (or other clients).  | 
// Once the Component Manager has registered a component, applications can find and open the component using standard  | 
// Component Manager routines.  | 
#if !STAND_ALONE && !TARGET_OS_WIN32  | 
void EI_GraphicsImporterRegister(void);  | 
void EI_GraphicsImporterRegister(void)  | 
{ | 
ComponentDescription foo;  | 
#if !TARGET_API_MAC_CARBON  | 
ComponentRoutineUPP componentEntryPoint = NewComponentRoutineProc(EI_GraphicsImportComponentDispatch);  | 
#else  | 
ComponentRoutineUPP componentEntryPoint = NewComponentRoutineUPP((ComponentRoutineProcPtr)EI_GraphicsImportComponentDispatch);  | 
#endif  | 
foo.componentType = GraphicsImporterComponentType;  | 
    foo.componentSubType = FOUR_CHAR_CODE('EIDI'); | 
foo.componentManufacturer = kAppleManufacturer;  | 
foo.componentFlags = 0;  | 
foo.componentFlagsMask = 0;  | 
RegisterComponent(&foo, componentEntryPoint, registerComponentGlobal, NULL, NULL, NULL);  | 
}  | 
#endif // !STAND_ALONE && !TARGET_OS_WIN32  | 
Copyright © 2004 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2004-01-23